diff options
author | Sergej Reich <sergej.reich@googlemail.com> | 2013-10-13 15:41:41 +0400 |
---|---|---|
committer | Sergej Reich <sergej.reich@googlemail.com> | 2013-10-13 15:41:41 +0400 |
commit | 5d5176095e82b34499e15d74f1fb76d56f4d9508 (patch) | |
tree | dd8c61741160804873601f6b6350661132ac1b2f /source | |
parent | bcbf976b48762c2f25df470c6d13a124bc868a66 (diff) | |
parent | 42ac7164e30dcca565253aa265201aad497e5360 (diff) |
svn merge -r60422:60726 ^/trunk/blender
Diffstat (limited to 'source')
318 files changed, 5352 insertions, 2709 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 7e327028a01..0d309523daf 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -117,6 +117,10 @@ if(WITH_IMAGE_OPENEXR) add_subdirectory(imbuf/intern/openexr) endif() +if(WITH_OPENIMAGEIO) + add_subdirectory(imbuf/intern/oiio) +endif() + if(WITH_IMAGE_DDS) add_subdirectory(imbuf/intern/dds) endif() diff --git a/source/blender/SConscript b/source/blender/SConscript index 66d54961131..de052f24c33 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -49,6 +49,9 @@ makesrna = SConscript('makesrna/SConscript') if env['WITH_BF_PYTHON']: SConscript(['python/SConscript']) +if env['WITH_BF_OIIO']: + SConscript (['imbuf/intern/oiio/SConscript']) + if env['WITH_BF_DDS']: SConscript (['imbuf/intern/dds/SConscript']) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index d485632955d..698098d28c3 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -188,6 +188,10 @@ struct bPoseChannel *BKE_pose_channel_active(struct Object *ob); */ struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name); +#ifndef NDEBUG +bool BKE_pose_channels_is_valid(const struct bPose *pose); +#endif + /* Copy the data from the action-pose (src) into the pose */ void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index dd150ba6a63..f0f6b5a2319 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -112,6 +112,9 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, st /* Fix all the paths for the entire database... */ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const char *oldName, const char *newName); +/* Fix the path after removing elements that are not ID (e.g., node) */ +void BKE_animdata_fix_paths_remove(struct ID *id, const char *path); + /* -------------------------------------- */ /* Move animation data from src to destination if it's paths are based on basepaths */ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f434bcf3cad..5b32e7229d5 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,15 +41,15 @@ extern "C" { /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 268 -#define BLENDER_SUBVERSION 5 +#define BLENDER_VERSION 269 +#define BLENDER_SUBVERSION 1 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 #define BLENDER_MINSUBVERSION 0 /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ -#define BLENDER_VERSION_CHAR a +#define BLENDER_VERSION_CHAR /* alpha/beta/rc/release, docs use this */ #define BLENDER_VERSION_CYCLE alpha diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index ac114a62de6..07116979eab 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -155,6 +155,7 @@ void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt); void BKE_nurb_handles_calc(struct Nurb *nu); void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag); -void BKE_nurb_handles_test(struct Nurb *nu); +void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle); +void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles); #endif /* __BKE_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index a43a243106d..435cad17e57 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -78,8 +78,12 @@ void defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, const i void defvert_normalize(struct MDeformVert *dvert); void defvert_normalize_subset(struct MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_tot); -void defvert_normalize_lock_single(struct MDeformVert *dvert, const int def_nr_lock); -void defvert_normalize_lock_map(struct MDeformVert *dvert, const bool *lock_flags, const int defbase_tot); +void defvert_normalize_lock_single(struct MDeformVert *dvert, + const bool *vgroup_subset, const int vgroup_tot, + const int def_nr_lock); +void defvert_normalize_lock_map(struct MDeformVert *dvert, + const bool *vgroup_subset, const int vgroup_tot, + const bool *lock_flags, const int defbase_tot); /* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only * used with defgroups currently */ diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index 64a6811bf51..c31dd745911 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -229,12 +229,13 @@ short calc_fcurve_bounds(struct FCurve *fcu, float *xmin, float *xmax, float *ym short fcurve_are_keyframes_usable(struct FCurve *fcu); /* Can keyframes be added to F-Curve? */ -short fcurve_is_keyframable(struct FCurve *fcu); +bool fcurve_is_keyframable(struct FCurve *fcu); +bool BKE_fcurve_is_protected(struct FCurve *fcu); /* -------- Curve Sanity -------- */ void calchandles_fcurve(struct FCurve *fcu); -void testhandles_fcurve(struct FCurve *fcu, const short use_handle); +void testhandles_fcurve(struct FCurve *fcu, const bool use_handle); void sort_time_fcurve(struct FCurve *fcu); short test_time_fcurve(struct FCurve *fcu); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 9e80a93fd63..a3d1eb74211 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -169,9 +169,9 @@ void BKE_mesh_calc_normals_tessface( struct MFace *mfaces, int numFaces, float (*faceNors_r)[3]); void BKE_mesh_normals_loop_split( - struct MVert *mverts, int numVerts, struct MEdge *medges, int numEdges, - struct MLoop *mloops, float (*r_loopnors)[3], int numLoops, - struct MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle); + struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges, + struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops, + struct MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle); void BKE_mesh_calc_poly_normal( struct MPoly *mpoly, struct MLoop *loopstart, diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 7f19a867093..7cc8c7290f7 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -131,8 +131,6 @@ typedef struct bNodeSocketType { int type, subtype; } bNodeSocketType; -typedef void (*NodeSocketDrawFunction)(struct bContext *C, struct uiLayout *layout, struct PointerRNA *ptr, struct PointerRNA *node_ptr); - typedef void *(*NodeInitExecFunction)(struct bNodeExecContext *context, struct bNode *node, bNodeInstanceKey key); typedef void (*NodeFreeExecFunction)(struct bNode *node, void *nodedata); typedef void (*NodeExecFunction)(void *data, int thread, struct bNode *, struct bNodeExecData *execdata, struct bNodeStack **in, struct bNodeStack **out); @@ -162,24 +160,19 @@ typedef struct bNodeType { char storagename[64]; /* struct name for DNA */ - /// Main draw function for the node. - void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, + /* Main draw function for the node */ + void (*draw_nodetype)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); - /// Updates the node geometry attributes according to internal state before actual drawing. - void (*drawupdatefunc)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); - /// Draw the option buttons on the node. - void (*uifunc)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr); - /// Additional parameters in the side panel. - void (*uifuncbut)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr); - /// Additional drawing on backdrop. - void (*uibackdropfunc)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y); - - /// Draw a node socket. Default draws the input value button. - /* XXX deprecated, only used for the OutputFile node, - * should be removed at some point. - */ - NodeSocketDrawFunction drawinputfunc; - NodeSocketDrawFunction drawoutputfunc; + /* Updates the node geometry attributes according to internal state before actual drawing */ + void (*draw_nodetype_prepare)(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); + + /* Draw the option buttons on the node */ + void (*draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr); + /* Additional parameters in the side panel */ + void (*draw_buttons_ex)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr); + + /* Additional drawing on backdrop */ + void (*draw_backdrop)(struct SpaceNode *snode, struct ImBuf *backdrop, struct bNode *node, int x, int y); /// Optional custom label function for the node header. const char *(*labelfunc)(struct bNode *); diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 653f2a42675..ab8b8b29915 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -72,11 +72,11 @@ struct DerivedMesh *subsurf_make_derived_from_derived( void subsurf_calculate_limit_positions(struct Mesh *me, float (*positions_r)[3]); /* get gridsize from 'level', level must be greater than zero */ -int ccg_gridsize(int level); +int BKE_ccg_gridsize(int level); /* x/y grid coordinates at 'low_level' can be multiplied by the result * of this function to convert to grid coordinates at 'high_level' */ -int ccg_factor(int low_level, int high_level); +int BKE_ccg_factor(int low_level, int high_level); void subsurf_copy_grid_hidden(struct DerivedMesh *dm, const struct MPoly *mpoly, diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 3c3ac61a3cb..07dbc1d6065 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -101,6 +101,9 @@ if env['WITH_BF_SDL']: incs += ' ' + env['BF_SDL_INC'] defs.append('WITH_SDL') +if env['WITH_BF_OIIO']: + defs.append('WITH_OPENIMAGEIO') + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index d4454a95a2d..ffb92788d4d 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -248,7 +248,7 @@ static CCGAllocatorIFC *_getStandardAllocatorIFC(void) /***/ -int ccg_gridsize(int level) +BLI_INLINE int ccg_gridsize(int level) { BLI_assert(level > 0); BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1); @@ -256,7 +256,12 @@ int ccg_gridsize(int level) return (1 << (level - 1)) + 1; } -int ccg_factor(int low_level, int high_level) +int BKE_ccg_gridsize(int level) +{ + return ccg_gridsize(level); +} + +int BKE_ccg_factor(int low_level, int high_level) { BLI_assert(low_level > 0 && high_level > 0); BLI_assert(low_level <= high_level); @@ -264,7 +269,7 @@ int ccg_factor(int low_level, int high_level) return 1 << (high_level - low_level); } -static int ccg_edgesize(int level) +BLI_INLINE int ccg_edgesize(int level) { BLI_assert(level > 0); BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1); @@ -272,7 +277,7 @@ static int ccg_edgesize(int level) return 1 + (1 << level); } -static int ccg_spacing(int high_level, int low_level) +BLI_INLINE int ccg_spacing(int high_level, int low_level) { BLI_assert(high_level > 0 && low_level > 0); BLI_assert(high_level >= low_level); @@ -281,7 +286,7 @@ static int ccg_spacing(int high_level, int low_level) return 1 << (high_level - low_level); } -static int ccg_edgebase(int level) +BLI_INLINE int ccg_edgebase(int level) { BLI_assert(level > 0); BLI_assert(level <= CCGSUBSURF_LEVEL_MAX + 1); @@ -742,7 +747,7 @@ BLI_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int le byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return (float *) &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing) + normalDataOffset]; } -static int _face_getVertIndex(CCGFace *f, CCGVert *v) +BLI_INLINE int _face_getVertIndex(CCGFace *f, CCGVert *v) { int i; for (i = 0; i < f->numVerts; i++) @@ -750,7 +755,7 @@ static int _face_getVertIndex(CCGFace *f, CCGVert *v) return i; return -1; } -static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e) +BLI_INLINE int _face_getEdgeIndex(CCGFace *f, CCGEdge *e) { int i; for (i = 0; i < f->numVerts; i++) diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 644fefad3b0..b0644da4598 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -489,6 +489,22 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name) return chan; } +#ifndef NDEBUG +bool BKE_pose_channels_is_valid(const bPose *pose) +{ + if (pose->chanhash) { + bPoseChannel *pchan; + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (BLI_ghash_lookup(pose->chanhash, pchan->name) != pchan) { + return false; + } + } + } + + return true; +} + +#endif /* Find the active posechannel for an object (we can't just use pose, as layer info is in armature) */ bPoseChannel *BKE_pose_channel_active(Object *ob) { diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 5c3f67d8959..225be335c6d 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -530,7 +530,7 @@ void calc_curvepath(Object *ob, ListBase *nurbs) path->len = nu->resolu * SEGMENTSU(nu); } - dist = (float *)MEM_mallocN((tot + 1) * 4, "calcpathdist"); + dist = (float *)MEM_mallocN(sizeof(float) * (tot + 1), "calcpathdist"); /* all lengths in *dist */ bevp = bevpfirst = (BevPoint *)(bl + 1); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 8e697ad4ef3..74578266c63 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -42,6 +42,7 @@ #include "BLI_blenlib.h" #include "BLI_alloca.h" #include "BLI_dynstr.h" +#include "BLI_listbase.h" #include "BLF_translation.h" @@ -759,6 +760,76 @@ void BKE_animdata_fix_paths_rename(ID *owner_id, AnimData *adt, ID *ref_id, cons MEM_freeN(newN); } +/* *************************** */ +/* remove of individual paths */ + +/* Check RNA-Paths for a list of F-Curves */ +static void fcurves_path_remove_fix(const char *prefix, ListBase *curves) +{ + FCurve *fcu, *fcn; + if (!prefix) return; + + /* we need to check every curve... */ + for (fcu = curves->first; fcu; fcu = fcn) { + fcn = fcu->next; + + if (fcu->rna_path) { + if (STRPREFIX(fcu->rna_path, prefix)) { + BLI_remlink(curves, fcu); + free_fcurve(fcu); + } + } + } +} + +/* Check RNA-Paths for a list of F-Curves */ +static void nlastrips_path_remove_fix(const char *prefix, ListBase *strips) +{ + NlaStrip *strip; + + /* recursively check strips, fixing only actions... */ + for (strip = strips->first; strip; strip = strip->next) { + + /* fix strip's action */ + if (strip->act) + fcurves_path_remove_fix(prefix, &strip->act->curves); + + /* check sub-strips (if metas) */ + nlastrips_path_remove_fix(prefix, &strip->strips); + } +} + +void BKE_animdata_fix_paths_remove(ID *id, const char *prefix) +{ + /* Only some ID-blocks have this info for now, so we cast the + * types that do to be of type IdAdtTemplate + */ + NlaTrack *nlt; + + if (id_type_can_have_animdata(id)) { + IdAdtTemplate *iat = (IdAdtTemplate *)id; + AnimData *adt = iat->adt; + + /* check if there's any AnimData to start with */ + if (adt) { + + /* free fcurves */ + if (adt->action) + fcurves_path_remove_fix(prefix, &adt->action->curves); + + if (adt->tmpact) + fcurves_path_remove_fix(prefix, &adt->tmpact->curves); + + /* free drivers - stored as a list of F-Curves */ + fcurves_path_remove_fix(prefix, &adt->drivers); + + /* NLA Data - Animation Data for Strips */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) + nlastrips_path_remove_fix(prefix, &nlt->strips); + } + } +} + /* Whole Database Ops -------------------------------------------- */ /* apply the given callback function on all data in main database */ diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 5b66b8b4cd4..370dbc62ef8 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -355,7 +355,7 @@ float nearest_point_in_tri_surface(const float v0[3], const float v1[3], const f /* - * BVH from meshs callbacks + * BVH from meshes callbacks */ /* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces. diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 7f94f365925..578fa5d348d 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -972,9 +972,6 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM if (ibuf->rect_float) cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - /* persistent draw */ - hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */ - for (i = 0; i < 256; i++) { x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f); y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 02b35794d28..e255732d3fb 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -3102,46 +3102,67 @@ void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt) } } -void BKE_nurb_handles_test(Nurb *nu) -{ - /* use when something has changed with handles. - * it treats all BezTriples with the following rules: - * PHASE 1: do types have to be altered? - * Auto handles: become aligned when selection status is NOT(000 || 111) - * Vector handles: become 'nothing' when (one half selected AND other not) - * PHASE 2: recalculate handles - */ - BezTriple *bezt; - short flag, a; +/** + * Use when something has changed handle positions. + * + * The caller needs to recalculate handles. + */ +void BKE_nurb_bezt_handle_test(BezTriple *bezt, const bool use_handle) +{ + short flag = 0; - if (nu->type != CU_BEZIER) return; +#define SEL_F1 (1 << 0) +#define SEL_F2 (1 << 1) +#define SEL_F3 (1 << 2) - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - flag = 0; - if (bezt->f1 & SELECT) - flag++; - if (bezt->f2 & SELECT) - flag += 2; - if (bezt->f3 & SELECT) - flag += 4; + if (use_handle) { + if (bezt->f1 & SELECT) flag |= SEL_F1; + if (bezt->f2 & SELECT) flag |= SEL_F2; + if (bezt->f3 & SELECT) flag |= SEL_F3; + } + else { + flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0; + } - if (!(flag == 0 || flag == 7) ) { - if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) { /* auto */ - bezt->h1 = HD_ALIGN; - } - if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { /* auto */ - bezt->h2 = HD_ALIGN; - } + /* check for partial selection */ + if (!ELEM(flag, 0, SEL_F1 | SEL_F2 | SEL_F3)) { + if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) { + bezt->h1 = HD_ALIGN; + } + if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { + bezt->h2 = HD_ALIGN; + } - if (bezt->h1 == HD_VECT) { /* vector */ - if (flag < 4) bezt->h1 = 0; + if (bezt->h1 == HD_VECT) { + if ((!(flag & SEL_F1)) != (!(flag & SEL_F2))) { + bezt->h1 = HD_FREE; } - if (bezt->h2 == HD_VECT) { /* vector */ - if (flag > 3) bezt->h2 = 0; + } + if (bezt->h2 == HD_VECT) { + if ((!(flag & SEL_F3)) != (!(flag & SEL_F2))) { + bezt->h2 = HD_FREE; } } + } + +#undef SEL_F1 +#undef SEL_F2 +#undef SEL_F3 + +} + +void BKE_nurb_handles_test(Nurb *nu, const bool use_handle) +{ + BezTriple *bezt; + short a; + + if (nu->type != CU_BEZIER) + return; + + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + BKE_nurb_bezt_handle_test(bezt, use_handle); bezt++; } @@ -3151,9 +3172,11 @@ void BKE_nurb_handles_test(Nurb *nu) void BKE_nurb_handles_autocalc(Nurb *nu, int flag) { /* checks handle coordinates and calculates type */ + const float eps = 0.0001f; + const float eps_sq = eps * eps; BezTriple *bezt2, *bezt1, *bezt0; - int i, align, leftsmall, rightsmall; + int i; if (nu == NULL || nu->bezt == NULL) return; @@ -3164,54 +3187,54 @@ void BKE_nurb_handles_autocalc(Nurb *nu, int flag) i = nu->pntsu; while (i--) { - align = leftsmall = rightsmall = 0; + bool align = false, leftsmall = false, rightsmall = false; /* left handle: */ if (flag == 0 || (bezt1->f1 & flag) ) { - bezt1->h1 = 0; + bezt1->h1 = HD_FREE; /* distance too short: vectorhandle */ - if (len_v3v3(bezt1->vec[1], bezt0->vec[1]) < 0.0001f) { + if (len_squared_v3v3(bezt1->vec[1], bezt0->vec[1]) < eps_sq) { bezt1->h1 = HD_VECT; - leftsmall = 1; + leftsmall = true; } else { /* aligned handle? */ - if (dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001f) { - align = 1; + if (dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < eps) { + align = true; bezt1->h1 = HD_ALIGN; } /* or vector handle? */ - if (dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001f) + if (dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < eps) bezt1->h1 = HD_VECT; } } /* right handle: */ if (flag == 0 || (bezt1->f3 & flag) ) { - bezt1->h2 = 0; + bezt1->h2 = HD_FREE; /* distance too short: vectorhandle */ - if (len_v3v3(bezt1->vec[1], bezt2->vec[1]) < 0.0001f) { + if (len_squared_v3v3(bezt1->vec[1], bezt2->vec[1]) < eps_sq) { bezt1->h2 = HD_VECT; - rightsmall = 1; + rightsmall = true; } else { /* aligned handle? */ if (align) bezt1->h2 = HD_ALIGN; /* or vector handle? */ - if (dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001f) + if (dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < eps) bezt1->h2 = HD_VECT; } } if (leftsmall && bezt1->h2 == HD_ALIGN) - bezt1->h2 = 0; + bezt1->h2 = HD_FREE; if (rightsmall && bezt1->h1 == HD_ALIGN) - bezt1->h1 = 0; + bezt1->h1 = HD_FREE; /* undesired combination: */ if (bezt1->h1 == HD_ALIGN && bezt1->h2 == HD_VECT) - bezt1->h1 = 0; + bezt1->h1 = HD_FREE; if (bezt1->h2 == HD_ALIGN && bezt1->h1 == HD_VECT) - bezt1->h2 = 0; + bezt1->h2 = HD_FREE; bezt0 = bezt1; bezt1 = bezt2; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 1521ec8467e..8a74f4719d5 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -1463,8 +1463,7 @@ int CustomData_get_named_layer_index(const CustomData *data, int type, const cha for (i = 0; i < data->totlayer; ++i) if (data->layers[i].type == type) - if ((!name && !data->layers[i].name) || - (strcmp(data->layers[i].name, name) == 0)) + if (strcmp(data->layers[i].name, name) == 0) return i; return -1; @@ -1970,10 +1969,10 @@ static void CustomData_copy_data_layer(const CustomData *source, CustomData *des dest_offset = dest_index * typeInfo->size; if (!src_data || !dest_data) { - if (src_data != NULL && dest_data != NULL) { + if (!(src_data == NULL && dest_data == NULL)) { printf("%s: warning null data for %s type (%p --> %p), skipping\n", - __func__, layerType_getName(source->layers[src_i].type), - (void *)src_data, (void *)dest_data); + __func__, layerType_getName(source->layers[src_i].type), + (void *)src_data, (void *)dest_data); } return; } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 882085aa5db..a183872552d 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -217,24 +217,35 @@ void defvert_remap(MDeformVert *dvert, int *map, const int map_len) void defvert_normalize_subset(MDeformVert *dvert, const bool *vgroup_subset, const int vgroup_tot) { - MDeformWeight *dw; - unsigned int i; - float tot_weight = 0.0f; - - for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if (dvert->totweight == 0) { + /* nothing */ + } + else if (dvert->totweight == 1) { + MDeformWeight *dw = dvert->dw; if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - tot_weight += dw->weight; + dw->weight = 1.0f; } } + else { + MDeformWeight *dw; + unsigned int i; + float tot_weight = 0.0f; - if (tot_weight > 0.0f) { - float scalar = 1.0f / tot_weight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - dw->weight *= scalar; - - /* in case of division errors with very low weights */ - CLAMP(dw->weight, 0.0f, 1.0f); + tot_weight += dw->weight; + } + } + + if (tot_weight > 0.0f) { + float scalar = 1.0f / tot_weight; + for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + dw->weight *= scalar; + + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } } } } @@ -242,7 +253,7 @@ void defvert_normalize_subset(MDeformVert *dvert, void defvert_normalize(MDeformVert *dvert) { - if (dvert->totweight <= 0) { + if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { @@ -269,14 +280,20 @@ void defvert_normalize(MDeformVert *dvert) } } -void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) +/* Same as defvert_normalize() if the locked vgroup is not a member of the subset */ +void defvert_normalize_lock_single(MDeformVert *dvert, + const bool *vgroup_subset, const int vgroup_tot, + const int def_nr_lock) { - if (dvert->totweight <= 0) { + if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { - if (def_nr_lock != 0) { - dvert->dw[0].weight = 1.0f; + MDeformWeight *dw = dvert->dw; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (def_nr_lock != 0) { + dw->weight = 1.0f; + } } } else { @@ -287,13 +304,15 @@ void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) float lock_iweight = 1.0f; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if (dw->def_nr != def_nr_lock) { - tot_weight += dw->weight; - } - else { - dw_lock = dw; - lock_iweight = (1.0f - dw_lock->weight); - CLAMP(lock_iweight, 0.0f, 1.0f); + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (dw->def_nr != def_nr_lock) { + tot_weight += dw->weight; + } + else { + dw_lock = dw; + lock_iweight = (1.0f - dw_lock->weight); + CLAMP(lock_iweight, 0.0f, 1.0f); + } } } @@ -302,25 +321,33 @@ void defvert_normalize_lock_single(MDeformVert *dvert, const int def_nr_lock) float scalar = (1.0f / tot_weight) * lock_iweight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if (dw != dw_lock) { - dw->weight *= scalar; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (dw != dw_lock) { + dw->weight *= scalar; - /* in case of division errors with very low weights */ - CLAMP(dw->weight, 0.0f, 1.0f); + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } } } } } } -void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, const int defbase_tot) +/* Same as defvert_normalize() if no locked vgroup is a member of the subset */ +void defvert_normalize_lock_map(MDeformVert *dvert, + const bool *vgroup_subset, const int vgroup_tot, + const bool *lock_flags, const int defbase_tot) { - if (dvert->totweight <= 0) { + if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { - if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { - dvert->dw[0].weight = 1.0f; + MDeformWeight *dw = dvert->dw; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if (LIKELY(defbase_tot >= 1) && lock_flags[0]) { + dw->weight = 1.0f; + } } } else { @@ -330,12 +357,14 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, cons float lock_iweight = 0.0f; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { - tot_weight += dw->weight; - } - else { - /* invert after */ - lock_iweight += dw->weight; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + tot_weight += dw->weight; + } + else { + /* invert after */ + lock_iweight += dw->weight; + } } } @@ -346,11 +375,13 @@ void defvert_normalize_lock_map(MDeformVert *dvert, const bool *lock_flags, cons float scalar = (1.0f / tot_weight) * lock_iweight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { - dw->weight *= scalar; + if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == FALSE)) { + dw->weight *= scalar; - /* in case of division errors with very low weights */ - CLAMP(dw->weight, 0.0f, 1.0f); + /* in case of division errors with very low weights */ + CLAMP(dw->weight, 0.0f, 1.0f); + } } } } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 580172bcccd..fe9a96d60cf 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -98,12 +98,13 @@ #endif /* precalculated gaussian factors for 5x super sampling */ -static float gaussianFactors[5] = {0.996849f, - 0.596145f, - 0.596145f, - 0.596145f, - 0.524141f}; -static float gaussianTotal = 3.309425f; +static const float gaussianFactors[5] = { + 0.996849f, + 0.596145f, + 0.596145f, + 0.596145f, + 0.524141f}; +static const float gaussianTotal = 3.309425f; /* UV Image neighboring pixel table x and y list */ static int neighX[8] = {1, 1, 0, -1, -1, -1, 0, 1}; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 791c47cc551..dbdf30ea63d 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -688,21 +688,27 @@ short fcurve_are_keyframes_usable(FCurve *fcu) return 1; } +bool BKE_fcurve_is_protected(FCurve *fcu) +{ + return ((fcu->flag & FCURVE_PROTECTED) || + ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED))); +} + /* Can keyframes be added to F-Curve? * Keyframes can only be added if they are already visible */ -short fcurve_is_keyframable(FCurve *fcu) +bool fcurve_is_keyframable(FCurve *fcu) { /* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */ if (fcurve_are_keyframes_usable(fcu) == 0) - return 0; + return false; /* F-Curve must currently be editable too */ - if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) - return 0; + if (BKE_fcurve_is_protected(fcu)) + return false; /* F-Curve is keyframable */ - return 1; + return true; } /* ***************************** Keyframe Column Tools ********************************* */ @@ -841,14 +847,7 @@ void calchandles_fcurve(FCurve *fcu) } } -/* Use when F-Curve with handles has changed - * It treats all BezTriples with the following rules: - * - PHASE 1: do types have to be altered? - * -> Auto handles: become aligned when selection status is NOT(000 || 111) - * -> Vector handles: become 'nothing' when (one half selected AND other not) - * - PHASE 2: recalculate handles - */ -void testhandles_fcurve(FCurve *fcu, const short use_handle) +void testhandles_fcurve(FCurve *fcu, const bool use_handle) { BezTriple *bezt; unsigned int a; @@ -856,45 +855,10 @@ void testhandles_fcurve(FCurve *fcu, const short use_handle) /* only beztriples have handles (bpoints don't though) */ if (ELEM(NULL, fcu, fcu->bezt)) return; - + /* loop over beztriples */ for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) { - short flag = 0; - - /* flag is initialized as selection status - * of beztriple control-points (labelled 0, 1, 2) - */ - if (bezt->f2 & SELECT) flag |= (1 << 1); // == 2 - if (use_handle == FALSE) { - if (flag & 2) { - flag |= (1 << 0) | (1 << 2); - } - } - else { - if (bezt->f1 & SELECT) flag |= (1 << 0); // == 1 - if (bezt->f3 & SELECT) flag |= (1 << 2); // == 4 - } - - /* one or two handles selected only */ - if (ELEM(flag, 0, 7) == 0) { - /* auto handles become aligned */ - if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) - bezt->h1 = HD_ALIGN; - if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) - bezt->h2 = HD_ALIGN; - - /* vector handles become 'free' when only one half selected */ - if (bezt->h1 == HD_VECT) { - /* only left half (1 or 2 or 1+2) */ - if (flag < 4) - bezt->h1 = 0; - } - if (bezt->h2 == HD_VECT) { - /* only right half (4 or 2+4) */ - if (flag > 3) - bezt->h2 = 0; - } - } + BKE_nurb_bezt_handle_test(bezt, use_handle); } /* recalculate handles */ diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index 1f106ff90a7..d87c93310c8 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -107,7 +107,8 @@ void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *con static void copy_lineset(FreestyleLineSet *new_lineset, FreestyleLineSet *lineset) { new_lineset->linestyle = lineset->linestyle; - new_lineset->linestyle->id.us++; + if (new_lineset->linestyle) + new_lineset->linestyle->id.us++; new_lineset->flags = lineset->flags; new_lineset->selection = lineset->selection; new_lineset->qi = lineset->qi; diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 2e32c18b264..6f275e4ec75 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -56,7 +56,13 @@ static char idp_size_table[] = { sizeof(double) }; -/* ------------Property Array Type ----------- */ + +/* -------------------------------------------------------------------- */ +/* Array Functions */ + +/** \name IDP Array API + * \{ */ + #define GETPROP(prop, i) (((IDProperty *)(prop)->data.pointer) + (i)) /* --------- property array type -------------*/ @@ -78,9 +84,12 @@ IDProperty *IDP_NewIDPArray(const char *name) IDProperty *IDP_CopyIDPArray(IDProperty *array) { /* don't use MEM_dupallocN because this may be part of an array */ - IDProperty *narray = MEM_mallocN(sizeof(IDProperty), "IDP_CopyIDPArray"), *tmp; + IDProperty *narray, *tmp; int i; + BLI_assert(array->type == IDP_IDPARRAY); + + narray = MEM_mallocN(sizeof(IDProperty), __func__); *narray = *array; narray->data.pointer = MEM_dupallocN(array->data.pointer); @@ -103,6 +112,8 @@ void IDP_FreeIDPArray(IDProperty *prop) { int i; + BLI_assert(prop->type == IDP_IDPARRAY); + for (i = 0; i < prop->len; i++) IDP_FreeProperty(GETPROP(prop, i)); @@ -113,7 +124,11 @@ void IDP_FreeIDPArray(IDProperty *prop) /*shallow copies item*/ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) { - IDProperty *old = GETPROP(prop, index); + IDProperty *old; + + BLI_assert(prop->type == IDP_IDPARRAY); + + old = GETPROP(prop, index); if (index >= prop->len || index < 0) return; if (item != old) IDP_FreeProperty(old); @@ -122,11 +137,15 @@ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) IDProperty *IDP_GetIndexArray(IDProperty *prop, int index) { + BLI_assert(prop->type == IDP_IDPARRAY); + return GETPROP(prop, index); } void IDP_AppendArray(IDProperty *prop, IDProperty *item) { + BLI_assert(prop->type == IDP_IDPARRAY); + IDP_ResizeIDPArray(prop, prop->len + 1); IDP_SetIndexArray(prop, prop->len - 1, item); } @@ -135,6 +154,8 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) { int newsize; + BLI_assert(prop->type == IDP_IDPARRAY); + /* first check if the array buffer size has room */ /* if newlen is 200 items less then totallen, reallocate anyway */ if (newlen <= prop->totallen) { @@ -286,8 +307,14 @@ static IDProperty *IDP_CopyArray(IDProperty *prop) return newp; } +/** \} */ + -/* ---------- String Type ------------ */ +/* -------------------------------------------------------------------- */ +/* String Functions */ + +/** \name IDProperty String API + * \{ */ /** * @@ -327,9 +354,13 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) static IDProperty *IDP_CopyString(IDProperty *prop) { - IDProperty *newp = idp_generic_copy(prop); + IDProperty *newp; + + BLI_assert(prop->type == IDP_STRING); + newp = idp_generic_copy(prop); - if (prop->data.pointer) newp->data.pointer = MEM_dupallocN(prop->data.pointer); + if (prop->data.pointer) + newp->data.pointer = MEM_dupallocN(prop->data.pointer); newp->len = prop->len; newp->subtype = prop->subtype; newp->totallen = prop->totallen; @@ -340,8 +371,10 @@ static IDProperty *IDP_CopyString(IDProperty *prop) void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) { - int stlen = strlen(st); + int stlen; + BLI_assert(prop->type == IDP_STRING); + stlen = strlen(st); if (maxlen > 0 && maxlen < stlen) stlen = maxlen; @@ -360,6 +393,8 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st) { int newlen; + BLI_assert(prop->type == IDP_STRING); + newlen = prop->len + strlen(st); /* we have to remember that prop->len includes the null byte for strings. * so there's no need to add +1 to the resize function.*/ @@ -371,6 +406,8 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append) { int newlen; + BLI_assert(append->type == IDP_STRING); + /* since ->len for strings includes the NULL byte, we have to subtract one or * we'll get an extra null byte after each concatenation operation.*/ newlen = str1->len + append->len - 1; @@ -380,13 +417,19 @@ void IDP_ConcatString(IDProperty *str1, IDProperty *append) void IDP_FreeString(IDProperty *prop) { + BLI_assert(prop->type == IDP_STRING); + if (prop->data.pointer) MEM_freeN(prop->data.pointer); } +/** \} */ -/*-------- ID Type, not in use yet -------*/ +/* -------------------------------------------------------------------- */ +/* ID Type (not in use yet) */ +/** \name IDProperty ID API (unused) + * \{ */ void IDP_LinkID(IDProperty *prop, ID *id) { if (prop->data.pointer) ((ID *)prop->data.pointer)->us--; @@ -398,15 +441,26 @@ void IDP_UnlinkID(IDProperty *prop) { ((ID *)prop->data.pointer)->us--; } +/** \} */ + -/*-------- Group Functions -------*/ +/* -------------------------------------------------------------------- */ +/* Group Functions */ -/*checks if a property with the same name as prop exists, and if so replaces it.*/ +/** \name IDProperty Group API + * \{ */ + +/** + * Checks if a property with the same name as prop exists, and if so replaces it. + */ static IDProperty *IDP_CopyGroup(IDProperty *prop) { - IDProperty *newp = idp_generic_copy(prop), *link; - newp->len = prop->len; + IDProperty *newp, *link; + BLI_assert(prop->type == IDP_GROUP); + newp = idp_generic_copy(prop); + newp->len = prop->len; + for (link = prop->data.group.first; link; link = link->next) { BLI_addtail(&newp->data.group, IDP_CopyProperty(link)); } @@ -419,6 +473,10 @@ static IDProperty *IDP_CopyGroup(IDProperty *prop) void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src) { IDProperty *other, *prop; + + BLI_assert(dest->type == IDP_GROUP); + BLI_assert(src->type == IDP_GROUP); + for (prop = src->data.group.first; prop; prop = prop->next) { other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name)); if (other && prop->type == other->type) { @@ -454,6 +512,10 @@ void IDP_SyncGroupValues(IDProperty *dest, IDProperty *src) void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src) { IDProperty *loop, *prop; + + BLI_assert(dest->type == IDP_GROUP); + BLI_assert(src->type == IDP_GROUP); + for (prop = src->data.group.first; prop; prop = prop->next) { for (loop = dest->data.group.first; loop; loop = loop->next) { if (STREQ(loop->name, prop->name)) { @@ -484,6 +546,9 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src) void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) { IDProperty *loop; + + BLI_assert(group->type == IDP_GROUP); + if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) { BLI_insertlinkafter(&group->data.group, loop, prop); @@ -497,13 +562,16 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) } } -/* +/** * If a property is missing in \a dest, add it. */ void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) { IDProperty *prop; + BLI_assert(dest->type == IDP_GROUP); + BLI_assert(src->type == IDP_GROUP); + if (do_overwrite) { for (prop = src->data.group.first; prop; prop = prop->next) { IDProperty *copy = IDP_CopyProperty(prop); @@ -538,6 +606,8 @@ void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) */ int IDP_AddToGroup(IDProperty *group, IDProperty *prop) { + BLI_assert(group->type == IDP_GROUP); + if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) { group->len++; BLI_addtail(&group->data.group, prop); @@ -553,6 +623,8 @@ int IDP_AddToGroup(IDProperty *group, IDProperty *prop) */ int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew) { + BLI_assert(group->type == IDP_GROUP); + if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) { group->len++; BLI_insertlinkafter(&group->data.group, previous, pnew); @@ -571,12 +643,16 @@ int IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew) */ void IDP_RemFromGroup(IDProperty *group, IDProperty *prop) { + BLI_assert(group->type == IDP_GROUP); + group->len--; BLI_remlink(&group->data.group, prop); } IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name) { + BLI_assert(prop->type == IDP_GROUP); + return (IDProperty *)BLI_findstring(&prop->data.group, name, offsetof(IDProperty, name)); } /** same as above but ensure type match */ @@ -599,7 +675,10 @@ typedef struct IDPIter { */ void *IDP_GetGroupIterator(IDProperty *prop) { - IDPIter *iter = MEM_callocN(sizeof(IDPIter), "IDPIter"); + IDPIter *iter; + + BLI_assert(prop->type == IDP_GROUP); + iter = MEM_mallocN(sizeof(IDPIter), "IDPIter"); iter->next = prop->data.group.first; iter->parent = prop; return (void *) iter; @@ -640,14 +719,21 @@ void IDP_FreeIterBeforeEnd(void *vself) static void IDP_FreeGroup(IDProperty *prop) { IDProperty *loop; + + BLI_assert(prop->type == IDP_GROUP); for (loop = prop->data.group.first; loop; loop = loop->next) { IDP_FreeProperty(loop); } BLI_freelistN(&prop->data.group); } +/** \} */ -/*-------- Main Functions --------*/ +/* -------------------------------------------------------------------- */ +/* Main Functions */ + +/** \name IDProperty Main API + * \{ */ IDProperty *IDP_CopyProperty(IDProperty *prop) { switch (prop->type) { @@ -909,3 +995,5 @@ void IDP_UnlinkProperty(IDProperty *prop) break; } } + +/** \} */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 2bf6304b04b..01b41eb22cd 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1250,6 +1250,12 @@ static int do_add_image_extension(char *string, const char imtype, const ImageFo } } #endif +#ifdef WITH_OPENIMAGEIO + else if (imtype == R_IMF_IMTYPE_PSD) { + if (!BLI_testextensie(string, ".psd")) + extension = ".psd"; + } +#endif #ifdef WITH_OPENEXR else if (ELEM(imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) { if (!BLI_testextensie(string, ".exr")) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index dd747ba4e46..9b8d34e651d 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1411,7 +1411,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname) /* This was in 2.43 and previous releases * however all data in blender should be sorted, not just duplicate names - * sorting should not hurt, but noting just incause it alters the way other + * sorting should not hurt, but noting just incase it alters the way other * functions work, so sort every time */ #if 0 if (result) diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 874e60936d1..a43bf41058c 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -409,7 +409,7 @@ static void layer_bucket_init_dummy(MaskRasterLayer *layer) static void layer_bucket_init(MaskRasterLayer *layer, const float pixel_size) { - MemArena *arena = BLI_memarena_new(1 << 16, __func__); + MemArena *arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__); const float bucket_dim_x = BLI_rctf_size_x(&layer->bounds); const float bucket_dim_y = BLI_rctf_size_y(&layer->bounds); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 090d41aba73..a77f768835a 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -645,7 +645,7 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int } cdlp = &pdata->layers[poly_index]; cdlu = &ldata->layers[loop_index]; - cdlf = do_tessface ? &fdata->layers[face_index] : NULL; + cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL; BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name)); CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers); @@ -662,8 +662,10 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers); break; case 2: - BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name)); - CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers); + if (cdlf) { + BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name)); + CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers); + } break; } } @@ -673,48 +675,61 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface) { - CustomData *pdata = &me->pdata, *ldata = &me->ldata, *fdata = &me->fdata; - const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY); - const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV); - const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1; - int pidx, lidx, fidx; - - do_tessface = (do_tessface && fdata->totlayer && !me->edit_btmesh); - pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name); - lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name); - fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1; - - /* None of those cases should happen, in theory! - * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers! - */ - if (pidx == -1) { - if (lidx == -1) { - if (fidx == -1) { - /* No layer found with this name! */ - return false; - } - else { - lidx = lidx_start + (fidx - fidx_start); - } - } - pidx = pidx_start + (lidx - lidx_start); + CustomData *pdata, *ldata, *fdata; + if (me->edit_btmesh) { + pdata = &me->edit_btmesh->bm->pdata; + ldata = &me->edit_btmesh->bm->ldata; + /* No tessellated data in BMesh! */ + fdata = NULL; + do_tessface = false; } else { - if (lidx == -1) { - lidx = lidx_start + (pidx - pidx_start); + pdata = &me->pdata; + ldata = &me->ldata; + fdata = &me->fdata; + do_tessface = (do_tessface && fdata->totlayer); + } + + { + const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY); + const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV); + const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1; + int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name); + int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name); + int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1; + + /* None of those cases should happen, in theory! + * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers! + */ + if (pidx == -1) { + if (lidx == -1) { + if (fidx == -1) { + /* No layer found with this name! */ + return false; + } + else { + lidx = lidx_start + (fidx - fidx_start); + } + } + pidx = pidx_start + (lidx - lidx_start); } - if (fidx == -1 && do_tessface) { - fidx = fidx_start + (pidx - pidx_start); + else { + if (lidx == -1) { + lidx = lidx_start + (pidx - pidx_start); + } + if (fidx == -1 && do_tessface) { + fidx = fidx_start + (pidx - pidx_start); + } } - } #if 0 - /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */ - else if ((pidx - pidx_start) != (lidx - lidx_start)) { - lidx = lidx_start + (pidx - pidx_start); - } + /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */ + else if ((pidx - pidx_start) != (lidx - lidx_start)) { + lidx = lidx_start + (pidx - pidx_start); + } #endif - return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface); + return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface); + } } void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3]) diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 07dfae2f28a..47b8e053bf7 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -318,9 +318,9 @@ void BKE_mesh_calc_normals_tessface(MVert *mverts, int numVerts, MFace *mfaces, * Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals'). * Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges). */ -void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *medges, int numEdges, - MLoop *mloops, float (*r_loopnors)[3], int numLoops, - MPoly *mpolys, float (*polynors)[3], int numPolys, float split_angle) +void BKE_mesh_normals_loop_split(MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges, + MLoop *mloops, float (*r_loopnors)[3], const int numLoops, + MPoly *mpolys, float (*polynors)[3], const int numPolys, float split_angle) { #define INDEX_UNSET INT_MIN #define INDEX_INVALID -1 @@ -333,7 +333,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med * sharp edge: < 0 (INDEX_INVALID || INDEX_UNSET), * unset: INDEX_UNSET * Note that currently we only have two values for second loop of sharp edges. However, if needed, we can - * store the negated value of loop index instead of INDEX_INVALID to retrieve th real value later in code). + * store the negated value of loop index instead of INDEX_INVALID to retrieve the real value later in code). * Note also that lose edges always have both values set to 0! */ int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__); @@ -377,7 +377,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med /* Check whether current edge might be smooth or sharp */ if ((e2l[0] | e2l[1]) == 0) { - /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INT_MIN to tag it as unset). */ + /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */ e2l[0] = ml_curr_index; e2l[1] = INDEX_UNSET; } @@ -397,7 +397,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med } } else if (!IS_EDGE_SHARP(e2l)) { - /* More that two loops using this edge, tag as sharp if not yet done. */ + /* More than two loops using this edge, tag as sharp if not yet done. */ e2l[1] = INDEX_INVALID; } /* Else, edge is already 'disqualified' (i.e. sharp)! */ @@ -448,6 +448,7 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med * it should not be a common case in real-life meshes anyway). */ const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */ + const MVert *mv_pivot = &mverts[mv_pivot_index]; const int *e2lfan_curr; float vec_curr[3], vec_prev[3]; MLoop *mlfan_curr, *mlfan_next; @@ -464,11 +465,10 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med /* Only need to compute previous edge's vector once, then we can just reuse old current one! */ { - const MEdge *me_prev = &medges[ml_prev->e]; - const MVert *mv_1 = &mverts[mv_pivot_index]; + const MEdge *me_prev = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */ const MVert *mv_2 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] : &mverts[me_prev->v1]; - sub_v3_v3v3(vec_prev, mv_2->co, mv_1->co); + sub_v3_v3v3(vec_prev, mv_2->co, mv_pivot->co); normalize_v3(vec_prev); } @@ -479,12 +479,11 @@ void BKE_mesh_normals_loop_split(MVert *mverts, int UNUSED(numVerts), MEdge *med * given the fact that this code should not be called that much in real-life meshes... */ { - const MEdge *me_curr = &medges[ml_curr->e]; - const MVert *mv_1 = &mverts[mv_pivot_index]; + const MEdge *me_curr = &medges[mlfan_curr->e]; const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] : &mverts[me_curr->v1]; - sub_v3_v3v3(vec_curr, mv_2->co, mv_1->co); + sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co); normalize_v3(vec_curr); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index bf4a63c52a8..d9630a7343d 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -62,7 +62,6 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_math.h" -#include "BLI_mempool.h" #include "BLI_threads.h" #include "BKE_animsys.h" diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4519a116946..0cdcf4e7298 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -114,8 +114,8 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, BLI_bitmap *prev_hidden) { BLI_bitmap *subd; - int hi_gridsize = ccg_gridsize(hi_level); - int lo_gridsize = ccg_gridsize(lo_level); + int hi_gridsize = BKE_ccg_gridsize(hi_level); + int lo_gridsize = BKE_ccg_gridsize(lo_level); int yh, xh, xl, yl, xo, yo, hi_ndx; int offset, factor; @@ -127,7 +127,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample"); - factor = ccg_factor(lo_level, hi_level); + factor = BKE_ccg_factor(lo_level, hi_level); offset = 1 << (hi_level - lo_level - 1); /* low-res blocks */ @@ -173,12 +173,12 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden, int new_level) { BLI_bitmap *new_hidden; - int new_gridsize = ccg_gridsize(new_level); - int old_gridsize = ccg_gridsize(old_level); + int new_gridsize = BKE_ccg_gridsize(new_level); + int old_gridsize = BKE_ccg_gridsize(old_level); int x, y, factor, old_value; BLI_assert(new_level <= old_level); - factor = ccg_factor(new_level, old_level); + factor = BKE_ccg_factor(new_level, old_level); new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize, "downsample hidden"); @@ -246,7 +246,7 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) { MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); - int gridsize = ccg_gridsize(level); + int gridsize = BKE_ccg_gridsize(level); int gridarea = gridsize * gridsize; int i, j, k; @@ -594,7 +594,7 @@ static void multires_copy_dm_grid(CCGElem *gridA, CCGElem *gridB, CCGKey *keyA, static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level) { if (level < gpm->level) { - int gridsize = ccg_gridsize(level); + int gridsize = BKE_ccg_gridsize(level); float *data = MEM_callocN(sizeof(float) * gridsize * gridsize, "multires_grid_paint_mask_downsample"); int x, y; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 2305c0696af..c0df306a3fa 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1107,7 +1107,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) * copying for internal use (threads for eg), where you wont want it to modify the * scene data. */ -static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern, const short copy_previews) +static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool do_id_user, bool do_make_extern, bool copy_previews) { bNodeTree *newtree; bNode *node /*, *nnode */ /* UNUSED */, *last; @@ -1116,13 +1116,17 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use if (ntree == NULL) return NULL; - /* is ntree part of library? */ - for (newtree = G.main->nodetree.first; newtree; newtree = newtree->id.next) - if (newtree == ntree) break; - if (newtree) { - newtree = BKE_libblock_copy(&ntree->id); + if (bmain) { + /* is ntree part of library? */ + if (BLI_findindex(&bmain->nodetree, ntree) != -1) + newtree = BKE_libblock_copy(&ntree->id); + else + newtree = NULL; } - else { + else + newtree = NULL; + + if (newtree == NULL) { newtree = MEM_dupallocN(ntree); newtree->id.lib = NULL; /* same as owning datablock id.lib */ BKE_libblock_copy_data(&newtree->id, &ntree->id, true); /* copy animdata and ID props */ @@ -1208,7 +1212,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user) { - return ntreeCopyTree_internal(ntree, do_id_user, TRUE, TRUE); + return ntreeCopyTree_internal(ntree, G.main, do_id_user, TRUE, TRUE); } bNodeTree *ntreeCopyTree(bNodeTree *ntree) { @@ -1590,6 +1594,8 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent) void nodeFreeNode(bNodeTree *ntree, bNode *node) { bNodeSocket *sock, *nextsock; + char propname_esc[MAX_IDPROP_NAME * 2]; + char prefix[MAX_IDPROP_NAME * 2]; /* extra free callback */ if (node->typeinfo && node->typeinfo->freefunc_api) { @@ -1609,6 +1615,11 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node) BLI_remlink(&ntree->nodes, node); + BLI_strescape(propname_esc, node->name, sizeof(propname_esc)); + BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc); + + BKE_animdata_fix_paths_remove((ID *)ntree, prefix); + if (ntree->typeinfo && ntree->typeinfo->free_node_cache) ntree->typeinfo->free_node_cache(ntree, node); @@ -1657,6 +1668,22 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *so MEM_freeN(sock->default_value); } +static void free_localized_node_groups(bNodeTree *ntree) +{ + bNode *node; + + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP && node->id) { + bNodeTree *ngroup = (bNodeTree *)node->id; + if (BLI_findindex(&G.main->nodetree, ngroup) == -1) { + /* ntree is not in library, i.e. localized node group: free it */ + ntreeFreeTree_ex(ngroup, false); + MEM_freeN(ngroup); + } + } + } +} + /* do not free ntree itself here, BKE_libblock_free calls this function too */ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) { @@ -1683,6 +1710,9 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) } } + /* XXX not nice, but needed to free localized node groups properly */ + free_localized_node_groups(ntree); + /* unregister associated RNA types */ ntreeInterfaceTypeFree(ntree); @@ -1932,8 +1962,14 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) /* Make full copy. * Note: previews are not copied here. */ - ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE, FALSE); - + ltree = ntreeCopyTree_internal(ntree, NULL, FALSE, FALSE, FALSE); + + for (node = ltree->nodes.first; node; node = node->next) { + if (node->type == NODE_GROUP && node->id) { + node->id = (ID *)ntreeLocalize((bNodeTree *)node->id); + } + } + if (adt) { AnimData *ladt = BKE_animdata_from_id(<ree->id); @@ -1978,7 +2014,7 @@ void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) /* we have to assume the editor already changed completely */ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) { - if (localtree && ntree) { + if (ntree && localtree) { if (ntree->typeinfo->local_merge) ntree->typeinfo->local_merge(localtree, ntree); @@ -2285,7 +2321,7 @@ bNode *nodeGetActive(bNodeTree *ntree) static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key, bNodeInstanceKey parent_key, bNodeTree *ntree, short idtype) { - if (parent_key.value == active_key.value) { + if (parent_key.value == active_key.value || active_key.value == 0) { bNode *node; for (node = ntree->nodes.first; node; node = node->next) if (node->id && GS(node->id->name) == idtype) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5d0216affca..8c2475369de 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -643,7 +643,9 @@ void BKE_object_unlink(Object *ob) for (lineset = (FreestyleLineSet *)srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { - BKE_unlink_linestyle_target_object(lineset->linestyle, ob); + if (lineset->linestyle) { + BKE_unlink_linestyle_target_object(lineset->linestyle, ob); + } } } } diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index b47a493581e..6bdfb22dc1a 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -359,8 +359,8 @@ int paint_is_bmesh_face_hidden(BMFace *f) float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, unsigned x, unsigned y) { - int factor = ccg_factor(level, gpm->level); - int gridsize = ccg_gridsize(gpm->level); + int factor = BKE_ccg_factor(level, gpm->level); + int gridsize = BKE_ccg_gridsize(gpm->level); return gpm->data[(y * factor) * gridsize + (x * factor)]; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 216bc94a058..24cf98d957d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1729,7 +1729,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_ return 0; if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) { - /* for meshes that are either only defined or for child particles, the + /* for meshes that are either only deformed or for child particles, the * index and fw do not require any mapping, so we can directly use it */ if (from == PART_FROM_VERT) { if (index >= dm->getNumVerts(dm)) @@ -1817,8 +1817,8 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache copy_v3_v3(orco, orcodata[mapindex]); if (ornor) { - dm->getVertNo(dm, mapindex, nor); - normalize_v3(nor); + dm->getVertNo(dm, mapindex, ornor); + normalize_v3(ornor); } if (utan && vtan) { @@ -1843,7 +1843,7 @@ void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache if (nor) copy_v3_v3(nor, tmpnor); - normalize_v3(tmpnor); + normalize_v3(tmpnor); /* XXX Why not normalize tmpnor before copying it into nor??? -- mont29 */ mul_v3_fl(tmpnor, -foffset); add_v3_v3(vec, tmpnor); } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index c83d760797b..0a7c6d901af 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -438,10 +438,6 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) if (new_node) { pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v); } - else { - BLI_gset_remove(f_node->bm_unique_verts, v, NULL); - BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); - } } else { /* Remove from other verts */ @@ -516,10 +512,10 @@ static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) return ((len_squared_v3v3(q->center, c) <= q->radius_squared)); } -/* Return true if the vertex mask is less than 0.5, false otherwise */ -static bool check_mask_half(EdgeQueueContext *eq_ctx, BMVert *v) +/* Return true if the vertex mask is less than 1.0, false otherwise */ +static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v) { - return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 0.5f); + return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f); } static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, @@ -527,11 +523,13 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, { BMVert **pair; - /* Don't let topology update affect masked vertices. Unlike with - * displacements, can't do 50% topology update, so instead set - * (arbitrary) cutoff: if both vertices' masks are less than 50%, - * topology update can happen. */ - if (check_mask_half(eq_ctx, e->v1) && check_mask_half(eq_ctx, e->v2)) { + /* Don't let topology update affect fully masked vertices. This used to + * have a 50% mask cutoff, with the reasoning that you can't do a 50% + * topology update. But this gives an ugly border in the mesh. The mask + * should already make the brush move the vertices only 50%, which means + * that topology updates will also happen less frequent, that should be + * enough. */ + if (check_mask(eq_ctx, e->v1) || check_mask(eq_ctx, e->v2)) { pair = BLI_mempool_alloc(eq_ctx->pool); pair[0] = e->v1; pair[1] = e->v2; @@ -678,6 +676,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, BMVert *v_new; float mid[3]; int i, node_index; + const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK); /* Get all faces adjacent to the edge */ pbvh_bmesh_edge_loops(edge_loops, e); @@ -689,6 +688,15 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, e->v1)); v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1); + /* update paint mask */ + if (cd_vert_mask_offset != -1) { + float mask_v1 = BM_ELEM_CD_GET_FLOAT(e->v1, cd_vert_mask_offset); + float mask_v2 = BM_ELEM_CD_GET_FLOAT(e->v2, cd_vert_mask_offset); + float mask_v_new = 0.5f * (mask_v1 + mask_v2); + + BM_ELEM_CD_SET_FLOAT(v_new, cd_vert_mask_offset, mask_v_new); + } + /* For each face, add two new triangles and delete the original */ for (i = 0; i < edge_loops->count; i++) { BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); @@ -1112,7 +1120,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, if (mode & PBVH_Collapse) { EdgeQueue q; - BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, + BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 128, 128, 0); EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset}; @@ -1125,7 +1133,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, if (mode & PBVH_Subdivide) { EdgeQueue q; - BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, + BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert *[2]), 128, 128, 0); EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset}; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b89cb6b7b82..41e43c00457 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -493,23 +493,10 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.border.ymax = 1.0f; sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct"); - sce->toolsettings->cornertype = 1; - sce->toolsettings->degr = 90; - sce->toolsettings->step = 9; - sce->toolsettings->turn = 1; - sce->toolsettings->extr_offs = 1; sce->toolsettings->doublimit = 0.001; - sce->toolsettings->segments = 32; - sce->toolsettings->rings = 32; - sce->toolsettings->vertices = 32; - sce->toolsettings->uvcalc_radius = 1.0f; - sce->toolsettings->uvcalc_cubesize = 1.0f; - sce->toolsettings->uvcalc_mapdir = 1; - sce->toolsettings->uvcalc_mapalign = 1; sce->toolsettings->uvcalc_margin = 0.001f; sce->toolsettings->unwrapper = 1; sce->toolsettings->select_thresh = 0.01f; - sce->toolsettings->jointrilimit = 0.8f; sce->toolsettings->selectmode = SCE_SELECT_VERTEX; sce->toolsettings->uv_selectmode = UV_SELECT_VERTEX; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 43845638754..dd7e847feaf 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -632,7 +632,7 @@ static void seq_update_sound_bounds_recursive_rec(Scene *scene, Sequence *metase endofs = seq->start + seq->len - end; sound_move_scene_sound(scene, seq->scene_sound, seq->start + startofs, - seq->start + seq->len - endofs, startofs); + seq->start + seq->len - endofs, startofs + seq->anim_startofs); } } } @@ -664,8 +664,9 @@ void BKE_sequence_calc_disp(Scene *scene, Sequence *seq) if (ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) { BKE_sequencer_update_sound_bounds(scene, seq); } - else if (seq->type == SEQ_TYPE_META) + else if (seq->type == SEQ_TYPE_META) { seq_update_sound_bounds_recursive(scene, seq); + } } void BKE_sequence_calc(Scene *scene, Sequence *seq) diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 9bc7f4b9e2b..5c9c564998e 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -506,7 +506,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM DerivedMesh *ss_mesh = NULL; ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; - /* remove loop dependencies on derived meshs (TODO should this be done elsewhere?) */ + /* remove loop dependencies on derived meshes (TODO should this be done elsewhere?) */ if (smd->target == ob) smd->target = NULL; if (smd->auxTarget == ob) smd->auxTarget = NULL; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 2461ec85bb4..9a38a5f87b8 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -170,7 +170,7 @@ static CCGSubSurf *_getSubSurf(CCGSubSurf *prevSS, int subdivLevels, if (useArena) { CCGAllocatorIFC allocatorIFC; - CCGAllocatorHDL allocator = BLI_memarena_new((1 << 16), "subsurf arena"); + CCGAllocatorHDL allocator = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "subsurf arena"); allocatorIFC.alloc = arena_alloc; allocatorIFC.realloc = arena_realloc; @@ -1064,8 +1064,8 @@ void subsurf_copy_grid_hidden(DerivedMesh *dm, const MPoly *mpoly, for (j = 0; j < mpoly[i].totloop; j++) { const MDisps *md = &mdisps[mpoly[i].loopstart + j]; - int hidden_gridsize = ccg_gridsize(md->level); - int factor = ccg_factor(level, md->level); + int hidden_gridsize = BKE_ccg_gridsize(md->level); + int factor = BKE_ccg_factor(level, md->level); if (!md->hidden) continue; @@ -1107,8 +1107,8 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly, if (!gpm->data) continue; - factor = ccg_factor(level, gpm->level); - gpm_gridsize = ccg_gridsize(gpm->level); + factor = BKE_ccg_factor(level, gpm->level); + gpm_gridsize = BKE_ccg_gridsize(gpm->level); for (y = 0; y < gridSize; y++) { for (x = 0; x < gridSize; x++) { diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index d98a6cbe0cc..22b0fe7bc24 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -123,12 +123,12 @@ void init_tex_mapping(TexMapping *texmap) if (ELEM(texmap->type, TEXMAP_TYPE_TEXTURE, TEXMAP_TYPE_NORMAL)) { /* keep matrix invertible */ - if(fabsf(size[0]) < 1e-5f) - size[0] = signf(size[0])*1e-5f; - if(fabsf(size[1]) < 1e-5f) - size[1] = signf(size[1])*1e-5f; - if(fabsf(size[2]) < 1e-5f) - size[2] = signf(size[2])*1e-5f; + if (fabsf(size[0]) < 1e-5f) + size[0] = signf(size[0]) * 1e-5f; + if (fabsf(size[1]) < 1e-5f) + size[1] = signf(size[1]) * 1e-5f; + if (fabsf(size[2]) < 1e-5f) + size[2] = signf(size[2]) * 1e-5f; } size_to_mat4(smat, texmap->size); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index fd92ec9f462..b8711f6e5f6 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -3340,7 +3340,7 @@ static void track_plane_from_existing_motion(MovieTrackingPlaneTrack *plane_trac break; } - libmv_homography2DFromCorrespondencesLinear(x1, x2, num_correspondences, H_double, 1e-8); + libmv_homography2DFromCorrespondencesEuc(x1, x2, num_correspondences, H_double); mat3f_from_mat3d(H, H_double); @@ -3444,7 +3444,7 @@ void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners float_corners_to_double(reference_corners, x1); float_corners_to_double(corners, x2); - libmv_homography2DFromCorrespondencesLinear(x1, x2, 4, H_double, 1e-8); + libmv_homography2DFromCorrespondencesEuc(x1, x2, 4, H_double); mat3f_from_mat3d(H, H_double); } diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h index bcdc97cdaa7..cf10fe53a5d 100644 --- a/source/blender/blenlib/BLI_bitmap.h +++ b/source/blender/blenlib/BLI_bitmap.h @@ -60,6 +60,9 @@ typedef unsigned int BLI_bitmap; ((_bitmap)[(_index) >> BLI_BITMAP_POWER] & \ (1u << ((_index) & BLI_BITMAP_MASK))) +#define BLI_BITMAP_GET_BOOL(_bitmap, _index) \ + (BLI_BITMAP_GET(_bitmap, _index) != 0) + /* set the value of a single bit at '_index' */ #define BLI_BITMAP_SET(_bitmap, _index) \ ((_bitmap)[(_index) >> BLI_BITMAP_POWER] |= \ diff --git a/source/blender/blenlib/BLI_boxpack2d.h b/source/blender/blenlib/BLI_boxpack2d.h index 8316987dfcd..b02e3423f88 100644 --- a/source/blender/blenlib/BLI_boxpack2d.h +++ b/source/blender/blenlib/BLI_boxpack2d.h @@ -39,14 +39,15 @@ typedef struct BoxPack { float y; float w; float h; - int index; /* Verts this box uses * (BL,TR,TL,BR) / 0,1,2,3 */ struct BoxVert *v[4]; + + int index; } BoxPack; -void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *tot_height); +void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *tot_width, float *tot_height); #endif diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h index ca050883018..c9fb00ecdf5 100644 --- a/source/blender/blenlib/BLI_linklist_stack.h +++ b/source/blender/blenlib/BLI_linklist_stack.h @@ -151,8 +151,6 @@ (void)&(_##var##_type); \ } (void)0 -#include "BLI_alloca.h" - /** \} */ #endif /* __BLI_LINKLIST_STACK_H__ */ diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index d3f6c7ef14b..f815716148b 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -155,8 +155,8 @@ bool isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon); /* point in polygon */ -bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr); -bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr); +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, const bool use_holes); +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, const bool use_holes); int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]); @@ -188,7 +188,10 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4]); bool clip_segment_v3_plane_n(float p1[3], float p2[3], float plane_array[][4], const int plane_tot); void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int, void *), void *userData); - +void fill_poly_v2i_n( + const int xmin, const int ymin, const int xmax, const int ymax, + const int polyXY[][2], const int polyCorners, + void (*callback)(int, int, void *), void *userData); /****************************** Interpolation ********************************/ /* tri or quad, d can be NULL */ diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index 9ff4883c89c..737324ebc16 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -47,7 +47,7 @@ extern "C" { * enough to not cause much internal fragmentation, * small enough not to waste resources */ -#define BLI_MEMARENA_STD_BUFSIZE (1 << 14) +#define BLI_MEMARENA_STD_BUFSIZE MEM_SIZE_OPTIMAL(1 << 14) struct MemArena; typedef struct MemArena MemArena; diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 88650719712..3fab77f2cb2 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -67,6 +67,10 @@ void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) ATTR_ void BLI_mempool_as_array(BLI_mempool *pool, void *data) ATTR_NONNULL(1, 2); void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); +#ifdef DEBUG +void BLI_mempool_set_memory_debug(void); +#endif + /** iteration stuff. note: this may easy to produce bugs with **/ /* private structure */ typedef struct BLI_mempool_iter { diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index e7d2130e473..52f5decb4f4 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -51,7 +51,7 @@ typedef struct ScanFillContext { struct MemArena *arena; } ScanFillContext; -#define BLI_SCANFILL_ARENA_SIZE 16384 +#define BLI_SCANFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14) typedef struct ScanFillVert { struct ScanFillVert *next, *prev; diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h new file mode 100644 index 00000000000..f57d42858c7 --- /dev/null +++ b/source/blender/blenlib/BLI_task.h @@ -0,0 +1,108 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_TASK_H__ +#define __BLI_TASK_H__ + +/** \file BLI_task.h + * \ingroup bli + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +/* Task Scheduler + * + * Central scheduler that holds running threads ready to execute tasks. A single + * queue holds the task from all pools. + * + * Init/exit must be called before/after any task pools are created/freed, and + * must be called from the main threads. All other scheduler and pool functions + * are thread-safe. */ + +typedef struct TaskScheduler TaskScheduler; + +enum { + TASK_SCHEDULER_AUTO_THREADS = 0, + TASK_SCHEDULER_SINGLE_THREAD = 1 +}; + +TaskScheduler *BLI_task_scheduler_create(int num_threads); +void BLI_task_scheduler_free(TaskScheduler *scheduler); + +int BLI_task_scheduler_num_threads(TaskScheduler *scheduler); + +/* Task Pool + * + * Pool of tasks that will be executed by the central TaskScheduler. For each + * pool, we can wait for all tasks to be done, or cancel them before they are + * done. + * + * Running tasks may spawn new tasks. + * + * Pools may be nested, i.e. a thread running a task can create another task + * pool with smaller tasks. When other threads are busy they will continue + * working on their own tasks, if not they will join in, no new threads will + * be launched. + */ + +typedef enum TaskPriority { + TASK_PRIORITY_LOW, + TASK_PRIORITY_HIGH +} TaskPriority; + +typedef struct TaskPool TaskPool; +typedef void (*TaskRunFunction)(TaskPool *pool, void *taskdata, int threadid); + +TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata); +void BLI_task_pool_free(TaskPool *pool); + +void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, + void *taskdata, bool free_taskdata, TaskPriority priority); + +/* work and wait until all tasks are done */ +void BLI_task_pool_work_and_wait(TaskPool *pool); +/* cancel all tasks, keep worker threads running */ +void BLI_task_pool_cancel(TaskPool *pool); +/* stop all worker threads */ +void BLI_task_pool_stop(TaskPool *pool); + +/* for worker threads, test if cancelled */ +bool BLI_task_pool_cancelled(TaskPool *pool); + +/* optional userdata pointer to pass along to run function */ +void *BLI_task_pool_userdata(TaskPool *pool); + +/* optional mutex to use from run function */ +ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); + +/* number of tasks done, for stats, don't use this to make decisions */ +size_t BLI_task_pool_tasks_done(TaskPool *pool); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 38ad0827246..7a3ee1dd0f4 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -45,6 +45,7 @@ extern "C" { #define BLENDER_MAX_THREADS 64 struct ListBase; +struct TaskScheduler; /* Threading API */ @@ -52,6 +53,8 @@ struct ListBase; void BLI_threadapi_init(void); void BLI_threadapi_exit(void); +struct TaskScheduler *BLI_task_scheduler_get(void); + void BLI_init_threads(struct ListBase *threadbase, void *(*do_thread)(void *), int tot); int BLI_available_threads(struct ListBase *threadbase); int BLI_available_thread_index(struct ListBase *threadbase); @@ -101,6 +104,7 @@ ThreadMutex *BLI_mutex_alloc(void); void BLI_mutex_free(ThreadMutex *mutex); void BLI_mutex_lock(ThreadMutex *mutex); +bool BLI_mutex_trylock(ThreadMutex *mutex); void BLI_mutex_unlock(ThreadMutex *mutex); /* Spin Lock */ @@ -144,27 +148,15 @@ void BLI_ticket_mutex_free(TicketMutex *ticket); void BLI_ticket_mutex_lock(TicketMutex *ticket); void BLI_ticket_mutex_unlock(TicketMutex *ticket); -/* ThreadedWorker - * - * A simple tool for dispatching work to a limited number of threads - * in a transparent fashion from the caller's perspective. */ - -struct ThreadedWorker; - -/* Create a new worker supporting tot parallel threads. - * When new work in inserted and all threads are busy, sleep(sleep_time) before checking again - */ -struct ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time); - -/* join all working threads */ -void BLI_end_worker(struct ThreadedWorker *worker); - -/* also ends all working threads */ -void BLI_destroy_worker(struct ThreadedWorker *worker); +/* Condition */ + +typedef pthread_cond_t ThreadCondition; -/* Spawns a new work thread if possible, sleeps until one is available otherwise - * NOTE: inserting work is NOT thread safe, so make sure it is only done from one thread */ -void BLI_insert_work(struct ThreadedWorker *worker, void *param); +void BLI_condition_init(ThreadCondition *cond); +void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex); +void BLI_condition_notify_one(ThreadCondition *cond); +void BLI_condition_notify_all(ThreadCondition *cond); +void BLI_condition_end(ThreadCondition *cond); /* ThreadWorkQueue * diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 31125fd3153..d855d45760a 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -94,6 +94,7 @@ set(SRC intern/string.c intern/string_cursor_utf8.c intern/string_utf8.c + intern/task.c intern/threads.c intern/time.c intern/uvproject.c @@ -160,6 +161,7 @@ set(SRC BLI_string_cursor_utf8.h BLI_string_utf8.h BLI_sys_types.h + BLI_task.h BLI_threads.h BLI_utildefines.h BLI_uvproject.h @@ -178,6 +180,10 @@ if(WITH_BINRELOC) add_definitions(-DWITH_BINRELOC) endif() +if(WITH_MEM_VALGRIND) + add_definitions(-DWITH_MEM_VALGRIND) +endif() + if(WIN32) list(APPEND INC ../../../intern/utfconv diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 45bdeeedcf9..206a8041c4a 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -127,7 +127,7 @@ Heap *BLI_heap_new_ex(unsigned int tot_reserve) /* ensure we have at least one so we can keep doubling it */ heap->bufsize = MAX2(1, tot_reserve); heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); - heap->arena = BLI_memarena_new(1 << 16, "heap arena"); + heap->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "heap arena"); return heap; } diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 80483fbfa38..7c1cdd593c3 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -117,7 +117,7 @@ typedef struct BVHRayCastData { * Notes: You can choose the tree type --> binary, quad, octree, choose below */ -static float KDOP_AXES[13][3] = { +static const float KDOP_AXES[13][3] = { {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, {1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, {0, 1.0, -1.0} diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 747c2f0c2b7..4a6712201a9 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -38,6 +38,10 @@ #include "BLI_linklist.h" #include "BLI_strict_flags.h" +#ifdef WITH_MEM_VALGRIND +# include "valgrind/memcheck.h" +#endif + struct MemArena { unsigned char *curbuf; int bufsize, cursize; @@ -56,6 +60,10 @@ MemArena *BLI_memarena_new(const int bufsize, const char *name) ma->align = 8; ma->name = name; +#ifdef WITH_MEM_VALGRIND + VALGRIND_CREATE_MEMPOOL(ma, 0, false); +#endif + return ma; } @@ -78,6 +86,11 @@ void BLI_memarena_use_align(struct MemArena *ma, const int align) void BLI_memarena_free(MemArena *ma) { BLI_linklist_freeN(ma->bufs); + +#ifdef WITH_MEM_VALGRIND + VALGRIND_DESTROY_MEMPOOL(ma); +#endif + MEM_freeN(ma); } @@ -122,6 +135,10 @@ void *BLI_memarena_alloc(MemArena *ma, int size) ma->curbuf += size; ma->cursize -= size; +#ifdef WITH_MEM_VALGRIND + VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); +#endif + return ptr; } @@ -152,4 +169,10 @@ void BLI_memarena_clear(MemArena *ma) memset(ma->curbuf, 0, (size_t)curbuf_used); } } + +#ifdef WITH_MEM_VALGRIND + VALGRIND_DESTROY_MEMPOOL(ma); + VALGRIND_CREATE_MEMPOOL(ma, 0, false); +#endif + } diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index febf09745fb..261e53f0f55 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -45,6 +45,9 @@ #include "BLI_strict_flags.h" /* keep last */ +#ifdef WITH_MEM_VALGRIND +# include "valgrind/memcheck.h" +#endif /* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */ #ifdef __BIG_ENDIAN__ @@ -63,6 +66,10 @@ /* when undefined, merge the allocs for BLI_mempool_chunk and its data */ // #define USE_DATA_PTR +#ifndef NDEBUG +static bool mempool_debug_memset = false; +#endif + /** * A free element from #BLI_mempool_chunk. Data is cast to this type and stored in * #BLI_mempool.free as a single linked list, each item #BLI_mempool.esize large. @@ -275,6 +282,10 @@ BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem, lasttail = mempool_chunk_add(pool, mpchunk, lasttail); } +#ifdef WITH_MEM_VALGRIND + VALGRIND_CREATE_MEMPOOL(pool, 0, false); +#endif + return pool; } @@ -297,6 +308,11 @@ void *BLI_mempool_alloc(BLI_mempool *pool) } pool->free = pool->free->next; + +#ifdef WITH_MEM_VALGRIND + VALGRIND_MEMPOOL_ALLOC(pool, retval, pool->esize); +#endif + return retval; } @@ -330,6 +346,11 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) BLI_assert(!"Attempt to free data which is not in pool.\n"); } } + + /* enable for debugging */ + if (UNLIKELY(mempool_debug_memset)) { + memset(addr, 255, pool->esize); + } #endif if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { @@ -345,8 +366,12 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) pool->totused--; +#ifdef WITH_MEM_VALGRIND + VALGRIND_MEMPOOL_FREE(pool, addr); +#endif + /* nothing is in use; free all the chunks except the first */ - if (pool->totused == 0) { + if (UNLIKELY(pool->totused == 0)) { BLI_freenode *curnode = NULL; char *tmpaddr = NULL; unsigned int i; @@ -359,6 +384,10 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) pool->totalloc = pool->pchunk; #endif + /* temp alloc so valgrind doesn't complain when setting free'd blocks 'next' */ +#ifdef WITH_MEM_VALGRIND + VALGRIND_MEMPOOL_ALLOC(pool, CHUNK_DATA(first), pool->csize); +#endif pool->free = CHUNK_DATA(first); /* start of the list */ for (tmpaddr = CHUNK_DATA(first), i = 0; i < pool->pchunk; i++) { curnode = ((BLI_freenode *)tmpaddr); @@ -366,6 +395,10 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) curnode->next = (BLI_freenode *)tmpaddr; } curnode->next = NULL; /* terminate the list */ + +#ifdef WITH_MEM_VALGRIND + VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first)); +#endif } } @@ -537,6 +570,11 @@ void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve) ListBase chunks_temp; BLI_freenode *lasttail = NULL; +#ifdef WITH_MEM_VALGRIND + VALGRIND_DESTROY_MEMPOOL(pool); + VALGRIND_CREATE_MEMPOOL(pool, 0, false); +#endif + if (totelem_reserve == -1) { maxchunks = pool->maxchunks; } @@ -582,6 +620,10 @@ void BLI_mempool_destroy(BLI_mempool *pool) { mempool_chunk_free_all(&pool->chunks, pool->flag); +#ifdef WITH_MEM_VALGRIND + VALGRIND_DESTROY_MEMPOOL(pool); +#endif + if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { free(pool); } @@ -589,3 +631,10 @@ void BLI_mempool_destroy(BLI_mempool *pool) MEM_freeN(pool); } } + +#ifndef NDEBUG +void BLI_mempool_set_memory_debug(void) +{ + mempool_debug_memset = true; +} +#endif diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index 8707be46196..4b51aefbd87 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -31,14 +31,19 @@ #include "BLI_boxpack2d.h" /* own include */ +#ifdef __GNUC__ +# pragma GCC diagnostic error "-Wpadded" +#endif + /* BoxPacker for backing 2D rectangles into a square * * The defined Below are for internal use only */ - typedef struct BoxVert { float x; float y; - short free; + + int free; /* could be a char */ + unsigned int index; struct BoxPack *trb; /* top right box */ struct BoxPack *blb; /* bottom left box */ @@ -48,8 +53,6 @@ typedef struct BoxVert { /* Store last intersecting boxes here * speedup intersection testing */ struct BoxPack *isect_cache[4]; - - int index; } BoxVert; /* free vert flags */ @@ -156,13 +159,15 @@ static int vertex_sort(const void *p1, const void *p2) * len - the number of boxes in the array. * tot_width and tot_height are set so you can normalize the data. * */ -void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float *tot_height) +void BLI_box_pack_2d(BoxPack *boxarray, const unsigned int len, float *tot_width, float *tot_height) { - BoxVert *vert; /* the current vert */ - int box_index, verts_pack_len, i, j, k, isect; - int quad_flags[4] = {BLF, TRF, TLF, BRF}; /* use for looping */ + const int quad_flags[4] = {BLF, TRF, TLF, BRF}; /* use for looping */ + unsigned int box_index, verts_pack_len, i, j, k; + unsigned int *vertex_pack_indices; /* an array of indices used for sorting verts */ + bool isect; + BoxPack *box, *box_test; /*current box and another for intersection tests*/ - int *vertex_pack_indices; /*an array of indices used for sorting verts*/ + BoxVert *vert; /* the current vert */ if (!len) { *tot_width = 0.0f; @@ -184,7 +189,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~TRF; vert->trb = box; - vert->index = i; i++; + vert->index = i++; box->v[BL] = vert; vert++; vert->trb = vert->brb = vert->tlb = @@ -192,7 +197,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~BLF; vert->blb = box; - vert->index = i; i++; + vert->index = i++; box->v[TR] = vert; vert++; vert->trb = vert->blb = vert->tlb = @@ -200,7 +205,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~BRF; vert->brb = box; - vert->index = i; i++; + vert->index = i++; box->v[TL] = vert; vert++; vert->trb = vert->blb = vert->brb = @@ -208,7 +213,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * vert->isect_cache[2] = vert->isect_cache[3] = NULL; vert->free = CORNERFLAGS & ~TLF; vert->tlb = box; - vert->index = i; i++; + vert->index = i++; box->v[BR] = vert; vert++; } vert = NULL; @@ -247,7 +252,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * /* Pack the box in with the others */ /* sort the verts */ - isect = 1; + isect = true; for (i = 0; i < verts_pack_len && isect; i++) { vert = vertarray + vertex_pack_indices[i]; @@ -283,7 +288,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * /* Now we need to check that the box intersects * with any other boxes * Assume no intersection... */ - isect = 0; + isect = false; if ( /* Constrain boxes to positive X/Y values */ BOXLEFT(box) < 0.0f || BOXBOTTOM(box) < 0.0f || @@ -296,7 +301,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * * isect_cache that can store a pointer to a * box for each quadrant * big speedup */ - isect = 1; + isect = true; } else { /* do a full search for colliding box @@ -307,7 +312,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * /* Store the last intersecting here as cache * for faster checking next time around */ vert->isect_cache[j] = box_test; - isect = 1; + isect = true; break; } } @@ -320,7 +325,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const int len, float *tot_width, float * (*tot_height) = max_ff(BOXTOP(box), (*tot_height)); /* Place the box */ - vert->free &= (short)~quad_flags[j]; + vert->free &= ~quad_flags[j]; switch (j) { case TR: diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c index 8e22d6f1182..e89f7fd795b 100644 --- a/source/blender/blenlib/intern/lasso.c +++ b/source/blender/blenlib/intern/lasso.c @@ -63,7 +63,7 @@ bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves, } else { int pt[2] = {sx, sy}; - return isect_point_poly_v2_int(pt, mcords, moves); + return isect_point_poly_v2_int(pt, mcords, moves, true); } } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 65cfac86021..0d15eede9ea 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -712,7 +712,8 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2], } /* point in polygon (keep float and int versions in sync) */ -bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr) +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr, + const bool use_holes) { /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */ float angletot = 0.0; @@ -749,9 +750,18 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsign p1 = p2; } - return (fabsf(angletot) > 4.0f); + angletot = fabsf(angletot); + if (use_holes) { + const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f); + angletot -= nested * (float)(M_PI * 2.0); + return (angletot > 4.0f) != (nested % 2); + } + else { + return (angletot > 4.0f); + } } -bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr) +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned int nr, + const bool use_holes) { /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */ float angletot = 0.0; @@ -788,7 +798,15 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsign p1 = p2; } - return (fabsf(angletot) > 4.0f); + angletot = fabsf(angletot); + if (use_holes) { + const int nested = floorf((angletot / (float)(M_PI * 2.0)) + 0.00001f); + angletot -= nested * (float)(M_PI * 2.0); + return (angletot > 4.0f) != (nested % 2); + } + else { + return (angletot > 4.0f); + } } /* point in tri */ @@ -1979,6 +1997,59 @@ void plot_line_v2v2i(const int p1[2], const int p2[2], bool (*callback)(int, int } } +void fill_poly_v2i_n( + const int xmin, const int ymin, const int xmax, const int ymax, + const int verts[][2], const int nr, + void (*callback)(int, int, void *), void *userData) +{ + /* originally by Darel Rex Finley, 2007 */ + + int nodes, pixel_y, i, j, swap; + int *node_x = MEM_mallocN(sizeof(*node_x) * (nr + 1), __func__); + + /* Loop through the rows of the image. */ + for (pixel_y = ymin; pixel_y < ymax; pixel_y++) { + + /* Build a list of nodes. */ + nodes = 0; j = nr - 1; + for (i = 0; i < nr; i++) { + if ((verts[i][1] < pixel_y && verts[j][1] >= pixel_y) || + (verts[j][1] < pixel_y && verts[i][1] >= pixel_y)) + { + node_x[nodes++] = (int)(verts[i][0] + + ((double)(pixel_y - verts[i][1]) / (verts[j][1] - verts[i][1])) * + (verts[j][0] - verts[i][0])); + } + j = i; + } + + /* Sort the nodes, via a simple "Bubble" sort. */ + i = 0; + while (i < nodes - 1) { + if (node_x[i] > node_x[i + 1]) { + SWAP_TVAL(swap, node_x[i], node_x[i + 1]); + if (i) i--; + } + else { + i++; + } + } + + /* Fill the pixels between node pairs. */ + for (i = 0; i < nodes; i += 2) { + if (node_x[i] >= xmax) break; + if (node_x[i + 1] > xmin) { + if (node_x[i ] < xmin) node_x[i ] = xmin; + if (node_x[i + 1] > xmax) node_x[i + 1] = xmax; + for (j = node_x[i]; j < node_x[i + 1]; j++) { + callback(j - xmin, pixel_y - ymin, userData); + } + } + } + } + MEM_freeN(node_x); +} + /****************************** Axis Utils ********************************/ /** diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 6bac102e1b1..2eebe10dd58 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -286,7 +286,7 @@ void mat3_to_quat(float q[4], float wmat[3][3]) tr = 0.25 * (double)(1.0f + mat[0][0] + mat[1][1] + mat[2][2]); - if (tr > (double)FLT_EPSILON) { + if (tr > (double)1e-4f) { s = sqrt(tr); q[0] = (float)s; s = 1.0 / (4.0 * s); @@ -300,7 +300,7 @@ void mat3_to_quat(float q[4], float wmat[3][3]) q[1] = (float)(0.25 * s); s = 1.0 / s; - q[0] = (float)((double)(mat[2][1] - mat[1][2]) * s); + q[0] = (float)((double)(mat[1][2] - mat[2][1]) * s); q[2] = (float)((double)(mat[1][0] + mat[0][1]) * s); q[3] = (float)((double)(mat[2][0] + mat[0][2]) * s); } @@ -318,7 +318,7 @@ void mat3_to_quat(float q[4], float wmat[3][3]) q[3] = (float)(0.25 * s); s = 1.0 / s; - q[0] = (float)((double)(mat[1][0] - mat[0][1]) * s); + q[0] = (float)((double)(mat[0][1] - mat[1][0]) * s); q[1] = (float)((double)(mat[2][0] + mat[0][2]) * s); q[2] = (float)((double)(mat[2][1] + mat[1][2]) * s); } diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 2f94e833e9d..5b9fefe77bb 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -42,7 +42,7 @@ /* local */ static float noise3_perlin(float vec[3]); -//static float turbulence_perlin(float *point, float lofreq, float hifreq); +//static float turbulence_perlin(const float point[3], float lofreq, float hifreq); //static float turbulencep(float noisesize, float x, float y, float z, int nr); /* UNUSED */ @@ -50,7 +50,7 @@ static float noise3_perlin(float vec[3]); /* needed for voronoi */ #define HASHPNT(x, y, z) hashpntf + 3 * hash[(hash[(hash[(z) & 255] + (y)) & 255] + (x)) & 255] -static float hashpntf[768] = { +static const float hashpntf[768] = { 0.536902, 0.020915, 0.501445, 0.216316, 0.517036, 0.822466, 0.965315, 0.377313, 0.678764, 0.744545, 0.097731, 0.396357, 0.247202, 0.520897, 0.613396, 0.542124, 0.146813, 0.255489, 0.810868, 0.638641, 0.980742, @@ -163,7 +163,7 @@ static float hashpntf[768] = { 0.114246, 0.905043, 0.713870, 0.555261, 0.951333 }; -unsigned char hash[512] = { +const unsigned char hash[512] = { 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, @@ -194,7 +194,7 @@ unsigned char hash[512] = { }; -float hashvectf[768] = { +const float hashvectf[768] = { 0.33783, 0.715698, -0.611206, -0.944031, -0.326599, -0.045624, -0.101074, -0.416443, -0.903503, 0.799286, 0.49411, -0.341949, -0.854645, 0.518036, 0.033936, 0.42514, -0.437866, -0.792114, -0.358948, 0.597046, 0.717377, -0.985413, 0.144714, 0.089294, -0.601776, -0.33728, -0.723907, -0.449921, 0.594513, 0.666382, 0.208313, -0.10791, 0.972076, @@ -327,7 +327,8 @@ static float newPerlinU(float x, float y, float z) /* Was BLI_hnoise(), removed noisesize, so other functions can call it without scaling. */ static float orgBlenderNoise(float x, float y, float z) { - register float cn1, cn2, cn3, cn4, cn5, cn6, i, *h; + register float cn1, cn2, cn3, cn4, cn5, cn6, i; + register const float *h; float fx, fy, fz, ox, oy, oz, jx, jy, jz; float n = 0.5; int ix, iy, iz, b00, b01, b10, b11, b20, b21; @@ -504,7 +505,7 @@ static const char p[512 + 2] = { }; -static float g[512 + 2][3] = { +static const float g[512 + 2][3] = { {0.33783, 0.715698, -0.611206}, {-0.944031, -0.326599, -0.045624}, {-0.101074, -0.416443, -0.903503}, @@ -1034,7 +1035,8 @@ static float g[512 + 2][3] = { static float noise3_perlin(float vec[3]) { int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11; - float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v; + float rx0, rx1, ry0, ry1, rz0, rz1, sx, sy, sz, a, b, c, d, t, u, v; + const float *q; register int i, j; @@ -1095,7 +1097,7 @@ static float noise3_perlin(float vec[3]) } #if 0 -static float turbulence_perlin(float *point, float lofreq, float hifreq) +static float turbulence_perlin(const float point[3], float lofreq, float hifreq) { float freq, t, p[3]; @@ -1227,7 +1229,7 @@ static float dist_Minkovsky(float x, float y, float z, float e) void voronoi(float x, float y, float z, float *da, float *pa, float me, int dtype) { int xx, yy, zz, xi, yi, zi; - float xd, yd, zd, d, *p; + float xd, yd, zd, d; float (*distfunc)(float, float, float, float); switch (dtype) { @@ -1262,7 +1264,7 @@ void voronoi(float x, float y, float z, float *da, float *pa, float me, int dtyp for (xx = xi - 1; xx <= xi + 1; xx++) { for (yy = yi - 1; yy <= yi + 1; yy++) { for (zz = zi - 1; zz <= zi + 1; zz++) { - p = HASHPNT(xx, yy, zz); + const float *p = HASHPNT(xx, yy, zz); xd = x - (p[0] + xx); yd = y - (p[1] + yy); zd = z - (p[2] + zz); @@ -1416,7 +1418,7 @@ void cellNoiseV(float x, float y, float z, float *ca) int xi = (int)(floor(x)); int yi = (int)(floor(y)); int zi = (int)(floor(z)); - float *p = HASHPNT(xi, yi, zi); + const float *p = HASHPNT(xi, yi, zi); ca[0] = p[0]; ca[1] = p[1]; ca[2] = p[2]; diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 19eb88f9e15..9790ce1f0b4 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -55,7 +55,7 @@ ((h) + (((hoff) = ((hoff) * 2) + 1), (hoff))) \ ) -extern unsigned int hashsizes[]; +extern const unsigned int hashsizes[]; void BLI_smallhash_init(SmallHash *hash) { diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c new file mode 100644 index 00000000000..7fa108b906f --- /dev/null +++ b/source/blender/blenlib/intern/task.c @@ -0,0 +1,424 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_task.h" +#include "BLI_threads.h" + +/* Types */ + +typedef struct Task { + struct Task *next, *prev; + + TaskRunFunction run; + void *taskdata; + bool free_taskdata; + TaskPool *pool; +} Task; + +struct TaskPool { + TaskScheduler *scheduler; + + volatile size_t num; + volatile size_t done; + ThreadMutex num_mutex; + ThreadCondition num_cond; + + void *userdata; + ThreadMutex user_mutex; + + volatile bool do_cancel; +}; + +struct TaskScheduler { + pthread_t *threads; + struct TaskThread *task_threads; + int num_threads; + + ListBase queue; + ThreadMutex queue_mutex; + ThreadCondition queue_cond; + + volatile bool do_exit; +}; + +typedef struct TaskThread { + TaskScheduler *scheduler; + int id; +} TaskThread; + +/* Task Scheduler */ + +static void task_pool_num_decrease(TaskPool *pool, size_t done) +{ + BLI_mutex_lock(&pool->num_mutex); + + BLI_assert(pool->num >= done); + + pool->num -= done; + pool->done += done; + + if (pool->num == 0) + BLI_condition_notify_all(&pool->num_cond); + + BLI_mutex_unlock(&pool->num_mutex); +} + +static void task_pool_num_increase(TaskPool *pool) +{ + BLI_mutex_lock(&pool->num_mutex); + + pool->num++; + BLI_condition_notify_all(&pool->num_cond); + + BLI_mutex_unlock(&pool->num_mutex); +} + +static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task) +{ + BLI_mutex_lock(&scheduler->queue_mutex); + + while (!scheduler->queue.first && !scheduler->do_exit) + BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); + + if (!scheduler->queue.first) { + BLI_mutex_unlock(&scheduler->queue_mutex); + BLI_assert(scheduler->do_exit); + return false; + } + + *task = scheduler->queue.first; + BLI_remlink(&scheduler->queue, *task); + + BLI_mutex_unlock(&scheduler->queue_mutex); + + return true; +} + +static void *task_scheduler_thread_run(void *thread_p) +{ + TaskThread *thread = (TaskThread *) thread_p; + TaskScheduler *scheduler = thread->scheduler; + int thread_id = thread->id; + Task *task; + + /* keep popping off tasks */ + while (task_scheduler_thread_wait_pop(scheduler, &task)) { + TaskPool *pool = task->pool; + + /* run task */ + task->run(pool, task->taskdata, thread_id); + + /* delete task */ + if (task->free_taskdata) + MEM_freeN(task->taskdata); + MEM_freeN(task); + + /* notify pool task was done */ + task_pool_num_decrease(pool, 1); + } + + return NULL; +} + +TaskScheduler *BLI_task_scheduler_create(int num_threads) +{ + TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler"); + + /* multiple places can use this task scheduler, sharing the same + * threads, so we keep track of the number of users. */ + scheduler->do_exit = false; + + scheduler->queue.first = scheduler->queue.last = NULL; + BLI_mutex_init(&scheduler->queue_mutex); + BLI_condition_init(&scheduler->queue_cond); + + if (num_threads == 0) { + /* automatic number of threads will be main thread + num cores */ + num_threads = BLI_system_thread_count(); + } + + /* main thread will also work, so we count it too */ + num_threads -= 1; + + /* launch threads that will be waiting for work */ + if (num_threads > 0) { + int i; + + scheduler->num_threads = num_threads; + scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads"); + scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * num_threads, "TaskScheduler task threads"); + + for (i = 0; i < num_threads; i++) { + TaskThread *thread = &scheduler->task_threads[i]; + thread->scheduler = scheduler; + thread->id = i + 1; + + if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { + fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); + MEM_freeN(thread); + } + } + } + + return scheduler; +} + +void BLI_task_scheduler_free(TaskScheduler *scheduler) +{ + Task *task; + + /* stop all waiting threads */ + BLI_mutex_lock(&scheduler->queue_mutex); + scheduler->do_exit = true; + BLI_condition_notify_all(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); + + /* delete threads */ + if (scheduler->threads) { + int i; + + for (i = 0; i < scheduler->num_threads; i++) { + if (pthread_join(scheduler->threads[i], NULL) != 0) + fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads); + } + + MEM_freeN(scheduler->threads); + } + + /* Delete task thread data */ + if (scheduler->task_threads) { + MEM_freeN(scheduler->task_threads); + } + + /* delete leftover tasks */ + for (task = scheduler->queue.first; task; task = task->next) { + if (task->free_taskdata) + MEM_freeN(task->taskdata); + } + BLI_freelistN(&scheduler->queue); + + /* delete mutex/condition */ + BLI_mutex_end(&scheduler->queue_mutex); + BLI_condition_end(&scheduler->queue_cond); + + MEM_freeN(scheduler); +} + +int BLI_task_scheduler_num_threads(TaskScheduler *scheduler) +{ + return scheduler->num_threads + 1; +} + +static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority) +{ + task_pool_num_increase(task->pool); + + /* add task to queue */ + BLI_mutex_lock(&scheduler->queue_mutex); + + if (priority == TASK_PRIORITY_HIGH) + BLI_addhead(&scheduler->queue, task); + else + BLI_addtail(&scheduler->queue, task); + + BLI_condition_notify_one(&scheduler->queue_cond); + BLI_mutex_unlock(&scheduler->queue_mutex); +} + +static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool) +{ + Task *task, *nexttask; + size_t done = 0; + + BLI_mutex_lock(&scheduler->queue_mutex); + + /* free all tasks from this pool from the queue */ + for (task = scheduler->queue.first; task; task = nexttask) { + nexttask = task->next; + + if (task->pool == pool) { + if (task->free_taskdata) + MEM_freeN(task->taskdata); + BLI_freelinkN(&scheduler->queue, task); + + done++; + } + } + + BLI_mutex_unlock(&scheduler->queue_mutex); + + /* notify done */ + task_pool_num_decrease(pool, done); +} + +/* Task Pool */ + +TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata) +{ + TaskPool *pool = MEM_callocN(sizeof(TaskPool), "TaskPool"); + + pool->scheduler = scheduler; + pool->num = 0; + pool->do_cancel = false; + + BLI_mutex_init(&pool->num_mutex); + BLI_condition_init(&pool->num_cond); + + pool->userdata = userdata; + BLI_mutex_init(&pool->user_mutex); + + /* Ensure malloc will go fine from threads, + * + * This is needed because we could be in main thread here + * and malloc could be non-threda safe at this point because + * no other jobs are running. + */ + BLI_begin_threaded_malloc(); + + return pool; +} + +void BLI_task_pool_free(TaskPool *pool) +{ + BLI_task_pool_stop(pool); + + BLI_mutex_end(&pool->num_mutex); + BLI_condition_end(&pool->num_cond); + + BLI_mutex_end(&pool->user_mutex); + + MEM_freeN(pool); + + BLI_end_threaded_malloc(); +} + +void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, + void *taskdata, bool free_taskdata, TaskPriority priority) +{ + Task *task = MEM_callocN(sizeof(Task), "Task"); + + task->run = run; + task->taskdata = taskdata; + task->free_taskdata = free_taskdata; + task->pool = pool; + + task_scheduler_push(pool->scheduler, task, priority); +} + +void BLI_task_pool_work_and_wait(TaskPool *pool) +{ + TaskScheduler *scheduler = pool->scheduler; + + BLI_mutex_lock(&pool->num_mutex); + + while (pool->num != 0) { + Task *task, *work_task = NULL; + bool found_task = false; + + BLI_mutex_unlock(&pool->num_mutex); + + BLI_mutex_lock(&scheduler->queue_mutex); + + /* find task from this pool. if we get a task from another pool, + * we can get into deadlock */ + + for (task = scheduler->queue.first; task; task = task->next) { + if (task->pool == pool) { + work_task = task; + found_task = true; + BLI_remlink(&scheduler->queue, task); + break; + } + } + + BLI_mutex_unlock(&scheduler->queue_mutex); + + /* if found task, do it, otherwise wait until other tasks are done */ + if (found_task) { + /* run task */ + work_task->run(pool, work_task->taskdata, 0); + + /* delete task */ + if (work_task->free_taskdata) + MEM_freeN(work_task->taskdata); + MEM_freeN(work_task); + + /* notify pool task was done */ + task_pool_num_decrease(pool, 1); + } + + BLI_mutex_lock(&pool->num_mutex); + if (pool->num == 0) + break; + + if (!found_task) + BLI_condition_wait(&pool->num_cond, &pool->num_mutex); + } + + BLI_mutex_unlock(&pool->num_mutex); +} + +void BLI_task_pool_cancel(TaskPool *pool) +{ + pool->do_cancel = true; + + task_scheduler_clear(pool->scheduler, pool); + + /* wait until all entries are cleared */ + BLI_mutex_lock(&pool->num_mutex); + while (pool->num) + BLI_condition_wait(&pool->num_cond, &pool->num_mutex); + BLI_mutex_unlock(&pool->num_mutex); + + pool->do_cancel = false; +} + +void BLI_task_pool_stop(TaskPool *pool) +{ + task_scheduler_clear(pool->scheduler, pool); + + BLI_assert(pool->num == 0); +} + +bool BLI_task_pool_cancelled(TaskPool *pool) +{ + return pool->do_cancel; +} + +void *BLI_task_pool_userdata(TaskPool *pool) +{ + return pool->userdata; +} + +ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool) +{ + return &pool->user_mutex; +} + +size_t BLI_task_pool_tasks_done(TaskPool *pool) +{ + return pool->done; +} + diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index c8b84d9310a..64682965649 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -37,6 +37,7 @@ #include "BLI_listbase.h" #include "BLI_gsqueue.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "PIL_time.h" @@ -63,6 +64,9 @@ extern pthread_key_t gomp_tls_key; static void *thread_tls_data; #endif +/* We're using one global task scheduler for all kind of tasks. */ +static TaskScheduler *task_scheduler = NULL; + /* ********** basic thread control API ************ * * Many thread cases have an X amount of jobs, and only an Y amount of @@ -151,9 +155,26 @@ void BLI_threadapi_init(void) void BLI_threadapi_exit(void) { + if (task_scheduler) { + BLI_task_scheduler_free(task_scheduler); + } BLI_spin_end(&_malloc_lock); } +TaskScheduler *BLI_task_scheduler_get(void) +{ + if (task_scheduler == NULL) { + int tot_thread = BLI_system_thread_count(); + + /* Do a lazy initialization, so it happes after + * command line arguments parsing + */ + task_scheduler = BLI_task_scheduler_create(tot_thread); + } + + return task_scheduler; +} + /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) * problem otherwise: scene render will kill of the mutex! */ @@ -419,6 +440,11 @@ void BLI_mutex_unlock(ThreadMutex *mutex) pthread_mutex_unlock(mutex); } +bool BLI_mutex_trylock(ThreadMutex *mutex) +{ + return (pthread_mutex_trylock(mutex) == 0); +} + void BLI_mutex_end(ThreadMutex *mutex) { pthread_mutex_destroy(mutex); @@ -563,97 +589,31 @@ void BLI_ticket_mutex_unlock(TicketMutex *ticket) /* ************************************************ */ -typedef struct ThreadedWorker { - ListBase threadbase; - void *(*work_fnct)(void *); - char busy[RE_MAX_THREAD]; - int total; - int sleep_time; -} ThreadedWorker; - -typedef struct WorkParam { - ThreadedWorker *worker; - void *param; - int index; -} WorkParam; +/* Condition */ -static void *exec_work_fnct(void *v_param) +void BLI_condition_init(ThreadCondition *cond) { - WorkParam *p = (WorkParam *)v_param; - void *value; - - value = p->worker->work_fnct(p->param); - - p->worker->busy[p->index] = 0; - MEM_freeN(p); - - return value; + pthread_cond_init(cond, NULL); } -ThreadedWorker *BLI_create_worker(void *(*do_thread)(void *), int tot, int sleep_time) +void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex) { - ThreadedWorker *worker; - - (void)sleep_time; /* unused */ - - worker = MEM_callocN(sizeof(ThreadedWorker), "threadedworker"); - - if (tot > RE_MAX_THREAD) { - tot = RE_MAX_THREAD; - } - else if (tot < 1) { - tot = 1; - } - - worker->total = tot; - worker->work_fnct = do_thread; - - BLI_init_threads(&worker->threadbase, exec_work_fnct, tot); - - return worker; + pthread_cond_wait(cond, mutex); } -void BLI_end_worker(ThreadedWorker *worker) +void BLI_condition_notify_one(ThreadCondition *cond) { - BLI_remove_threads(&worker->threadbase); + pthread_cond_signal(cond); } -void BLI_destroy_worker(ThreadedWorker *worker) +void BLI_condition_notify_all(ThreadCondition *cond) { - BLI_end_worker(worker); - BLI_freelistN(&worker->threadbase); - MEM_freeN(worker); + pthread_cond_broadcast(cond); } -void BLI_insert_work(ThreadedWorker *worker, void *param) +void BLI_condition_end(ThreadCondition *cond) { - WorkParam *p = MEM_callocN(sizeof(WorkParam), "workparam"); - int index; - - if (BLI_available_threads(&worker->threadbase) == 0) { - index = worker->total; - while (index == worker->total) { - PIL_sleep_ms(worker->sleep_time); - - for (index = 0; index < worker->total; index++) { - if (worker->busy[index] == 0) { - BLI_remove_thread_index(&worker->threadbase, index); - break; - } - } - } - } - else { - index = BLI_available_thread_index(&worker->threadbase); - } - - worker->busy[index] = 1; - - p->param = param; - p->index = index; - p->worker = worker; - - BLI_insert_thread(&worker->threadbase, p); + pthread_cond_destroy(cond); } /* ************************************************ */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d3b2e382388..40d442f4e0b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1776,6 +1776,27 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData } } +#define IDP_DirectLinkGroup_OrFree(prop, switch_endian, fd) \ + _IDP_DirectLinkGroup_OrFree(prop, switch_endian, fd, __func__) + +static void _IDP_DirectLinkGroup_OrFree(IDProperty **prop, int switch_endian, FileData *fd, + const char *caller_func_id) +{ + if (*prop) { + if ((*prop)->type == IDP_GROUP) { + IDP_DirectLinkGroup(*prop, switch_endian, fd); + } + else { + /* corrupt file! */ + printf("%s: found non group data, freeing type %d!\n", + caller_func_id, (*prop)->type); + /* don't risk id, data's likely corrupt. */ + // IDP_FreeProperty(*prop); + *prop = NULL; + } + } +} + /* stub function */ static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endian), FileData *UNUSED(fd)) { @@ -1788,9 +1809,8 @@ static void direct_link_id(FileData *fd, ID *id) /*link direct data of ID properties*/ if (id->properties) { id->properties = newdataadr(fd, id->properties); - if (id->properties) { /* this case means the data was written incorrectly, it should not happen */ - IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - } + /* this case means the data was written incorrectly, it should not happen */ + IDP_DirectLinkGroup_OrFree(&id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } } @@ -2041,7 +2061,7 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list) FMod_Python *data = (FMod_Python *)fcm->data; data->prop = newdataadr(fd, data->prop); - IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } break; } @@ -2596,8 +2616,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) static void direct_link_node_socket(FileData *fd, bNodeSocket *sock) { sock->prop = newdataadr(fd, sock->prop); - if (sock->prop) - IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); sock->link = newdataadr(fd, sock->link); sock->typeinfo = NULL; @@ -2635,8 +2654,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree) link_list(fd, &node->outputs); node->prop = newdataadr(fd, node->prop); - if (node->prop) - IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); link_list(fd, &node->internal_links); for (link = node->internal_links.first; link; link = link->next) { @@ -2794,8 +2812,7 @@ static void direct_link_constraints(FileData *fd, ListBase *lb) link_list(fd, &data->targets); data->prop = newdataadr(fd, data->prop); - if (data->prop) - IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); break; } case CONSTRAINT_TYPE_SPLINEIK: @@ -2894,8 +2911,7 @@ static void direct_link_bones(FileData *fd, Bone *bone) bone->parent = newdataadr(fd, bone->parent); bone->prop = newdataadr(fd, bone->prop); - if (bone->prop) - IDP_DirectLinkProperty(bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&bone->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); bone->flag &= ~BONE_DRAW_ACTIVE; @@ -4148,12 +4164,6 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) direct_link_customdata(fd, &mesh->fdata, mesh->totface); direct_link_customdata(fd, &mesh->ldata, mesh->totloop); direct_link_customdata(fd, &mesh->pdata, mesh->totpoly); - - if (mesh->mloopuv || mesh->mtpoly) { - /* for now we have to ensure texpoly and mloopuv layers are aligned - * in the future we may allow non-aligned layers */ - BKE_mesh_cd_validate(mesh); - } mesh->bb = NULL; mesh->edit_btmesh = NULL; @@ -4163,6 +4173,12 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) mesh->totselect = 0; } + if (mesh->mloopuv || mesh->mtpoly) { + /* for now we have to ensure texpoly and mloopuv layers are aligned + * in the future we may allow non-aligned layers */ + BKE_mesh_cd_validate(mesh); + } + /* Multires data */ mesh->mr= newdataadr(fd, mesh->mr); if (mesh->mr) { @@ -4534,8 +4550,7 @@ static void direct_link_pose(FileData *fd, bPose *pose) direct_link_constraints(fd, &pchan->constraints); pchan->prop = newdataadr(fd, pchan->prop); - if (pchan->prop) - IDP_DirectLinkProperty(pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&pchan->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); pchan->mpath = newdataadr(fd, pchan->mpath); if (pchan->mpath) @@ -5438,10 +5453,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) } if (sce->r.ffcodecdata.properties) { sce->r.ffcodecdata.properties = newdataadr(fd, sce->r.ffcodecdata.properties); - if (sce->r.ffcodecdata.properties) { - IDP_DirectLinkProperty(sce->r.ffcodecdata.properties, - (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - } + IDP_DirectLinkGroup_OrFree(&sce->r.ffcodecdata.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } link_list(fd, &(sce->markers)); @@ -6135,8 +6147,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) ui_list->type = NULL; ui_list->dyn_data = NULL; ui_list->properties = newdataadr(fd, ui_list->properties); - if (ui_list->properties) - IDP_DirectLinkProperty(ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } if (spacetype == SPACE_EMPTY) { @@ -9702,11 +9713,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 269, 1)) { + /* Removal of Cycles SSS Compatible falloff */ + FOREACH_NODETREE(main, ntree, id) { + if (ntree->type == NTREE_SHADER) { + bNode *node; + for (node = ntree->nodes.first; node; node = node->next) { + if (node->type == SH_NODE_SUBSURFACE_SCATTERING) { + if (node->custom1 == SHD_SUBSURFACE_COMPATIBLE) { + node->custom1 = SHD_SUBSURFACE_CUBIC; + } + } + } + } + } FOREACH_NODETREE_END + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */ - /* don't forget to set version number in blender.c! */ + /* don't forget to set version number in BKE_blender.h! */ } #if 0 // XXX: disabled for now... we still don't have this in the right place in the loading code for it to work @@ -9762,8 +9789,7 @@ static void lib_link_all(FileData *fd, Main *main) static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi) { kmi->properties = newdataadr(fd, kmi->properties); - if (kmi->properties) - IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + IDP_DirectLinkGroup_OrFree(&kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); kmi->ptr = NULL; kmi->flag &= ~KMI_UPDATE; } @@ -9820,9 +9846,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) for (addon = user->addons.first; addon; addon = addon->next) { addon->prop = newdataadr(fd, addon->prop); - if (addon->prop) { - IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - } + IDP_DirectLinkGroup_OrFree(&addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } // XXX diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index f32215dbf03..067a8629906 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1994,15 +1994,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) while (sce) { if (sce->toolsettings == NULL) { sce->toolsettings = MEM_callocN(sizeof(struct ToolSettings), "Tool Settings Struct"); - sce->toolsettings->cornertype =0; - sce->toolsettings->degr = 90; - sce->toolsettings->step = 9; - sce->toolsettings->turn = 1; - sce->toolsettings->extr_offs = 1; sce->toolsettings->doublimit = 0.001f; - sce->toolsettings->segments = 32; - sce->toolsettings->rings = 32; - sce->toolsettings->vertices = 32; } sce = sce->id.next; } @@ -2149,9 +2141,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) } for (; sce; sce = sce->id.next) { - /* make 'innervert' the default subdivide type, for backwards compat */ - sce->toolsettings->cornertype = 1; - if (sce->r.scemode & R_PASSEPARTOUT) { set_passepartout = 1; sce->r.scemode &= ~R_PASSEPARTOUT; @@ -2238,11 +2227,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) ntree_version_241(sce->nodetree); /* uv calculation options moved to toolsettings */ - if (sce->toolsettings->uvcalc_radius == 0.0f) { - sce->toolsettings->uvcalc_radius = 1.0f; - sce->toolsettings->uvcalc_cubesize = 1.0f; - sce->toolsettings->uvcalc_mapdir = 1; - sce->toolsettings->uvcalc_mapalign = 1; + if (sce->toolsettings->unwrapper == 0) { sce->toolsettings->uvcalc_flag = UVCALC_FILLHOLES; sce->toolsettings->unwrapper = 1; } @@ -2343,8 +2328,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) for (sce = main->scene.first; sce; sce = sce->id.next) { if (sce->toolsettings->select_thresh == 0.0f) sce->toolsettings->select_thresh = 0.01f; - if (sce->toolsettings->clean_thresh == 0.0f) - sce->toolsettings->clean_thresh = 0.1f; if (sce->r.threads == 0) { if (sce->r.mode & R_THREADS) @@ -2554,14 +2537,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) sce->r.bake_flag = R_BAKE_CLEAR; } } - - if (main->subversionfile < 5) { - for (sce = main->scene.first; sce; sce = sce->id.next) { - /* improved triangle to quad conversion settings */ - if (sce->toolsettings->jointrilimit == 0.0f) - sce->toolsettings->jointrilimit = 0.8f; - } - } } if (main->versionfile <= 243) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b8d0857449b..44dc98fe537 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1737,7 +1737,7 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_ for (i = 0; i < count; ++i) { GridPaintMask *gpm = &grid_paint_mask[i]; if (gpm->data) { - const int gridsize = ccg_gridsize(gpm->level); + const int gridsize = BKE_ccg_gridsize(gpm->level); writedata(wd, DATA, sizeof(*gpm->data) * gridsize * gridsize, gpm->data); @@ -1809,7 +1809,7 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, CustomData_free(&data_tmp, count); } -static void write_meshs(WriteData *wd, ListBase *idbase) +static void write_meshes(WriteData *wd, ListBase *idbase) { Mesh *mesh; int save_for_old_blender= 0; @@ -3367,7 +3367,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil write_objects (wd, &mainvar->object); write_materials(wd, &mainvar->mat); write_textures (wd, &mainvar->tex); - write_meshs (wd, &mainvar->mesh); + write_meshes (wd, &mainvar->mesh); write_particlesettings(wd, &mainvar->particle); write_nodetrees(wd, &mainvar->nodetree); write_brushes (wd, &mainvar->brush); diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 930964667e9..1a7464ce340 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -500,10 +500,10 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, */ void BMO_remove_tagged_faces(BMesh *bm, const short oflag) { - BMFace *f; + BMFace *f, *f_next; BMIter iter; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { if (BMO_elem_flag_test(bm, f, oflag)) { BM_face_kill(bm, f); } @@ -512,10 +512,10 @@ void BMO_remove_tagged_faces(BMesh *bm, const short oflag) void BMO_remove_tagged_edges(BMesh *bm, const short oflag) { - BMEdge *e; + BMEdge *e, *e_next; BMIter iter; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, oflag)) { BM_edge_kill(bm, e); } @@ -524,10 +524,10 @@ void BMO_remove_tagged_edges(BMesh *bm, const short oflag) void BMO_remove_tagged_verts(BMesh *bm, const short oflag) { - BMVert *v; + BMVert *v, *v_next; BMIter iter; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, oflag)) { BM_vert_kill(bm, v); } diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 164a92125cd..8441a6ec75f 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2279,3 +2279,28 @@ BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep) BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep); return bmesh_urmv_loop(bm, l); } + +/** + * Avoid calling this where possible, + * low level function so both face pointers remain intact but point to swapped data. + * \note must be from the same bmesh. + */ +void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b) +{ + BMLoop *l_iter, *l_first; + + BLI_assert(f_a != f_b); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f_a); + do { + l_iter->f = f_b; + } while ((l_iter = l_iter->next) != l_first); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f_b); + do { + l_iter->f = f_a; + } while ((l_iter = l_iter->next) != l_first); + + SWAP(BMFace, (*f_a), (*f_b)); + bm->elem_index_dirty |= BM_FACE; +} diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index a18c2ebd32c..9e33509c2c8 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -87,4 +87,6 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); +void bmesh_face_swap_data(BMesh *bm, BMFace *f_a, BMFace *f_b); + #endif /* __BMESH_CORE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 4555de7b13d..91b9774634d 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -54,6 +54,32 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = { }; /** + * Utility function. + */ +int BM_iter_mesh_count(BMesh *bm, const char itype) +{ + int count; + + switch (itype) { + case BM_VERTS_OF_MESH: + count = bm->totvert; + break; + case BM_EDGES_OF_MESH: + count = bm->totedge; + break; + case BM_FACES_OF_MESH: + count = bm->totface; + break; + default: + count = 0; + BLI_assert(0); + break; + } + + return count; +} + +/** * \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays. */ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) @@ -304,36 +330,66 @@ int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const * VERT OF MESH CALLBACKS */ +/* see bug [#36923] for why we need this, + * allow adding but not removing, this isnt _totally_ safe since + * you could add/remove within the same loop, but catches common cases + */ +#ifdef DEBUG +# define USE_IMMUTABLE_ASSERT +#endif + void bmiter__vert_of_mesh_begin(struct BMIter__vert_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + ((BMIter *)iter)->count = iter->bm->totvert; +#endif BLI_mempool_iternew(iter->bm->vpool, &iter->pooliter); } void *bmiter__vert_of_mesh_step(struct BMIter__vert_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + BLI_assert(((BMIter *)iter)->count <= iter->bm->totvert); +#endif return BLI_mempool_iterstep(&iter->pooliter); } void bmiter__edge_of_mesh_begin(struct BMIter__edge_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + ((BMIter *)iter)->count = iter->bm->totedge; +#endif BLI_mempool_iternew(iter->bm->epool, &iter->pooliter); } void *bmiter__edge_of_mesh_step(struct BMIter__edge_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + BLI_assert(((BMIter *)iter)->count <= iter->bm->totedge); +#endif return BLI_mempool_iterstep(&iter->pooliter); } void bmiter__face_of_mesh_begin(struct BMIter__face_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + ((BMIter *)iter)->count = iter->bm->totface; +#endif BLI_mempool_iternew(iter->bm->fpool, &iter->pooliter); } void *bmiter__face_of_mesh_step(struct BMIter__face_of_mesh *iter) { +#ifdef USE_IMMUTABLE_ASSERT + BLI_assert(((BMIter *)iter)->count <= iter->bm->totface); +#endif return BLI_mempool_iterstep(&iter->pooliter); } +#ifdef USE_IMMUTABLE_ASSERT +# undef USE_IMMUTABLE_ASSERT +#endif + /* * EDGE OF VERT CALLBACKS */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index bb25d3fabd1..fdf0f27f05f 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -89,6 +89,20 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; #define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \ for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++) +/* a version of BM_ITER_MESH which keeps the next item in storage + * so we can delete the current item, see bug [#36923] */ +#ifdef DEBUG +# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ + for (ele = BM_iter_new(iter, bm, itype, NULL); \ + ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \ + (void)(ele_next = BM_iter_step(iter)), 1) : 0; \ + ele = ele_next) +#else +# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ + for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next) +#endif + + #define BM_ITER_ELEM(ele, iter, data, itype) \ for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter)) @@ -182,6 +196,7 @@ typedef struct BMIter { char itype; } BMIter; +int BM_iter_mesh_count(BMesh *bm, const char itype); void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 284ff3e759c..611ee4d03b8 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -1639,9 +1639,9 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, // BMOpDefine *def; char *opname, *ofmt, *fmt; char slot_name[64] = {0}; - int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state; + int i, type; + bool noslot, state; char htype; - int noslot = 0; /* basic useful info to help find where bmop formatting strings fail */ @@ -1662,7 +1662,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, i = strcspn(fmt, " "); opname = fmt; - if (!opname[i]) noslot = 1; + noslot = (opname[i] == '\0'); opname[i] = '\0'; fmt += i + (noslot ? 0 : 1); @@ -1679,7 +1679,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, // def = bmo_opdefines[i]; i = 0; - state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ + state = true; /* false: not inside slot_code name, true: inside slot_code name */ while (*fmt) { if (state) { @@ -1705,7 +1705,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BLI_strncpy(slot_name, fmt, sizeof(slot_name)); - state = 0; + state = false; fmt += i; } else { @@ -1726,13 +1726,13 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, else GOTO_ERROR("matrix size was not 3 or 4"); BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); - state = 1; + state = true; break; } case 'v': { BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); - state = 1; + state = true; break; } case 'e': /* single vert/edge/face */ @@ -1742,7 +1742,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BMO_slot_buffer_from_single(op, slot, ele); - state = 1; + state = true; break; } case 's': @@ -1761,20 +1761,20 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BMO_slot_copy(op_other, slots_out, slot_name_other, op, slots_in, slot_name); } - state = 1; + state = true; break; } case 'i': BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); - state = 1; + state = true; break; case 'b': BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); - state = 1; + state = true; break; case 'p': BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); - state = 1; + state = true; break; case 'f': case 'F': @@ -1787,15 +1787,16 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); } else { + bool stop = false; + htype = 0; - stop = 0; while (1) { switch (NEXT_CHAR(fmt)) { case 'f': htype |= BM_FACE; break; case 'e': htype |= BM_EDGE; break; case 'v': htype |= BM_VERT; break; default: - stop = 1; + stop = true; break; } if (stop) { @@ -1822,7 +1823,7 @@ bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, } } - state = 1; + state = true; break; default: fprintf(stderr, diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 2492dce05c7..e4c1180d433 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -30,10 +30,9 @@ #include "DNA_listBase.h" -#include "MEM_guardedalloc.h" - #include "BLI_alloca.h" #include "BLI_math.h" +#include "BLI_memarena.h" #include "BLI_scanfill.h" #include "BLI_listbase.h" @@ -801,195 +800,6 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3]) return crosses % 2 != 0; } -static bool bm_face_goodline(float const (*projectverts)[2], BMFace *f, int v1i, int v2i, int v3i) -{ - BMLoop *l_iter; - BMLoop *l_first; - - float pv1[2]; - const float *v1 = projectverts[v1i]; - const float *v2 = projectverts[v2i]; - const float *v3 = projectverts[v3i]; - int i; - - /* v3 must be on the left side of [v1, v2] line, else we know [v1, v3] is outside of f! */ - if (testedgesidef(v1, v2, v3)) { - return false; - } - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - i = BM_elem_index_get(l_iter->v); - copy_v2_v2(pv1, projectverts[i]); - - if (ELEM3(i, v1i, v2i, v3i)) { -#if 0 - printf("%d in (%d, %d, %d) tri (from indices!), continuing\n", i, v1i, v2i, v3i); -#endif - continue; - } - - if (isect_point_tri_v2(pv1, v1, v2, v3) || - isect_point_tri_v2(pv1, v3, v2, v1)) - { -#if 0 - if (isect_point_tri_v2(pv1, v1, v2, v3)) - printf("%d in (%d, %d, %d)\n", v3i, i, v1i, v2i); - else - printf("%d in (%d, %d, %d)\n", v1i, i, v3i, v2i); -#endif - return false; - } - } while ((l_iter = l_iter->next) != l_first); - return true; -} - -/** - * \brief Find Ear - * - * Used by tessellator to find the next triangle to 'clip off' of a polygon while tessellating. - * - * \param f The face to search. - * \param projectverts an array of face vert coords. - * \param use_beauty Currently only applies to quads, can be extended later on. - * \param abscoss Must be allocated by caller, and at least f->len length - * (allow to avoid allocating a new one for each tri!). - */ -static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use_beauty, float *abscoss) -{ - BMLoop *bestear = NULL; - - BMLoop *l_iter; - BMLoop *l_first; - - const float cos_threshold = 0.9f; - const float bias = 1.0f + 1e-6f; - - BLI_assert(BM_face_is_normal_valid(f)); - /* just triangulate degenerate faces */ - if (UNLIKELY(is_zero_v3(f->no))) { - return BM_FACE_FIRST_LOOP(f); - } - - if (f->len == 4) { - BMLoop *larr[4]; - int i = 0, i4; - float cos1, cos2; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - larr[i] = l_iter; - i++; - } while ((l_iter = l_iter->next) != l_first); - - /* pick 0/1 based on best length */ - /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ - i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > - len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); - i4 = (i + 3) % 4; - /* Check produced tris aren't too flat/narrow... - * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ - cos1 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i]->v->co, larr[i + 1]->v->co)); - cos2 = fabsf(cos_v3v3v3(larr[i4]->v->co, larr[i + 2]->v->co, larr[i + 1]->v->co)); -#if 0 - printf("%d, (%f, %f), (%f, %f)\n", i, cos1, cos2, - fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)), - fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co))); -#endif - if (cos1 < cos2) - cos1 = cos2; - - if (cos1 > cos_threshold) { - if (cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i4]->v->co, larr[i + 2]->v->co)) && - cos1 > fabsf(cos_v3v3v3(larr[i]->v->co, larr[i + 1]->v->co, larr[i + 2]->v->co))) - { - i = !i; - } - } - /* Last check we do not get overlapping triangles - * (as much as possible, there are some cases with no good solution!) */ - i4 = (i + 3) % 4; - if (!bm_face_goodline((float const (*)[2])projectverts, f, - BM_elem_index_get(larr[i4]->v), - BM_elem_index_get(larr[i]->v), - BM_elem_index_get(larr[i + 1]->v))) - { - i = !i; - } -/* printf("%d\n", i);*/ - bestear = larr[i]; - - } - else { - /* float angle, bestangle = 180.0f; */ - const int len = f->len; - float cos, cos_best = 1.0f; - int i, j; - - /* Compute cos of all corners! */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - const BMVert *v1 = l_iter->prev->v; - const BMVert *v2 = l_iter->v; - const BMVert *v3 = l_iter->next->v; - - abscoss[i] = fabsf(cos_v3v3v3(v1->co, v2->co, v3->co)); -/* printf("tcoss: %f\n", *tcoss);*/ - i++; - } while ((l_iter = l_iter->next) != l_first); - - i = 0; - l_iter = l_first; - do { - const BMVert *v1 = l_iter->prev->v; - const BMVert *v2 = l_iter->v; - const BMVert *v3 = l_iter->next->v; - - /* Compute highest cos (i.e. narrowest angle) of this tri. */ - cos = max_fff(abscoss[i], - fabsf(cos_v3v3v3(v2->co, v3->co, v1->co)), - fabsf(cos_v3v3v3(v3->co, v1->co, v2->co))); - - /* Compare to prev best (i.e. lowest) cos. */ - if (cos < cos_best) { - if (bm_face_goodline((float const (*)[2])projectverts, f, - BM_elem_index_get(v1), - BM_elem_index_get(v2), - BM_elem_index_get(v3))) - { - /* We must check this tri would not leave a (too much) degenerated remaining face! */ - /* For now just assume if the average of cos of all - * "remaining face"'s corners is below a given threshold, it's OK. */ - float cos_mean = fabsf(cos_v3v3v3(v1->co, v3->co, l_iter->next->next->v->co)); - const int i_limit = (i - 1 + len) % len; - cos_mean += fabsf(cos_v3v3v3(l_iter->prev->prev->v->co, v1->co, v3->co)); - j = (i + 2) % len; - do { - cos_mean += abscoss[j]; - } while ((j = (j + 1) % len) != i_limit); - cos_mean /= len - 1; - - /* We need a best ear in any case... */ - if (cos_mean < cos_threshold || (!bestear && cos_mean < 1.0f)) { - /* OKI, keep this ear (corner...) as a potential best one! */ - bestear = l_iter; - cos_best = cos; - } -#if 0 - else - printf("Had a nice tri (higest cos of %f, current cos_best is %f), " - "but average cos of all \"remaining face\"'s corners is too high (%f)!\n", - cos, cos_best, cos_mean); -#endif - } - } - i++; - } while ((l_iter = l_iter->next) != l_first); - } - - return bestear; -} - /** * \brief BMESH TRIANGULATE FACE * @@ -1003,63 +813,126 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use * * \note use_tag tags new flags and edges. */ +#define SF_EDGE_IS_BOUNDARY 0xff void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **r_faces_new, - const bool use_beauty, const bool use_tag) + MemArena *sf_arena, + const bool UNUSED(use_beauty), const bool use_tag) { - const float f_len_orig = f->len; - int i, nf_i = 0; - BMLoop *l_new; - BMLoop *l_iter; - BMLoop *l_first; - /* BM_face_triangulate: temp absolute cosines of face corners */ - float (*projectverts)[2] = BLI_array_alloca(projectverts, f_len_orig); - float *abscoss = BLI_array_alloca(abscoss, f_len_orig); - float mat[3][3]; + int nf_i = 0; + BMLoop *l_iter, *l_first, *l_new; + BMFace *f_new; BLI_assert(BM_face_is_normal_valid(f)); - axis_dominant_v3_to_m3(mat, f->no); - /* copy vertex coordinates to vertspace area */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - mul_v2_m3v3(projectverts[i], mat, l_iter->v->co); - BM_elem_index_set(l_iter->v, i++); /* set dirty! */ - } while ((l_iter = l_iter->next) != l_first); + if (f->len == 4) { + l_first = BM_FACE_FIRST_LOOP(f); - bm->elem_index_dirty |= BM_VERT; /* see above */ + f_new = BM_face_split(bm, f, l_first->v, l_first->next->next->v, &l_new, NULL, false); + copy_v3_v3(f_new->no, f->no); - while (f->len > 3) { - l_iter = poly_find_ear(f, projectverts, use_beauty, abscoss); + if (use_tag) { + BM_elem_flag_enable(l_new->e, BM_ELEM_TAG); + BM_elem_flag_enable(f_new, BM_ELEM_TAG); + } - /* force triangulation - if we can't find an ear the face is degenerate */ - if (l_iter == NULL) { - l_iter = BM_FACE_FIRST_LOOP(f); + if (r_faces_new) { + r_faces_new[nf_i++] = f_new; } + } + else if (f->len > 4) { + /* scanfill */ + ScanFillContext sf_ctx; + ScanFillVert *sf_vert, *sf_vert_prev = NULL; + ScanFillEdge *sf_edge; + ScanFillFace *sf_tri; + int totfilltri; -/* printf("Subdividing face...\n");*/ - f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &l_new, NULL, true); + /* populate scanfill */ + BLI_scanfill_begin_arena(&sf_ctx, sf_arena); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); - if (UNLIKELY(!f)) { - fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__); - break; - } + /* step once before entering the loop */ + sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co); + sf_vert->tmp.p = l_iter; + sf_vert_prev = sf_vert; + l_iter = l_iter->next; + + do { + sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co); + sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_vert); + sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY; + + sf_vert->tmp.p = l_iter; + sf_vert_prev = sf_vert; + } while ((l_iter = l_iter->next) != l_first); + + sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_prev, sf_ctx.fillvertbase.first); + sf_edge->tmp.c = SF_EDGE_IS_BOUNDARY; + + /* calculate filled triangles */ + totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no); + BLI_assert(totfilltri <= f->len - 2); - copy_v3_v3(f->no, l_iter->f->no); + + /* loop over calculated triangles and create new geometry */ + for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { + /* the order is reverse, otherwise the normal is flipped */ + BMLoop *l_tri[3] = { + sf_tri->v3->tmp.p, + sf_tri->v2->tmp.p, + sf_tri->v1->tmp.p}; + + BMVert *v_tri[3] = { + l_tri[0]->v, + l_tri[1]->v, + l_tri[2]->v}; + + f_new = BM_face_create_verts(bm, v_tri, 3, f, false, true); + l_new = BM_FACE_FIRST_LOOP(f_new); + + BLI_assert(v_tri[0] == l_new->v); + + /* copy CD data */ + BM_elem_attrs_copy(bm, bm, l_tri[0], l_new); + BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next); + BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev); + + /* add all but the last face which is swapped and removed (below) */ + if (sf_tri->next) { + if (use_tag) { + BM_elem_flag_enable(f_new, BM_ELEM_TAG); + } + if (r_faces_new && sf_tri->next) { + r_faces_new[nf_i++] = f_new; + } + } + } if (use_tag) { - BM_elem_flag_enable(l_new->e, BM_ELEM_TAG); - BM_elem_flag_enable(f, BM_ELEM_TAG); + ScanFillEdge *sf_edge; + for (sf_edge = sf_ctx.filledgebase.first; sf_edge; sf_edge = sf_edge->next) { + if (sf_edge->tmp.c != SF_EDGE_IS_BOUNDARY) { + BMLoop *l1 = sf_edge->v1->tmp.p; + BMLoop *l2 = sf_edge->v2->tmp.p; + + BMEdge *e = BM_edge_exists(l1->v, l2->v); + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + } } - if (r_faces_new) { - r_faces_new[nf_i++] = f; + if (sf_ctx.fillfacebase.first) { + /* we can't delete the real face, because some of the callers expect it to remain valid. + * so swap data and delete the last created tri */ + bmesh_face_swap_data(bm, f, f_new); + BM_face_kill(bm, f_new); } - } - BLI_assert(f->len == 3); + /* garbage collection */ + BLI_scanfill_end_arena(&sf_ctx, sf_arena); + } } /** diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 14fe1e76360..b7117621273 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -53,6 +53,7 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL(); bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces, + struct MemArena *sf_arena, const bool use_beauty, const bool use_tag) ATTR_NONNULL(1, 2); void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index a68d9ccd2bc..238b7b4aaaa 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -26,6 +26,8 @@ * BMesh Walker Code. */ +#include <string.h> + #include "BLI_utildefines.h" #include "BKE_customdata.h" @@ -34,6 +36,12 @@ #include "intern/bmesh_private.h" #include "intern/bmesh_walkers_private.h" +/* pop into stack memory (common operation) */ +#define BMW_state_remove_r(walker, owalk) { \ + memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \ + BMW_state_remove(walker); \ +} (void)0 + static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v) { if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { @@ -140,14 +148,16 @@ static void *bmw_ShellWalker_yield(BMWalker *walker) static void *bmw_ShellWalker_step(BMWalker *walker) { - BMwShellWalker *swalk = BMW_current_state(walker); + BMwShellWalker *swalk, owalk; BMEdge *e, *e2; BMVert *v; BMIter iter; int i; + BMW_state_remove_r(walker, &owalk); + swalk = &owalk; + e = swalk->curedge; - BMW_state_remove(walker); for (i = 0; i < 2; i++) { v = i ? e->v2 : e->v1; @@ -240,14 +250,15 @@ static void *bmw_ConnectedVertexWalker_yield(BMWalker *walker) static void *bmw_ConnectedVertexWalker_step(BMWalker *walker) { - BMwConnectedVertexWalker *vwalk = BMW_current_state(walker); + BMwConnectedVertexWalker *vwalk, owalk; BMVert *v, *v2; BMEdge *e; BMIter iter; - v = vwalk->curvert; + BMW_state_remove_r(walker, &owalk); + vwalk = &owalk; - BMW_state_remove(walker); + v = vwalk->curvert; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { v2 = BM_edge_other_vert(e, v); @@ -289,14 +300,19 @@ static void *bmw_IslandboundWalker_yield(BMWalker *walker) static void *bmw_IslandboundWalker_step(BMWalker *walker) { - BMwIslandboundWalker *iwalk = BMW_current_state(walker), owalk; + BMwIslandboundWalker *iwalk, owalk; BMVert *v; - BMEdge *e = iwalk->curloop->e; + BMEdge *e; BMFace *f; - BMLoop *l = iwalk->curloop; + BMLoop *l; /* int found = 0; */ - owalk = *iwalk; + memcpy(&owalk, BMW_current_state(walker), sizeof(owalk)); + /* normally we'd remove here, but delay until after error checking */ + iwalk = &owalk; + + l = iwalk->curloop; + e = l->e; v = BM_edge_other_vert(e, iwalk->lastv); @@ -307,7 +323,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) return NULL; } - /* pop off current stat */ + /* pop off current state */ BMW_state_remove(walker); f = l->f; @@ -381,13 +397,13 @@ static void *bmw_IslandWalker_yield(BMWalker *walker) static void *bmw_IslandWalker_step(BMWalker *walker) { - BMwIslandWalker *iwalk = BMW_current_state(walker); - /* BMwIslandWalker *owalk = iwalk; */ /* UNUSED */ + BMwIslandWalker *iwalk, owalk; BMIter iter, liter; - BMFace *f, *curf = iwalk->cur; + BMFace *f; BMLoop *l; - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + iwalk = &owalk; l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur); for ( ; l; l = BM_iter_step(&liter)) { @@ -419,7 +435,7 @@ static void *bmw_IslandWalker_step(BMWalker *walker) } } - return curf; + return owalk.cur; } @@ -507,15 +523,16 @@ static void *bmw_LoopWalker_yield(BMWalker *walker) static void *bmw_LoopWalker_step(BMWalker *walker) { - BMwLoopWalker *lwalk = BMW_current_state(walker), owalk; - BMEdge *e = lwalk->cur, *nexte = NULL; + BMwLoopWalker *lwalk, owalk; + BMEdge *e, *nexte = NULL; BMLoop *l; BMVert *v; int i = 0; - owalk = *lwalk; - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; + e = lwalk->cur; l = e->l; if (owalk.f_hub) { /* NGON EDGE */ @@ -770,13 +787,15 @@ static void *bmw_FaceLoopWalker_yield(BMWalker *walker) static void *bmw_FaceLoopWalker_step(BMWalker *walker) { - BMwFaceLoopWalker *lwalk = BMW_current_state(walker); - BMFace *f = lwalk->l->f; - BMLoop *l = lwalk->l, *origl = lwalk->l; + BMwFaceLoopWalker *lwalk, owalk; + BMFace *f; + BMLoop *l; - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; - l = l->radial_next; + f = lwalk->l->f; + l = lwalk->l->radial_next; if (lwalk->no_calc) { return f; @@ -797,7 +816,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) if (l->f->len != 4) { lwalk->no_calc = true; - lwalk->l = origl; + lwalk->l = owalk.l; } else { lwalk->no_calc = false; @@ -878,19 +897,21 @@ static void *bmw_EdgeringWalker_yield(BMWalker *walker) static void *bmw_EdgeringWalker_step(BMWalker *walker) { - BMwEdgeringWalker *lwalk = BMW_current_state(walker); - BMEdge *e, *wireedge = lwalk->wireedge; - BMLoop *l = lwalk->l, *origl = lwalk->l; + BMwEdgeringWalker *lwalk, owalk; + BMEdge *e; + BMLoop *l; #ifdef BMW_EDGERING_NGON int i, len; #endif #define EDGE_CHECK(e) (bmw_mask_check_edge(walker, e) && (BM_edge_is_boundary(e) || BM_edge_is_manifold(e))) - BMW_state_remove(walker); + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; + l = lwalk->l; if (!l) - return wireedge; + return lwalk->wireedge; e = l->e; if (!EDGE_CHECK(e)) { @@ -913,7 +934,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) if ((len <= 0) || (len % 2 != 0) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { - l = origl; + l = owalk.l; i = len; while (i > 0) { l = l->next; @@ -930,7 +951,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) l = l->next->next; if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { - l = origl->next->next; + l = owalk.l->next->next; } /* only walk to manifold edge */ if ((l->f->len == 4) && EDGE_CHECK(l->e) && @@ -975,17 +996,18 @@ static void *bmw_UVEdgeWalker_yield(BMWalker *walker) static void *bmw_UVEdgeWalker_step(BMWalker *walker) { - BMwUVEdgeWalker *lwalk = BMW_current_state(walker); + const int type = walker->bm->ldata.layers[walker->layer].type; + BMwUVEdgeWalker *lwalk, owalk; BMLoop *l, *l2, *l3, *nl, *cl; BMIter liter; void *d1, *d2; - int i, j, rlen, type; + int i, j, rlen; + + BMW_state_remove_r(walker, &owalk); + lwalk = &owalk; l = lwalk->l; nl = l->next; - type = walker->bm->ldata.layers[walker->layer].type; - - BMW_state_remove(walker); if (!bmw_mask_check_edge(walker, l->e)) { return l; diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index 9dfbf951fc0..10d15d93995 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -26,8 +26,6 @@ * Connect verts across faces (splits faces) and bridge tool. */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index b3a42ba533e..d0f64eb2892 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -26,8 +26,6 @@ * Connect verts across faces (splits faces). */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_alloca.h" diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c index 61085596acc..bd7a625406c 100644 --- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c +++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c @@ -26,8 +26,6 @@ * Connect verts non-planer faces iteratively (splits faces). */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_alloca.h" diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index d3c7a6864c3..cf36e88ea98 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -37,14 +37,21 @@ #include "intern/bmesh_operators_private.h" +/* ***_ISGC: mark for garbage-collection */ + #define FACE_MARK 1 #define FACE_ORIG 2 #define FACE_NEW 4 + #define EDGE_MARK 1 #define EDGE_TAG 2 +#define EDGE_ISGC 8 #define VERT_MARK 1 #define VERT_TAG 2 +#define VERT_ISGC 8 + + static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f) { @@ -232,14 +239,12 @@ cleanup: void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) { - /* might want to make this an option or mode - campbell */ - /* BMOperator fop; */ BMFace *act_face = bm->act_face; BMOIter eiter; - BMEdge *e; - BMIter viter; - BMVert *v; + BMIter iter; + BMEdge *e, *e_next; + BMVert *v, *v_next; const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split"); @@ -247,10 +252,10 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) if (use_face_split) { BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_TAG); - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - BMIter iter; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BMIter itersub; int untag_count = 0; - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + BM_ITER_ELEM (e, &itersub, v, BM_EDGES_OF_VERT) { if (!BMO_elem_flag_test(bm, e, EDGE_TAG)) { untag_count++; } @@ -266,22 +271,34 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } if (use_verts) { - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BMO_elem_flag_set(bm, v, VERT_MARK, (BM_vert_edge_count(v) != 2)); } } + /* tag all verts/edges connected to faces */ BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { - BMFace *fa, *fb; + BMFace *f_pair[2]; + if (BM_edge_face_pair(e, &f_pair[0], &f_pair[1])) { + unsigned int j; + for (j = 0; j < 2; j++) { + BMLoop *l_first, *l_iter; + l_iter = l_first = BM_FACE_FIRST_LOOP(f_pair[j]); + do { + BMO_elem_flag_enable(bm, l_iter->v, VERT_ISGC); + BMO_elem_flag_enable(bm, l_iter->e, EDGE_ISGC); + } while ((l_iter = l_iter->next) != l_first); + } + } + } + BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { + BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { BMFace *f_new; /* join faces */ - - /* BMESH_TODO - check on delaying edge removal since we may end up removing more than - * one edge, and later reference a removed edge */ - f_new = BM_faces_join_pair(bm, fa, fb, e, true); + f_new = BM_faces_join_pair(bm, fa, fb, e, false); if (f_new) { /* maintain active face */ @@ -292,8 +309,23 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } } + /* Cleanup geometry (#BM_faces_join_pair, but it removes geometry we're looping on) + * so do this in a separate pass instead. */ + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { + if ((e->l == NULL) && BMO_elem_flag_test(bm, e, EDGE_ISGC)) { + BM_edge_kill(bm, e); + } + } + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { + if ((v->e == NULL) && BMO_elem_flag_test(bm, v, VERT_ISGC)) { + BM_vert_kill(bm, v); + } + } + /* done with cleanup */ + + if (use_verts) { - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (BM_vert_edge_count(v) == 2) { BM_vert_collapse_edge(bm, v->e, v, true); @@ -349,7 +381,7 @@ static bool test_extra_verts(BMesh *bm, BMVert *v) void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) { BMIter iter, fiter; - BMVert *v; + BMVert *v, *v_next; BMFace *f; const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split"); @@ -361,7 +393,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) bm_face_split(bm, VERT_MARK); } - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { /* check if it's a two-valence ver */ if (BM_vert_edge_count(v) == 2) { @@ -409,7 +441,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) } /* clean up any remainin */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (!BM_vert_dissolve(bm, v)) { BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL); diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index bd2485b92fb..a5c34f7623b 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -26,8 +26,6 @@ * Duplicate, Split, Split operators. */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "BLI_alloca.h" diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index c58a11f21ec..de41bc7937d 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -28,13 +28,8 @@ #include "MEM_guardedalloc.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_array.h" -#include "BLI_alloca.h" -#include "BLI_smallhash.h" -#include "BLI_rand.h" -#include "BLI_heap.h" #include "bmesh.h" #include "bmesh_tools.h" @@ -44,10 +39,7 @@ #define EDGE_MARK 1 #define EDGE_VIS 2 -#define FACE_NEW 1 - #define ELE_NEW 1 -#define ELE_ORIG 4 void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) { diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c index f53b4536e44..fa77e6b509c 100644 --- a/source/blender/bmesh/operators/bmo_fill_attribute.c +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -27,8 +27,6 @@ * Fill in geometry with the attributes of their adjacent data. */ -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "BLI_linklist_stack.h" diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c index 8160d28d7a7..eadfbdb1aa8 100644 --- a/source/blender/bmesh/operators/bmo_fill_holes.c +++ b/source/blender/bmesh/operators/bmo_fill_holes.c @@ -26,8 +26,6 @@ * Fill boundary edge loop(s) with faces. */ -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "bmesh.h" diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 20cd828af1e..e20556a830d 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -31,7 +31,6 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" -#include "BLI_array.h" #include "BLI_alloca.h" #include "BLI_memarena.h" #include "BKE_customdata.h" diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 6d4f257909c..6562f26062f 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -203,7 +203,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMIter iter; BMOIter siter; BMFace *f; - BMEdge *e; + BMEdge *e, *e_next; /* data: edge-to-join, sort_value: error weight */ struct SortPointerByFloat *jedges; unsigned i, totedge; @@ -291,7 +291,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) MEM_freeN(jedges); /* join best weighted */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { BMFace *f_new; BMFace *f_a, *f_b; @@ -308,7 +308,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) } /* join 2-tri islands */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, EDGE_MARK)) { BMLoop *l_a, *l_b; BMFace *f_a, *f_b; @@ -326,7 +326,11 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) (BMO_elem_flag_test(bm, l_a->next->e, EDGE_MARK) == false) && (BMO_elem_flag_test(bm, l_a->prev->e, EDGE_MARK) == false) && (BMO_elem_flag_test(bm, l_b->next->e, EDGE_MARK) == false) && - (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false)) + (BMO_elem_flag_test(bm, l_b->prev->e, EDGE_MARK) == false) && + /* check for faces that use same verts, this is supported but raises an error + * and cancels the operation when performed from editmode, since this is only + * two triangles we only need to compare a single vertex */ + (LIKELY(l_a->prev->v != l_b->prev->v))) { BMFace *f_new; f_new = BM_faces_join_pair(bm, f_a, f_b, e, true); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 45653f3411f..6a540928d43 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -36,7 +36,7 @@ /* ************************ primitives ******************* */ -static float icovert[12][3] = { +static const float icovert[12][3] = { {0.0f, 0.0f, -200.0f}, {144.72f, -105.144f, -89.443f}, {-55.277f, -170.128, -89.443f}, @@ -51,7 +51,7 @@ static float icovert[12][3] = { {0.0f, 0.0f, 200.0f} }; -static short icoface[20][3] = { +static const short icoface[20][3] = { {0, 1, 2}, {1, 0, 5}, {0, 2, 3}, @@ -78,10 +78,10 @@ static short icoface[20][3] = { * this hack is only used so that scons & mingw + split-sources hack works * ------------------------------- start copied code */ /* these are not the monkeys you are looking for */ -static int monkeyo = 4; -static int monkeynv = 271; -static int monkeynf = 250; -static signed char monkeyv[271][3] = { +static const int monkeyo = 4; +static const int monkeynv = 271; +static const int monkeynf = 250; +static const signed char monkeyv[271][3] = { {-71, 21, 98}, {-63, 12, 88}, {-57, 7, 74}, {-82, -3, 79}, {-82, 4, 92}, {-82, 17, 100}, {-92, 21, 102}, {-101, 12, 95}, {-107, 7, 83}, {-117, 31, 84}, {-109, 31, 95}, {-96, 31, 102}, {-92, 42, 102}, diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 5ab909ffb0c..cc5a635092a 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -354,7 +354,7 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BMEdge *e, **edges = NULL; BLI_array_declare(edges); float min[3], max[3], center[3]; - int i, tot; + unsigned int i, tot; BMOpSlot *slot_targetmap; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); @@ -369,6 +369,8 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BMW_NIL_LAY); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BMVert *v_tar; + if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) continue; @@ -381,19 +383,29 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) minmax_v3v3_v3(min, max, e->v1->co); minmax_v3v3_v3(min, max, e->v2->co); + + /* prevent adding to slot_targetmap multiple times */ + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); } mid_v3_v3v3(center, min, max); /* snap edges to a point. for initial testing purposes anyway */ + v_tar = edges[0]->v1; + for (i = 0; i < tot; i++) { - copy_v3_v3(edges[i]->v1->co, center); - copy_v3_v3(edges[i]->v2->co, center); - - if (edges[i]->v1 != edges[0]->v1) - BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1); - if (edges[i]->v2 != edges[0]->v1) - BMO_slot_map_elem_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); + unsigned int j; + + for (j = 0; j < 2; j++) { + BMVert *v_src = *((&edges[i]->v1) + j); + + copy_v3_v3(v_src->co, center); + if ((v_src != v_tar) && !BM_elem_flag_test(v_src, BM_ELEM_TAG)) { + BM_elem_flag_enable(v_src, BM_ELEM_TAG); + BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_src, v_tar); + } + } } } diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index 4b538dccb4e..5c1b4287c2f 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -26,9 +26,6 @@ * Makes the mesh symmetrical by splitting along an axis and duplicating the geometry. */ - -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "BLI_math.h" @@ -59,7 +56,7 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) copy_v3_fl(plane_no, 0.0f); copy_v3_fl(scale, 1.0f); - plane_no[axis] = direction > 2 ? 1.0f : -1.0f; + plane_no[axis] = direction > 2 ? -1.0f : 1.0f; scale[axis] *= -1.0f; /* Cut in half */ diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index 590b5ea97c4..ca45289520b 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -26,7 +26,6 @@ * Triangulate faces, also defines triangle fill. */ -#include "MEM_guardedalloc.h" #include "DNA_listBase.h" #include "BLI_math.h" diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index e23358bf4ff..c89fee71cbc 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -32,7 +32,6 @@ #include "DNA_meshdata_types.h" #include "BLI_math.h" -#include "BLI_heap.h" #include "BLI_alloca.h" #include "BKE_customdata.h" diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 1463b3155c0..bb3fe129e0b 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1207,8 +1207,12 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) f = boundvert_rep_face(v); f2 = boundvert_rep_face(v->next); if (!v->any_seam) { - for (ring = 1; ring < ns2; ring++) - bev_merge_uvs(bm, mesh_vert(vm, i, ring, ns2)->v); + for (ring = 1; ring < ns2; ring++) { + BMVert *v_uv = mesh_vert(vm, i, ring, ns2)->v; + if (v_uv) { + bev_merge_uvs(bm, v_uv); + } + } } } while ((v = v->next) != vm->boundstart); if (!bv->any_seam) @@ -2371,7 +2375,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, const struct MDeformVert *dvert, const int vertex_group) { BMIter iter; - BMVert *v; + BMVert *v, *v_next; BMEdge *e; BevelParams bp = {NULL}; @@ -2385,7 +2389,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, if (bp.offset > 0) { /* primary alloc */ bp.vert_hash = BLI_ghash_ptr_new(__func__); - bp.mem_arena = BLI_memarena_new((1 << 16), __func__); + bp.mem_arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), __func__); BLI_memarena_use_calloc(bp.mem_arena); if (limit_offset) @@ -2414,7 +2418,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, } } - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { BLI_assert(find_bevvert(&bp, v) != NULL); BM_vert_kill(bm, v); diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c index 3baf8675a0d..9cfe17d6413 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.c +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -39,7 +39,6 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" -#include "BLI_mempool.h" #include "BLI_linklist.h" #include "BLI_linklist_stack.h" #include "BLI_math.h" @@ -122,9 +121,6 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con l_first = BM_FACE_FIRST_LOOP(f); - (void)bm; - (void)plane; - /* add plane-aligned verts to the stack * and check we have verts from both sides in this face, * ... that the face doesn't only have boundry verts on the plane for eg. */ @@ -238,7 +234,7 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)], face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]); - if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig)) { + if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig, false)) { BMLoop *l_a, *l_b; bool found = false; unsigned int j; diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index bc9288f98f6..868caa49ec7 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -197,7 +197,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool } for (iter_step = 0; iter_step < iterations; iter_step++) { - BMVert *v; + BMVert *v, *v_next; bool iter_done; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -318,7 +318,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ iter_done = false; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { if (bm_vert_dissolve_fan(bm, v)) { iter_done = true; diff --git a/source/blender/bmesh/tools/bmesh_triangulate.c b/source/blender/bmesh/tools/bmesh_triangulate.c index 2eacf62d68a..34ff493a026 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.c +++ b/source/blender/bmesh/tools/bmesh_triangulate.c @@ -31,6 +31,9 @@ #include "BLI_utildefines.h" #include "BLI_alloca.h" +#include "BLI_memarena.h" +#include "BLI_listbase.h" +#include "BLI_scanfill.h" #include "bmesh.h" @@ -39,14 +42,14 @@ /** * a version of #BM_face_triangulate that maps to #BMOpSlot */ -static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, const bool use_beauty, const bool use_tag, +static void bm_face_triangulate_mapping(BMesh *bm, BMFace *face, MemArena *sf_arena, const bool use_beauty, const bool use_tag, BMOperator *op, BMOpSlot *slot_facemap_out) { const int faces_array_tot = face->len - 3; BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot); BLI_assert(face->len > 3); - BM_face_triangulate(bm, face, faces_array, use_beauty, use_tag); + BM_face_triangulate(bm, face, faces_array, sf_arena, use_beauty, use_tag); if (faces_array) { int i; @@ -63,13 +66,16 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only, { BMIter iter; BMFace *face; + MemArena *sf_arena; + + sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); if (slot_facemap_out) { /* same as below but call: bm_face_triangulate_mapping() */ BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { if (face->len > 3) { if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) { - bm_face_triangulate_mapping(bm, face, use_beauty, tag_only, + bm_face_triangulate_mapping(bm, face, sf_arena, use_beauty, tag_only, op, slot_facemap_out); } } @@ -79,9 +85,11 @@ void BM_mesh_triangulate(BMesh *bm, const bool use_beauty, const bool tag_only, BM_ITER_MESH (face, &iter, bm, BM_FACES_OF_MESH) { if (face->len > 3) { if (tag_only == false || BM_elem_flag_test(face, BM_ELEM_TAG)) { - BM_face_triangulate(bm, face, NULL, use_beauty, tag_only); + BM_face_triangulate(bm, face, NULL, sf_arena, use_beauty, tag_only); } } } } + + BLI_memarena_free(sf_arena); } diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index bcbcdd42752..c1b6dc83139 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -963,10 +963,10 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj else copy_m4_m4(mat, pchan->pose_mat); - // SECOND_LIFE_COMPATIBILITY + // OPEN_SIM_COMPATIBILITY // AFAIK animation to second life is via BVH, but no // reason to not have the collada-animation be correct - if (export_settings->second_life) { + if (export_settings->open_sim) { float temp[4][4]; copy_m4_m4(temp, bone->arm_mat); temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 438421ccd14..174331c4644 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -193,11 +193,11 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, // and not it's head, seems arbitrary. (*i)->parentinv[3][1] += bone->length; - // SECOND_LIFE_COMPATIBILITY + // OPEN_SIM_COMPATIBILITY // TODO: when such objects are animated as // single matrix the tweak must be applied // to the result. - if (export_settings->second_life) { + if (export_settings->open_sim) { // tweak objects parentinverse to match compatibility float temp[4][4]; @@ -272,8 +272,8 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW: copy_m4_m4(mat, bone->arm_mat); } - // SECOND_LIFE_COMPATIBILITY - if (export_settings->second_life) { + // OPEN_SIM_COMPATIBILITY + if (export_settings->open_sim) { // Remove rotations vs armature from transform // parent_rest_rot * mat * irest_rot float temp[4][4]; diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index d04ed8d6fa1..948a3dc5ae1 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -507,8 +507,8 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas float world[4][4]; float inv_bind_mat[4][4]; - // SECOND_LIFE_COMPATIBILITY - if (export_settings->second_life) { + // OPEN_SIM_COMPATIBILITY + if (export_settings->open_sim) { // Only translations, no rotation vs armature float temp[4][4]; unit_m4(temp); diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index f9eb4cbc26f..3dc7e74379e 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -50,7 +50,7 @@ public: bool use_object_instantiation; bool sort_by_name; BC_export_transformation_type export_transformation_type; - bool second_life; + bool open_sim; char *filepath; LinkNode *export_set; diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 85bbaf4748f..223ab3eca2a 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -79,7 +79,7 @@ int collada_export(Scene *sce, int use_object_instantiation, int sort_by_name, BC_export_transformation_type export_transformation_type, - int second_life) + int open_sim) { ExportSettings export_settings; @@ -102,7 +102,7 @@ int collada_export(Scene *sce, export_settings.use_object_instantiation = use_object_instantiation != 0; export_settings.sort_by_name = sort_by_name != 0; export_settings.export_transformation_type = export_transformation_type; - export_settings.second_life = second_life != 0; + export_settings.open_sim = open_sim != 0; int includeFilter = OB_REL_NONE; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index b3a8156b6fe..e96bc2ea8a4 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -77,7 +77,7 @@ int collada_export(Scene *sce, int use_object_instantiation, int sort_by_name, BC_export_transformation_type export_transformation_type, - int second_life); + int open_sim); diff --git a/source/blender/collada/version.conf b/source/blender/collada/version.conf new file mode 100644 index 00000000000..d39af7a53df --- /dev/null +++ b/source/blender/collada/version.conf @@ -0,0 +1 @@ +463ba8a2ef5a021ce21df614dde29e0ee800e10b diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 4bebf004a89..f10e6696c6a 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -179,7 +179,7 @@ void MemoryBuffer::addPixel(int x, int y, const float color[4]) // table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2 // used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible #define EWA_MAXIDX 255 -static float EWA_WTS[EWA_MAXIDX + 1] = { +static const float EWA_WTS[EWA_MAXIDX + 1] = { 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 041a2c2216e..09b6e7d2206 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1546,7 +1546,9 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data for (srl = sce->r.layers.first; srl; srl = srl->next) { for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { - lineset->linestyle->id.flag |= LIB_DOIT; + if (lineset->linestyle) { + lineset->linestyle->id.flag |= LIB_DOIT; + } } } @@ -1562,8 +1564,11 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data ListBase tmp_data = {NULL, NULL}; size_t tmp_items = 0; - if (!(linestyle->id.flag & LIB_DOIT)) + if ((linestyle == NULL) || + !(linestyle->id.flag & LIB_DOIT)) + { continue; + } linestyle->id.flag &= ~LIB_DOIT; /* add scene-level animation channels */ diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 3c8576be312..34246427b7e 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -1380,7 +1380,7 @@ static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, const wm RNA_string_set(op->ptr, "name", marker->name); /* now see if the operator is usable */ - return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup); + return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup_confirm); } static void MARKER_OT_rename(wmOperatorType *ot) diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index decbc351cad..71717284d8e 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -396,7 +396,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac) int filter; /* when not in graph view, don't use handles */ SpaceIpo *sipo = (ac->spacetype == SPACE_IPO) ? (SpaceIpo *)ac->sl : NULL; - const short use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : FALSE; + const bool use_handle = sipo ? !(sipo->flag & SIPO_NOHANDLES) : false; /* filter animation data */ filter = ANIMFILTER_DATA_VISIBLE; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 70361f00004..6b9200afb75 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -61,6 +61,7 @@ #include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_main.h" +#include "BKE_idcode.h" #include "BKE_nla.h" #include "BKE_global.h" #include "BKE_context.h" @@ -141,9 +142,18 @@ bAction *verify_adt_action(ID *id, short add) /* init action if none available yet */ /* TODO: need some wizardry to handle NLA stuff correct */ if ((adt->action == NULL) && (add)) { + /* init action name from name of ID block */ char actname[sizeof(id->name) - 2]; BLI_snprintf(actname, sizeof(actname), "%sAction", id->name + 2); + + /* create action */ adt->action = add_empty_action(G.main, actname); + + /* set ID-type from ID-block that this is going to be assigned to + * so that users can't accidentally break actions by assigning them + * to the wrong places + */ + adt->action->idroot = GS(id->name); } /* return the action */ @@ -996,6 +1006,34 @@ short insert_keyframe(ReportList *reports, ID *id, bAction *act, const char grou * The flag argument is used for special settings that alter the behavior of * the keyframe deletion. These include the quick refresh options. */ + + + +/** + * \note caller needs to run #BKE_nla_tweakedit_remap to get NLA relative frame. + * caller should also check #BKE_fcurve_is_protected before keying. + */ +static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra) +{ + bool found; + int i; + + /* try to find index of beztriple to get rid of */ + i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found); + if (found) { + /* delete the key at the index (will sanity check + do recalc afterwards) */ + delete_fcurve_key(fcu, i, 1); + + /* Only delete curve too if it won't be doing anything anymore */ + if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) + ANIM_fcurve_delete_from_animdata(NULL, adt, fcu); + + /* return success */ + return true; + } + return false; +} + short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short UNUSED(flag)) { AnimData *adt = BKE_animdata_from_id(id); @@ -1055,32 +1093,20 @@ short delete_keyframe(ReportList *reports, ID *id, bAction *act, const char grou /* will only loop once unless the array index was -1 */ for (; array_index < array_index_max; array_index++) { FCurve *fcu = verify_fcurve(act, group, &ptr, rna_path, array_index, 0); - bool found; - int i; - + /* check if F-Curve exists and/or whether it can be edited */ if (fcu == NULL) continue; - - if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) { - if (G.debug & G_DEBUG) - printf("WARNING: not deleting keyframe for locked F-Curve\n"); + + if (BKE_fcurve_is_protected(fcu)) { + BKE_reportf(reports, RPT_WARNING, + "not deleting keyframe for locked F-Curve '%s' for %s '%s'", + fcu->rna_path, BKE_idcode_to_name(GS(id->name)), id->name + 2); continue; } - - /* try to find index of beztriple to get rid of */ - i = binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &found); - if (found) { - /* delete the key at the index (will sanity check + do recalc afterwards) */ - delete_fcurve_key(fcu, i, 1); - - /* Only delete curve too if it won't be doing anything anymore */ - if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) - ANIM_fcurve_delete_from_animdata(NULL, adt, fcu); - - /* return success */ - ret++; - } + + ret += delete_keyframe_fcurve(adt, fcu, cfra); + } /* return success/failure */ @@ -1158,7 +1184,7 @@ static short clear_keyframe(ReportList *reports, ID *id, bAction *act, const cha if (fcu == NULL) continue; - if ( (fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ) { + if (BKE_fcurve_is_protected(fcu)) { if (G.debug & G_DEBUG) printf("WARNING: not deleting keyframe for locked F-Curve\n"); continue; @@ -1537,14 +1563,22 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op) AnimData *adt = ob->adt; bAction *act = adt->action; FCurve *fcu, *fcn; + const float cfra_unmap = BKE_nla_tweakedit_remap(adt, cfra, NLATIME_CONVERT_UNMAP); for (fcu = act->curves.first; fcu; fcu = fcn) { fcn = fcu->next; - + + if (BKE_fcurve_is_protected(fcu)) { + BKE_reportf(op->reports, RPT_WARNING, + "not deleting keyframe for locked F-Curve '%s', object '%s'", + fcu->rna_path, id->name + 2); + continue; + } + /* delete keyframes on current frame * WARNING: this can delete the next F-Curve, hence the "fcn" copying */ - success += delete_keyframe(op->reports, id, NULL, NULL, fcu->rna_path, fcu->array_index, cfra, 0); + success += delete_keyframe_fcurve(adt, fcu, cfra_unmap); } } diff --git a/source/blender/editors/armature/BIF_retarget.h b/source/blender/editors/armature/BIF_retarget.h index 2ea0e0ab0d7..21e85b6fe89 100644 --- a/source/blender/editors/armature/BIF_retarget.h +++ b/source/blender/editors/armature/BIF_retarget.h @@ -29,6 +29,7 @@ #include "BLI_graph.h" #include "BLI_ghash.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "reeb.h" @@ -68,7 +69,8 @@ typedef struct RigGraph { ReebGraph *link_mesh; - struct ThreadedWorker *worker; + TaskScheduler *task_scheduler; + TaskPool *task_pool; GHash *bones_map; /* map of editbones by name */ GHash *controls_map; /* map of rigcontrols by bone pointer */ diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 1ee2dc80a97..8745d571a28 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -182,16 +182,22 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n if (ob->pose) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname); if (pchan) { + GHash *gh = ob->pose->chanhash; + + /* remove the old hash entry, and replace with the new name */ + if (gh) { + BLI_assert(BLI_ghash_haskey(gh, pchan->name)); + BLI_ghash_remove(gh, pchan->name, NULL, NULL); + } + BLI_strncpy(pchan->name, newname, MAXBONENAME); - - if (ob->pose->chanhash) { - GHash *gh = ob->pose->chanhash; - - /* remove the old hash entry, and replace with the new name */ - BLI_ghash_remove(gh, oldname, NULL, NULL); + + if (gh) { BLI_ghash_insert(gh, pchan->name, pchan); } } + + BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true); } /* Update any object constraints to use the new bone name */ @@ -294,9 +300,13 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op)) /* since we renamed stuff... */ DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - /* note, notifier might evolve */ - WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); - + /* copied from #rna_Bone_update_renamed */ + /* redraw view */ + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + + /* update animation channels */ + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, ob->data); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index 687455495a1..c03e7861307 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -83,7 +83,7 @@ static RigGraph *GLOBAL_RIGG = NULL; /*******************************************************************************************************/ -void *exec_retargetArctoArc(void *param); +void exec_retargetArctoArc(TaskPool *pool, void *taskdata, int threadid); static void RIG_calculateEdgeAngles(RigEdge *edge_first, RigEdge *edge_second); float rollBoneByQuat(EditBone *bone, float old_up_axis[3], float qrot[4]); @@ -235,9 +235,8 @@ void RIG_freeRigGraph(BGraph *rg) BNode *node; BArc *arc; -#ifdef USE_THREADS - BLI_destroy_worker(rigg->worker); -#endif + BLI_task_pool_free(rigg->task_pool); + BLI_task_scheduler_free(rigg->task_scheduler); if (rigg->link_mesh) { REEB_freeGraph(rigg->link_mesh); @@ -284,12 +283,14 @@ static RigGraph *newRigGraph(void) rg->free_node = NULL; #ifdef USE_THREADS - //totthread = BKE_scene_num_threads(G.scene); - totthread = BLI_system_thread_count(); - - rg->worker = BLI_create_worker(exec_retargetArctoArc, totthread, 20); /* fix number of threads */ + totthread = TASK_SCHEDULER_AUTO_THREADS; +#else + totthread = TASK_SCHEDULER_SINGLE_THREAD; #endif - + + rg->task_scheduler = BLI_task_scheduler_create(totthread); + rg->task_pool = BLI_task_pool_create(rg->task_scheduler, NULL); + return rg; } @@ -2133,7 +2134,6 @@ static void retargetArctoArcLength(bContext *C, RigGraph *rigg, RigArc *iarc, Ri static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode *inode_start) { -#ifdef USE_THREADS RetargetParam *p = MEM_callocN(sizeof(RetargetParam), "RetargetParam"); p->rigg = rigg; @@ -2141,22 +2141,12 @@ static void retargetArctoArc(bContext *C, RigGraph *rigg, RigArc *iarc, RigNode p->inode_start = inode_start; p->context = C; - BLI_insert_work(rigg->worker, p); -#else - RetargetParam p; - - p.rigg = rigg; - p.iarc = iarc; - p.inode_start = inode_start; - p.context = C; - - exec_retargetArctoArc(&p); -#endif + BLI_task_pool_push(rigg->task_pool, exec_retargetArctoArc, p, true, TASK_PRIORITY_HIGH); } -void *exec_retargetArctoArc(void *param) +void exec_retargetArctoArc(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid)) { - RetargetParam *p = (RetargetParam *)param; + RetargetParam *p = (RetargetParam *)taskdata; RigGraph *rigg = p->rigg; RigArc *iarc = p->iarc; bContext *C = p->context; @@ -2183,12 +2173,6 @@ void *exec_retargetArctoArc(void *param) retargetArctoArcLength(C, rigg, iarc, inode_start); } } - -#ifdef USE_THREADS - MEM_freeN(p); -#endif - - return NULL; } static void matchMultiResolutionNode(RigGraph *rigg, RigNode *inode, ReebNode *top_node) @@ -2414,9 +2398,7 @@ static void retargetSubgraph(bContext *C, RigGraph *rigg, RigArc *start_arc, Rig static void finishRetarget(RigGraph *rigg) { -#ifdef USE_THREADS - BLI_end_worker(rigg->worker); -#endif + BLI_task_pool_work_and_wait(rigg->task_pool); } static void adjustGraphs(bContext *C, RigGraph *rigg) diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index cb7a699b522..182f94b3693 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -638,7 +638,7 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *eve } /* part to sync with other similar operators... */ - return WM_operator_props_popup(C, op, event); + return WM_operator_props_popup_confirm(C, op, event); } static int poselib_rename_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 0bcb550b930..9b858a2c4e9 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -58,7 +58,7 @@ #include "curve_intern.h" -static float nurbcircle[8][2] = { +static const float nurbcircle[8][2] = { {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0}, {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0} }; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index b9759e16f20..ac9c338e431 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -981,7 +981,7 @@ void FONT_OT_move_select(wmOperatorType *ot) { /* identifiers */ ot->name = "Move Select"; - ot->description = "Make selection from current cursor position to new cursor position type"; + ot->description = "Move the cursor while selecting"; ot->idname = "FONT_OT_move_select"; /* api callbacks */ diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 352a74cf172..dd1995a5428 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -221,8 +221,5 @@ void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter, /* Draw imbuf on a screen, preferably using GLSL display transform */ void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter); -/* Transform buffer from role to scene linear space using GLSL OCIO conversion */ -int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role); - #endif /* __BIF_GLUTIL_H__ */ diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 3e2dbe255df..8da36f015dc 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -57,7 +57,7 @@ void ED_operatormacros_mask(void); /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); void ED_mask_draw_region(struct Mask *mask, struct ARegion *ar, - const char draw_flag, const char draw_type, + const char draw_flag, const char draw_type, const char overlay_mode, const int width_i, const int height_i, const float aspx, const float aspy, const short do_scale_applied, const short do_draw_cb, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index b7fd181883b..5d3d72d0e3d 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -152,7 +152,7 @@ void EDBM_select_mirrored(struct BMEditMesh *em, bool extend, void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag); bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -int EDBM_backbuf_check(unsigned int index); +bool EDBM_backbuf_check(unsigned int index); void EDBM_backbuf_free(void); bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2], short tot, diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index bdfbbbb9c74..518bee665ae 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -40,6 +40,7 @@ struct Scene; struct ScrArea; struct RegionView3D; struct RenderEngine; +struct View3D; /* render_ops.c */ @@ -51,6 +52,7 @@ void ED_render_id_flush_update(struct Main *bmain, struct ID *id); void ED_render_engine_changed(struct Main *bmain); void ED_render_engine_area_exit(struct ScrArea *sa); void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated); +void ED_render_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa); void ED_viewport_render_kill_jobs(const struct bContext *C, bool free_database); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 81308dd84f2..eff79b6a039 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -103,7 +103,7 @@ enum TfmMode { * returns 1 if successful, 0 otherwise (usually means there's no selection) * (if 0 is returns, *vec is unmodified) * */ -int calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], int cent2d[2]); +int calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], float cent2d[2]); struct TransInfo; struct ScrArea; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index ce9d3af3013..86abf29c308 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -336,4 +336,7 @@ void ED_view3d_operator_properties_viewmat_set(struct bContext *C, struct wmOper void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, int *winy, float persmat[4][4]); #endif +/* render */ +void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa); + #endif /* __ED_VIEW3D_H__ */ diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index a8b8765a5c6..e13517adbb3 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC interface.c interface_anim.c interface_draw.c + interface_eyedropper.c interface_handlers.c interface_icons.c interface_layout.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index e02cdf018c0..3bad2577409 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -611,6 +611,9 @@ static void ui_but_update_linklines(uiBlock *block, uiBut *oldbut, uiBut *newbut static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut **butpp) { + /* flags from the buttons we want to refresh, may want to add more here... */ + const int flag_copy = UI_BUT_REDALERT; + uiBlock *oldblock; uiBut *oldbut, *but = *butpp; int found = 0; @@ -659,6 +662,7 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut /* drawing */ oldbut->icon = but->icon; oldbut->iconadd = but->iconadd; + oldbut->alignnr = but->alignnr; /* typically the same pointers, but not on undo/redo */ /* XXX some menu buttons store button itself in but->poin. Ugly */ @@ -667,6 +671,8 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut SWAP(void *, oldbut->func_argN, but->func_argN); } + oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy); + /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position * when scrolling without moving mouse (see [#28432]) */ if (ELEM(oldbut->type, ROW, LISTROW)) @@ -2869,7 +2875,7 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, } /* keep track of UI_interface.h */ - if (ELEM8(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, BUTM, SCROLL, SEPR)) {} + if (ELEM9(but->type, BLOCK, BUT, LABEL, PULLDOWN, ROUNDBOX, LISTBOX, BUTM, SCROLL, SEPR)) {} else if (but->type >= SEARCH_MENU) {} else but->flag |= UI_BUT_UNDO; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index cd845da10c6..11062ea2bd2 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -1389,7 +1389,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc if (scopes->track_disabled) { glColor4f(0.7f, 0.3f, 0.3f, 0.3f); - uiSetRoundBox(15); + uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); ok = 1; @@ -1437,7 +1437,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc if (scopes->use_track_mask) { glColor4f(0.0f, 0.0f, 0.0f, 0.3f); - uiSetRoundBox(15); + uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); } @@ -1478,7 +1478,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc if (!ok) { glColor4f(0.f, 0.f, 0.f, 0.3f); - uiSetRoundBox(15); + uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_POLYGON, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f); } diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c new file mode 100644 index 00000000000..783a777a2fe --- /dev/null +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -0,0 +1,642 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_eyedropper.c + * \ingroup edinterface + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_space_types.h" +#include "DNA_screen_types.h" +#include "DNA_object_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math_vector.h" + +#include "BKE_context.h" +#include "BKE_screen.h" +#include "BKE_report.h" +#include "BKE_idcode.h" + +#include "RNA_access.h" + +#include "BIF_gl.h" + +#include "UI_interface.h" + +#include "IMB_colormanagement.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "interface_intern.h" + +/* for HDR color sampling */ +#include "ED_image.h" +#include "ED_node.h" +#include "ED_clip.h" + +/* for ID data eyedropper */ +#include "ED_space_api.h" +#include "ED_screen.h" +#include "ED_view3d.h" + + +/* -------------------------------------------------------------------- */ +/* Eyedropper + */ + +/** \name Eyedropper (RGB Color) + * \{ */ + +typedef struct Eyedropper { + struct ColorManagedDisplay *display; + + PointerRNA ptr; + PropertyRNA *prop; + int index; + + int accum_start; /* has mouse been presed */ + float accum_col[3]; + int accum_tot; +} Eyedropper; + +static int eyedropper_init(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Eyedropper *eye; + + op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper"); + + uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index); + + if ((eye->ptr.data == NULL) || + (eye->prop == NULL) || + (RNA_property_editable(&eye->ptr, eye->prop) == FALSE) || + (RNA_property_array_length(&eye->ptr, eye->prop) < 3) || + (RNA_property_type(eye->prop) != PROP_FLOAT)) + { + return FALSE; + } + + if (RNA_property_subtype(eye->prop) == PROP_COLOR) { + const char *display_device; + + display_device = scene->display_settings.display_device; + eye->display = IMB_colormanagement_display_get_named(display_device); + } + + return TRUE; +} + +static void eyedropper_exit(bContext *C, wmOperator *op) +{ + WM_cursor_modal_restore(CTX_wm_window(C)); + + if (op->customdata) { + MEM_freeN(op->customdata); + op->customdata = NULL; + } +} + +static int eyedropper_cancel(bContext *C, wmOperator *op) +{ + eyedropper_exit(C, op); + return OPERATOR_CANCELLED; +} + +/* *** eyedropper_color_ helper functions *** */ + +/** + * \brief get the color from the screen. + * + * Special check for image or nodes where we MAY have HDR pixels which don't display. + */ +static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3]) +{ + + /* we could use some clever */ + wmWindow *win = CTX_wm_window(C); + ScrArea *sa; + for (sa = win->screen->areabase.first; sa; sa = sa->next) { + if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) { + if (sa->spacetype == SPACE_IMAGE) { + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + SpaceImage *sima = sa->spacedata.first; + int mval[2] = {mx - ar->winrct.xmin, + my - ar->winrct.ymin}; + + if (ED_space_image_color_sample(sima, ar, mval, r_col)) { + return; + } + } + } + else if (sa->spacetype == SPACE_NODE) { + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + SpaceNode *snode = sa->spacedata.first; + int mval[2] = {mx - ar->winrct.xmin, + my - ar->winrct.ymin}; + + if (ED_space_node_color_sample(snode, ar, mval, r_col)) { + return; + } + } + } + else if (sa->spacetype == SPACE_CLIP) { + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + SpaceClip *sc = sa->spacedata.first; + int mval[2] = {mx - ar->winrct.xmin, + my - ar->winrct.ymin}; + + if (ED_space_clip_color_sample(sc, ar, mval, r_col)) { + return; + } + } + } + } + } + + /* fallback to simple opengl picker */ + glReadBuffer(GL_FRONT); + glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col); + glReadBuffer(GL_BACK); +} + +/* sets the sample color RGB, maintaining A */ +static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3]) +{ + float col_conv[4]; + + /* to maintain alpha */ + RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv); + + /* convert from display space to linear rgb space */ + if (eye->display) { + copy_v3_v3(col_conv, col); + IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display); + } + else { + copy_v3_v3(col_conv, col); + } + + RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv); + + RNA_property_update(C, &eye->ptr, eye->prop); +} + +/* set sample from accumulated values */ +static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye) +{ + float col[3]; + mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot); + eyedropper_color_set(C, eye, col); +} + +/* single point sample & set */ +static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my) +{ + float col[3]; + eyedropper_color_sample_fl(C, eye, mx, my, col); + eyedropper_color_set(C, eye, col); +} + +static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my) +{ + float col[3]; + eyedropper_color_sample_fl(C, eye, mx, my, col); + /* delay linear conversion */ + add_v3_v3(eye->accum_col, col); + eye->accum_tot++; +} + +/* main modal status check */ +static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Eyedropper *eye = (Eyedropper *)op->customdata; + + switch (event->type) { + case ESCKEY: + case RIGHTMOUSE: + return eyedropper_cancel(C, op); + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + if (eye->accum_tot == 0) { + eyedropper_color_sample(C, eye, event->x, event->y); + } + else { + eyedropper_color_set_accum(C, eye); + } + eyedropper_exit(C, op); + return OPERATOR_FINISHED; + } + else if (event->val == KM_PRESS) { + /* enable accum and make first sample */ + eye->accum_start = TRUE; + eyedropper_color_sample_accum(C, eye, event->x, event->y); + } + break; + case MOUSEMOVE: + if (eye->accum_start) { + /* button is pressed so keep sampling */ + eyedropper_color_sample_accum(C, eye, event->x, event->y); + eyedropper_color_set_accum(C, eye); + } + break; + case SPACEKEY: + if (event->val == KM_RELEASE) { + eye->accum_tot = 0; + zero_v3(eye->accum_col); + eyedropper_color_sample_accum(C, eye, event->x, event->y); + eyedropper_color_set_accum(C, eye); + } + break; + } + + return OPERATOR_RUNNING_MODAL; +} + +/* Modal Operator init */ +static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + /* init */ + if (eyedropper_init(C, op)) { + WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR); + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } + else { + eyedropper_exit(C, op); + return OPERATOR_CANCELLED; + } +} + +/* Repeat operator */ +static int eyedropper_exec(bContext *C, wmOperator *op) +{ + /* init */ + if (eyedropper_init(C, op)) { + + /* do something */ + + /* cleanup */ + eyedropper_exit(C, op); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int eyedropper_poll(bContext *C) +{ + if (!CTX_wm_window(C)) return 0; + else return 1; +} + +void UI_OT_eyedropper_color(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Eyedropper"; + ot->idname = "UI_OT_eyedropper_color"; + ot->description = "Sample a color from the Blender Window to store in a property"; + + /* api callbacks */ + ot->invoke = eyedropper_invoke; + ot->modal = eyedropper_modal; + ot->cancel = eyedropper_cancel; + ot->exec = eyedropper_exec; + ot->poll = eyedropper_poll; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; + + /* properties */ +} +/** \} */ + + +/* -------------------------------------------------------------------- */ +/* Data Dropper + * + * note: datadropper is only internal name to avoid confusion in this file + */ + +/** \name Eyedropper (ID data-blocks) + * \{ */ + +typedef struct DataDropper { + PointerRNA ptr; + PropertyRNA *prop; + short idcode; + const char *idcode_name; + + ARegionType *art; + void *draw_handle_pixel; + char name[200]; +} DataDropper; + + +static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg) +{ + DataDropper *ddr = arg; + int width; + const char *name = ddr->name; + wmWindow *win = CTX_wm_window(C); + int x = win->eventstate->x; + int y = win->eventstate->y; + + if ((name[0] == '\0') || + (BLI_rcti_isect_pt(&ar->winrct, x, y) == false)) + { + return; + } + + width = UI_GetStringWidth(name); + x = x - ar->winrct.xmin; + y = y - ar->winrct.ymin; + + y += 20; + + glColor4ub(0, 0, 0, 50); + + uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA); + uiRoundBox(x, y, x + width + 8, y + 15, 4); + + glColor4ub(255, 255, 255, 255); + UI_DrawString(x + 4, y + 4, name); +} + + +static int datadropper_init(bContext *C, wmOperator *op) +{ + DataDropper *ddr; + int index_dummy; + StructRNA *type; + + SpaceType *st; + ARegionType *art; + + st = BKE_spacetype_from_id(SPACE_VIEW3D); + art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW); + + op->customdata = ddr = MEM_callocN(sizeof(DataDropper), "DataDropper"); + + uiContextActiveProperty(C, &ddr->ptr, &ddr->prop, &index_dummy); + + if ((ddr->ptr.data == NULL) || + (ddr->prop == NULL) || + (RNA_property_editable(&ddr->ptr, ddr->prop) == false) || + (RNA_property_type(ddr->prop) != PROP_POINTER)) + { + return false; + } + + ddr->art = art; + ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL); + + type = RNA_property_pointer_type(&ddr->ptr, ddr->prop); + ddr->idcode = RNA_type_to_ID_code(type); + BLI_assert(ddr->idcode != 0); + ddr->idcode_name = BKE_idcode_to_name(ddr->idcode); + + return true; +} + +static void datadropper_exit(bContext *C, wmOperator *op) +{ + WM_cursor_modal_restore(CTX_wm_window(C)); + + if (op->customdata) { + DataDropper *ddr = (DataDropper *)op->customdata; + + ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel); + + MEM_freeN(op->customdata); + + op->customdata = NULL; + } +} + +static int datadropper_cancel(bContext *C, wmOperator *op) +{ + datadropper_exit(C, op); + return OPERATOR_CANCELLED; +} + +/* *** datadropper id helper functions *** */ +/** + * \brief get the ID from the screen. + * + */ +static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id) +{ + + /* we could use some clever */ + wmWindow *win = CTX_wm_window(C); + ScrArea *sa; + + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); + + ddr->name[0] = '\0'; + + for (sa = win->screen->areabase.first; sa; sa = sa->next) { + if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) { + if (sa->spacetype == SPACE_VIEW3D) { + ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); + if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + int mval[2] = {mx - ar->winrct.xmin, + my - ar->winrct.ymin}; + Base *base; + + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + /* grr, always draw else we leave stale text */ + ED_region_tag_redraw(ar); + + base = ED_view3d_give_base_under_cursor(C, mval); + if (base) { + Object *ob = base->object; + ID *id = NULL; + if (ddr->idcode == ID_OB) { + id = (ID *)ob; + } + else if (ob->data) { + if (GS(((ID *)ob->data)->name) == ddr->idcode) { + id = (ID *)ob->data; + } + else { + BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s", + ddr->idcode_name); + } + } + + if (id) { + BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s", + ddr->idcode_name, id->name + 2); + *r_id = id; + } + + break; + } + } + } + } + } + + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); +} + +/* sets the ID, returns success */ +static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id) +{ + PointerRNA ptr_value; + + RNA_id_pointer_create(id, &ptr_value); + + RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value); + + RNA_property_update(C, &ddr->ptr, ddr->prop); + + ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop); + + return (ptr_value.id.data == id); +} + +/* single point sample & set */ +static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my) +{ + ID *id = NULL; + + datadropper_id_sample_pt(C, ddr, mx, my, &id); + return datadropper_id_set(C, ddr, id); +} + +/* main modal status check */ +static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + DataDropper *ddr = (DataDropper *)op->customdata; + + switch (event->type) { + case ESCKEY: + case RIGHTMOUSE: + return datadropper_cancel(C, op); + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + bool success; + + success = datadropper_id_sample(C, ddr, event->x, event->y); + datadropper_exit(C, op); + + if (success) { + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_WARNING, "Failed to set value"); + return OPERATOR_CANCELLED; + } + } + break; + case MOUSEMOVE: + { + ID *id = NULL; + datadropper_id_sample_pt(C, ddr, event->x, event->y, &id); + break; + } + } + + return OPERATOR_RUNNING_MODAL; +} + +/* Modal Operator init */ +static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + /* init */ + if (datadropper_init(C, op)) { + WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR); + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } + else { + datadropper_exit(C, op); + return OPERATOR_CANCELLED; + } +} + +/* Repeat operator */ +static int datadropper_exec(bContext *C, wmOperator *op) +{ + /* init */ + if (datadropper_init(C, op)) { + /* cleanup */ + datadropper_exit(C, op); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int datadropper_poll(bContext *C) +{ + if (!CTX_wm_window(C)) return 0; + else return 1; +} + +void UI_OT_eyedropper_id(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Eyedropper Datablock"; + ot->idname = "UI_OT_eyedropper_id"; + ot->description = "Sample a color from the Blender Window to store in a property"; + + /* api callbacks */ + ot->invoke = datadropper_invoke; + ot->modal = datadropper_modal; + ot->cancel = datadropper_cancel; + ot->exec = datadropper_exec; + ot->poll = datadropper_poll; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; + + /* properties */ +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 20e03e7dcd5..c5faa99e067 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2227,8 +2227,16 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle break; case AKEY: + /* Ctrl + A: Select all */ - if (event->ctrl && !(event->alt || event->shift || event->oskey)) { +#if defined(__APPLE__) + /* OSX uses cmd-a systemwide, so add it */ + if ((event->oskey && !(event->alt || event->shift || event->ctrl)) || + (event->ctrl && !(event->alt || event->shift || event->oskey))) +#else + if (event->ctrl && !(event->alt || event->shift || event->oskey)) +#endif + { ui_textedit_move(but, data, STRCUR_DIR_PREV, false, STRCUR_JUMP_ALL); ui_textedit_move(but, data, STRCUR_DIR_NEXT, @@ -2613,7 +2621,10 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM4(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) { - if (but->dt == UI_EMBOSSN && !event->ctrl) { + if (ELEM(event->type, PADENTER, RETKEY) && (!ui_is_but_utf8(but))) { + /* pass - allow filesel, enter to execute */ + } + else if (but->dt == UI_EMBOSSN && !event->ctrl) { /* pass */ } else { @@ -2647,13 +2658,8 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa BLI_rcti_rctf_copy(&rect, &but->rect); rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect)); - if ( BLI_rcti_isect_pt(&rect, x, y) ) { - /* most likely NULL, but let's check, and give it temp zero string */ - if (data->str == NULL) - data->str = MEM_callocN(16, "temp str"); - data->str[0] = 0; - - ui_apply_but_TEX(C, but, data); + if (BLI_rcti_isect_pt(&rect, x, y)) { + ui_set_but_string(C, but, ""); button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; @@ -3579,31 +3585,6 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_BREAK; } } - else if (but->type == COLOR) { - if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) { - float *hsv = ui_block_hsv_get(but->block); - float col[3]; - - ui_get_but_vectorf(but, col); - rgb_to_hsv_compat_v(col, hsv); - - if (event->type == WHEELDOWNMOUSE) - hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f); - else if (event->type == WHEELUPMOUSE) - hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f); - else { - float fac = 0.005 * (event->y - event->prevy); - hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f); - } - - hsv_to_rgb_v(hsv, data->vec); - ui_set_but_vectorf(but, data->vec); - - button_activate_state(C, but, BUTTON_STATE_EXIT); - ui_apply_button(C, but->block, but, data, true); - return WM_UI_HANDLER_BREAK; - } - } } else if (data->state == BUTTON_STATE_WAIT_DRAG) { @@ -3691,6 +3672,41 @@ static bool ui_numedit_but_NORMAL(uiBut *but, uiHandleButtonData *data, int mx, return changed; } +static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +{ + if (data->state == BUTTON_STATE_HIGHLIGHT) { + if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { + button_activate_state(C, but, BUTTON_STATE_MENU_OPEN); + return WM_UI_HANDLER_BREAK; + } + else if (ELEM3(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->alt) { + float *hsv = ui_block_hsv_get(but->block); + float col[3]; + + ui_get_but_vectorf(but, col); + rgb_to_hsv_compat_v(col, hsv); + + if (event->type == WHEELDOWNMOUSE) + hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f); + else if (event->type == WHEELUPMOUSE) + hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f); + else { + float fac = 0.005 * (event->y - event->prevy); + hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f); + } + + hsv_to_rgb_v(hsv, data->vec); + ui_set_but_vectorf(but, data->vec); + + button_activate_state(C, but, BUTTON_STATE_EXIT); + ui_apply_button(C, but->block, but, data, true); + return WM_UI_HANDLER_BREAK; + } + } + + return WM_UI_HANDLER_CONTINUE; +} + static int ui_do_but_NORMAL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -5389,6 +5405,28 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * else if (event->type == EVT_DROP) { ui_but_drop(C, event, but, data); } + /* handle eyedropper */ + else if ((event->type == EKEY) && (event->val == KM_PRESS)) { + if (event->alt || event->shift || event->ctrl || event->oskey) { + /* pass */ + } + else { + if (but->type == COLOR) { + WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL); + return WM_UI_HANDLER_BREAK; + } + else if (but->type == SEARCH_MENU_UNLINK) { + if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) { + StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); + const short idcode = RNA_type_to_ID_code(type); + if ((idcode == ID_OB) || OB_DATA_SUPPORT_ID(idcode)) { + WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL); + return WM_UI_HANDLER_BREAK; + } + } + } + } + } /* handle keyframing */ else if ((event->type == IKEY) && !ELEM(KM_MOD_FIRST, event->ctrl, event->oskey) && @@ -5534,7 +5572,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * if (but->a1 == UI_GRAD_V_ALT) /* signal to prevent calling up color picker */ retval = ui_do_but_EXIT(C, but, data, event); else - retval = ui_do_but_BLOCK(C, but, data, event); + retval = ui_do_but_COLOR(C, but, data, event); break; case BUT_NORMAL: retval = ui_do_but_NORMAL(C, block, but, data, event); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6382130cbbd..9cc16d82810 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -584,4 +584,8 @@ int ui_but_anim_expression_set(uiBut *but, const char *str); int ui_but_anim_expression_create(uiBut *but, const char *str); void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra); -#endif +/* interface_eyedropper.c */ +void UI_OT_eyedropper_color(struct wmOperatorType *ot); +void UI_OT_eyedropper_id(struct wmOperatorType *ot); + +#endif /* __INTERFACE_INTERN_H__ */ diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 424d2231a03..b453a3b8363 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -505,6 +505,14 @@ static void ui_item_enum_expand_handle(bContext *C, void *arg1, void *arg2) static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, const char *uiname, int h, int icon_only) { + /* XXX The way this function currently handles uiname parameter is insane and inconsistent with general UI API: + * * uiname is the *enum property* label. + * * when it is NULL or empty, we do not draw *enum items* labels, this doubles the icon_only parameter. + * * we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag! + * Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/ + * --mont29 + */ + uiBut *but; EnumPropertyItem *item, *item_array; const char *name; @@ -3091,20 +3099,25 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, /* set various special settings for buttons */ { + uiBlock *block = uiLayoutGetBlock(layout); + const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; uiBut *but; + - for (but = uiLayoutGetBlock(layout)->buttons.first; but; but = but->next) { + for (but = block->buttons.first; but; but = but->next) { /* no undo for buttons for operator redo panels */ uiButClearFlag(but, UI_BUT_UNDO); -#if 0 /* broken, causes freedback loop, see [#36109] */ + /* only for popups, see [#36109] */ + /* if button is operator's default property, and a text-field, enable focus for it * - this is used for allowing operators with popups to rename stuff with fewer clicks */ - if ((but->rnaprop == op->type->prop) && (but->type == TEX)) { - uiButSetFocusOnEnter(CTX_wm_window(C), but); + if (is_popup) { + if ((but->rnaprop == op->type->prop) && (but->type == TEX)) { + uiButSetFocusOnEnter(CTX_wm_window(C), but); + } } -#endif } } } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index d52702c2d51..36e965e13d2 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -27,20 +27,14 @@ * \ingroup edinterface */ -#include <stdio.h> -#include <math.h> #include <string.h> #include "MEM_guardedalloc.h" -#include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_text_types.h" /* for UI_OT_reports_to_text */ #include "BLI_blenlib.h" -#include "BLI_math_color.h" -#include "BLI_math_vector.h" -#include "BLI_utildefines.h" #include "BLF_api.h" #include "BLF_translation.h" @@ -54,12 +48,8 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "BIF_gl.h" - #include "UI_interface.h" -#include "IMB_colormanagement.h" - #include "interface_intern.h" #include "WM_api.h" @@ -70,282 +60,6 @@ #include "BKE_main.h" #include "BLI_ghash.h" -#include "ED_image.h" /* for HDR color sampling */ -#include "ED_node.h" /* for HDR color sampling */ -#include "ED_clip.h" /* for HDR color sampling */ - -/* ********************************************************** */ - -typedef struct Eyedropper { - struct ColorManagedDisplay *display; - - PointerRNA ptr; - PropertyRNA *prop; - int index; - - int accum_start; /* has mouse been presed */ - float accum_col[3]; - int accum_tot; -} Eyedropper; - -static int eyedropper_init(bContext *C, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - Eyedropper *eye; - - op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper"); - - uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index); - - if ((eye->ptr.data == NULL) || - (eye->prop == NULL) || - (RNA_property_editable(&eye->ptr, eye->prop) == FALSE) || - (RNA_property_array_length(&eye->ptr, eye->prop) < 3) || - (RNA_property_type(eye->prop) != PROP_FLOAT)) - { - return FALSE; - } - - if (RNA_property_subtype(eye->prop) == PROP_COLOR) { - const char *display_device; - - display_device = scene->display_settings.display_device; - eye->display = IMB_colormanagement_display_get_named(display_device); - } - - return TRUE; -} - -static void eyedropper_exit(bContext *C, wmOperator *op) -{ - WM_cursor_modal_restore(CTX_wm_window(C)); - - if (op->customdata) - MEM_freeN(op->customdata); - op->customdata = NULL; -} - -static int eyedropper_cancel(bContext *C, wmOperator *op) -{ - eyedropper_exit(C, op); - return OPERATOR_CANCELLED; -} - -/* *** eyedropper_color_ helper functions *** */ - -/** - * \brief get the color from the screen. - * - * Special check for image or nodes where we MAY have HDR pixels which don't display. - */ -static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int mx, int my, float r_col[3]) -{ - - /* we could use some clever */ - wmWindow *win = CTX_wm_window(C); - ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) { - if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) { - if (sa->spacetype == SPACE_IMAGE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { - SpaceImage *sima = sa->spacedata.first; - int mval[2] = {mx - ar->winrct.xmin, - my - ar->winrct.ymin}; - - if (ED_space_image_color_sample(sima, ar, mval, r_col)) { - return; - } - } - } - else if (sa->spacetype == SPACE_NODE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { - SpaceNode *snode = sa->spacedata.first; - int mval[2] = {mx - ar->winrct.xmin, - my - ar->winrct.ymin}; - - if (ED_space_node_color_sample(snode, ar, mval, r_col)) { - return; - } - } - } - else if (sa->spacetype == SPACE_CLIP) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { - SpaceClip *sc = sa->spacedata.first; - int mval[2] = {mx - ar->winrct.xmin, - my - ar->winrct.ymin}; - - if (ED_space_clip_color_sample(sc, ar, mval, r_col)) { - return; - } - } - } - } - } - - /* fallback to simple opengl picker */ - glReadBuffer(GL_FRONT); - glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col); - glReadBuffer(GL_BACK); -} - -/* sets the sample color RGB, maintaining A */ -static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3]) -{ - float col_conv[4]; - - /* to maintain alpha */ - RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv); - - /* convert from display space to linear rgb space */ - if (eye->display) { - copy_v3_v3(col_conv, col); - IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display); - } - else { - copy_v3_v3(col_conv, col); - } - - RNA_property_float_set_array(&eye->ptr, eye->prop, col_conv); - - RNA_property_update(C, &eye->ptr, eye->prop); -} - -/* set sample from accumulated values */ -static void eyedropper_color_set_accum(bContext *C, Eyedropper *eye) -{ - float col[3]; - mul_v3_v3fl(col, eye->accum_col, 1.0f / (float)eye->accum_tot); - eyedropper_color_set(C, eye, col); -} - -/* single point sample & set */ -static void eyedropper_color_sample(bContext *C, Eyedropper *eye, int mx, int my) -{ - float col[3]; - eyedropper_color_sample_fl(C, eye, mx, my, col); - eyedropper_color_set(C, eye, col); -} - -static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, int my) -{ - float col[3]; - eyedropper_color_sample_fl(C, eye, mx, my, col); - /* delay linear conversion */ - add_v3_v3(eye->accum_col, col); - eye->accum_tot++; -} - -/* main modal status check */ -static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - Eyedropper *eye = (Eyedropper *)op->customdata; - - switch (event->type) { - case ESCKEY: - case RIGHTMOUSE: - return eyedropper_cancel(C, op); - case LEFTMOUSE: - if (event->val == KM_RELEASE) { - if (eye->accum_tot == 0) { - eyedropper_color_sample(C, eye, event->x, event->y); - } - else { - eyedropper_color_set_accum(C, eye); - } - eyedropper_exit(C, op); - return OPERATOR_FINISHED; - } - else if (event->val == KM_PRESS) { - /* enable accum and make first sample */ - eye->accum_start = TRUE; - eyedropper_color_sample_accum(C, eye, event->x, event->y); - } - break; - case MOUSEMOVE: - if (eye->accum_start) { - /* button is pressed so keep sampling */ - eyedropper_color_sample_accum(C, eye, event->x, event->y); - eyedropper_color_set_accum(C, eye); - } - break; - case SPACEKEY: - if (event->val == KM_RELEASE) { - eye->accum_tot = 0; - zero_v3(eye->accum_col); - eyedropper_color_sample_accum(C, eye, event->x, event->y); - eyedropper_color_set_accum(C, eye); - } - break; - } - - return OPERATOR_RUNNING_MODAL; -} - -/* Modal Operator init */ -static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) -{ - /* init */ - if (eyedropper_init(C, op)) { - WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR); - - /* add temp handler */ - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; - } - else { - eyedropper_exit(C, op); - return OPERATOR_CANCELLED; - } -} - -/* Repeat operator */ -static int eyedropper_exec(bContext *C, wmOperator *op) -{ - /* init */ - if (eyedropper_init(C, op)) { - - /* do something */ - - /* cleanup */ - eyedropper_exit(C, op); - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } -} - -static int eyedropper_poll(bContext *C) -{ - if (!CTX_wm_window(C)) return 0; - else return 1; -} - -static void UI_OT_eyedropper(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Eyedropper"; - ot->idname = "UI_OT_eyedropper"; - ot->description = "Sample a color from the Blender Window to store in a property"; - - /* api callbacks */ - ot->invoke = eyedropper_invoke; - ot->modal = eyedropper_modal; - ot->cancel = eyedropper_cancel; - ot->exec = eyedropper_exec; - ot->poll = eyedropper_poll; - - /* flags */ - ot->flag = OPTYPE_BLOCKING; - - /* properties */ -} - /* Reset Default Theme ------------------------ */ static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) @@ -1114,7 +828,6 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot) void UI_buttons_operatortypes(void) { - WM_operatortype_append(UI_OT_eyedropper); WM_operatortype_append(UI_OT_reset_default_theme); WM_operatortype_append(UI_OT_copy_data_path_button); WM_operatortype_append(UI_OT_reset_default_button); @@ -1127,4 +840,8 @@ void UI_buttons_operatortypes(void) WM_operatortype_append(UI_OT_edittranslation_init); #endif WM_operatortype_append(UI_OT_reloadtranslation); + + /* external */ + WM_operatortype_append(UI_OT_eyedropper_color); + WM_operatortype_append(UI_OT_eyedropper_id); } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 35741618211..15fbd51c6fc 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2185,7 +2185,7 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper yco = -3.0f * UI_UNIT_Y; if (show_picker) { - bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL); + bt = uiDefIconButO(block, BUT, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, ICON_EYEDROPPER, butwidth + 10, yco, UI_UNIT_X, UI_UNIT_Y, NULL); uiButSetFunc(bt, close_popup_cb, bt, NULL); } diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 22c20842723..00113666872 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1374,14 +1374,16 @@ static void VIEW2D_OT_smoothview(wmOperatorType *ot) { /* identifiers */ ot->name = "Smooth View 2D"; - ot->description = "Zoom in the view to the nearest item contained in the border"; + ot->description = ""; ot->idname = "VIEW2D_OT_smoothview"; /* api callbacks */ ot->invoke = view2d_smoothview_invoke; - ot->poll = view2d_poll; + /* flags */ + ot->flag = OPTYPE_INTERNAL; + /* rna */ WM_operator_properties_gesture_border(ot, FALSE); } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 70fa97bebc1..f50e4400b91 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -96,7 +96,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int use_object_instantiation; int sort_by_name; int export_transformation_type; - int second_life; + int open_sim; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { BKE_report(op->reports, RPT_ERROR, "No filename given"); @@ -142,7 +142,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); - second_life = RNA_boolean_get(op->ptr, "second_life"); + open_sim = RNA_boolean_get(op->ptr, "open_sim"); /* get editmode results */ ED_object_editmode_load(CTX_data_edit_object(C)); @@ -168,7 +168,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) use_object_instantiation, sort_by_name, export_transformation_type, - second_life)) + open_sim)) { return OPERATOR_FINISHED; } @@ -236,7 +236,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) row = uiLayoutRow(box, FALSE); uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, FALSE); - uiItemR(row, imfptr, "second_life", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE); /* Collada options: */ box = uiLayoutBox(layout); @@ -350,8 +350,8 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, "Transform", "Transformation type for translation, scale and rotation"); - RNA_def_boolean(ot->srna, "second_life", 0, "Export for Second Life", - "Compatibility mode for Second Life"); + RNA_def_boolean(ot->srna, "open_sim", 0, "Export for OpenSim", + "Compatibility mode for OpenSim and compatible online worlds"); } diff --git a/source/blender/editors/mask/SConscript b/source/blender/editors/mask/SConscript index a80d3317c89..9dd521e3a7c 100644 --- a/source/blender/editors/mask/SConscript +++ b/source/blender/editors/mask/SConscript @@ -41,5 +41,8 @@ incs = [ '../../makesrna', '../../windowmanager', ] + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + incs.append(env['BF_PTHREADS_INC']) env.BlenderLib('bf_editors_mask', sources, incs, defs, libtype=['core'], priority=[100]) diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index fec4ab87996..50d8e653737 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -35,6 +35,7 @@ #include "BLI_utildefines.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_task.h" #include "BKE_context.h" #include "BKE_mask.h" @@ -48,6 +49,7 @@ #include "ED_mask.h" /* own include */ #include "ED_space_api.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -535,10 +537,93 @@ void ED_mask_draw(const bContext *C, draw_masklays(C, mask, draw_flag, draw_type, width, height); } +typedef struct ThreadedMaskRasterizeState { + MaskRasterHandle *handle; + float *buffer; + int width, height; +} ThreadedMaskRasterizeState; + +typedef struct ThreadedMaskRasterizeData { + int start_scanline; + int num_scanlines; +} ThreadedMaskRasterizeData; + +static void mask_rasterize_func(TaskPool *pool, void *taskdata, int UNUSED(threadid)) +{ + ThreadedMaskRasterizeState *state = (ThreadedMaskRasterizeState *) BLI_task_pool_userdata(pool); + ThreadedMaskRasterizeData *data = (ThreadedMaskRasterizeData *) taskdata; + int scanline; + + for (scanline = 0; scanline < data->num_scanlines; scanline++) { + int x, y = data->start_scanline + scanline; + for (x = 0; x < state->width; x++) { + int index = y * state->width + x; + float xy[2]; + + xy[0] = (float) x / state->width; + xy[1] = (float) y / state->height; + + state->buffer[index] = BKE_maskrasterize_handle_sample(state->handle, xy); + } + } +} + +static float *threaded_mask_rasterize(Mask *mask, const int width, const int height) +{ + TaskScheduler *task_scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool; + MaskRasterHandle *handle; + ThreadedMaskRasterizeState state; + float *buffer; + int i, num_threads = BLI_task_scheduler_num_threads(task_scheduler), scanlines_per_thread; + + buffer = MEM_mallocN(sizeof(float) * height * width, "rasterized mask buffer"); + + /* Initialize rasterization handle. */ + handle = BKE_maskrasterize_handle_new(); + BKE_maskrasterize_handle_init(handle, mask, width, height, TRUE, TRUE, TRUE); + + state.handle = handle; + state.buffer = buffer; + state.width = width; + state.height = height; + + task_pool = BLI_task_pool_create(task_scheduler, &state); + + BLI_begin_threaded_malloc(); + + scanlines_per_thread = height / num_threads; + for (i = 0; i < num_threads; i++) { + ThreadedMaskRasterizeData *data = MEM_mallocN(sizeof(ThreadedMaskRasterizeData), + "threaded mask rasterize data"); + + data->start_scanline = i * scanlines_per_thread; + + if (i < num_threads - 1) { + data->num_scanlines = scanlines_per_thread; + } + else { + data->num_scanlines = height - data->start_scanline; + } + + BLI_task_pool_push(task_pool, mask_rasterize_func, data, true, TASK_PRIORITY_LOW); + } + + /* work and wait until tasks are done */ + BLI_task_pool_work_and_wait(task_pool); + + /* Free memory. */ + BLI_task_pool_free(task_pool); + BLI_end_threaded_malloc(); + BKE_maskrasterize_handle_free(handle); + + return buffer; +} + /* sets up the opengl context. * width, height are to match the values from ED_mask_get_size() */ void ED_mask_draw_region(Mask *mask, ARegion *ar, - const char draw_flag, const char draw_type, + const char draw_flag, const char draw_type, const char overlay_mode, const int width_i, const int height_i, /* convert directly into aspect corrected vars */ const float aspx, const float aspy, const short do_scale_applied, const short do_draw_cb, @@ -592,6 +677,37 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar, yofs = ((width - height) / -2.0f) * zoomy; } + if (draw_flag & MASK_DRAWFLAG_OVERLAY) { + float *buffer = threaded_mask_rasterize(mask, width, height); + int format; + + if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) { + glColor3f(1.0f, 1.0f, 1.0f); + format = GL_LUMINANCE; + } + else { + /* More blending types could be supported in the future. */ + glEnable(GL_BLEND); + glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); + format = GL_ALPHA; + } + + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(zoomx, zoomy, 0); + if (stabmat) { + glMultMatrixf(stabmat); + } + glaDrawPixelsTex(0.0f, 0.0f, width, height, format, GL_FLOAT, GL_NEAREST, buffer); + glPopMatrix(); + + if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) { + glDisable(GL_BLEND); + } + + MEM_freeN(buffer); + } + /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */ glPushMatrix(); glTranslatef(x + xofs, y + yofs, 0); diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 6033e7ee471..97da0047793 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -64,7 +64,7 @@ typedef struct { float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */ /* modal only */ - int mcenter[2]; + float mcenter[2]; BMBackup mesh_backup; void *draw_handle_pixel; short twtype; diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index afafd8458c5..5431b1deb1c 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -300,7 +300,7 @@ void MESH_OT_bisect(struct wmOperatorType *ot) /* identifiers */ ot->name = "Bisect"; - ot->description = "Enforce symmetry (both form and topological) across an axis"; + ot->description = "Cut geometry along a plane"; ot->idname = "MESH_OT_bisect"; /* api callbacks */ diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 300fb67ec80..3df4ad738ae 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -290,7 +290,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", - (float *)dvec, BM_ELEM_SELECT); + dvec, BM_ELEM_SELECT); //extrudeflag(obedit, em, SELECT, nor); //translateflag(em, SELECT, dvec); } diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 3966826a5b2..eb66cf50a1e 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -68,7 +68,7 @@ typedef struct { NumInput num_input; /* modal only */ - int mcenter[2]; + float mcenter[2]; BMBackup mesh_backup; void *draw_handle_pixel; short twtype; @@ -96,10 +96,10 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C) BLI_snprintf(msg, HEADER_LENGTH, str, flts_str, flts_str + NUM_STR_REP_LEN, - opdata->modify_depth ? IFACE_("On") : IFACE_("Off"), - RNA_boolean_get(op->ptr, "use_outset") ? IFACE_("On") : IFACE_("Off"), - RNA_boolean_get(op->ptr, "use_boundary") ? IFACE_("On") : IFACE_("Off"), - RNA_boolean_get(op->ptr, "use_individual") ? IFACE_("On") : IFACE_("Off") + WM_bool_as_string(opdata->modify_depth), + WM_bool_as_string(RNA_boolean_get(op->ptr, "use_outset")), + WM_bool_as_string(RNA_boolean_get(op->ptr, "use_boundary")), + WM_bool_as_string(RNA_boolean_get(op->ptr, "use_individual")) ); ED_area_headerprint(sa, msg); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index a60b0248644..b0dc30d73f7 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -230,10 +230,10 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, " "E: new cut, Ctrl: midpoint snap (%s), Shift: ignore snap (%s), " "C: angle constrain (%s), Z: cut through (%s)"), - kcd->snap_midpoints ? IFACE_("On") : IFACE_("Off"), - kcd->ignore_edge_snapping ? IFACE_("On") : IFACE_("Off"), - kcd->angle_snapping ? IFACE_("On") : IFACE_("Off"), - kcd->cut_through ? IFACE_("On") : IFACE_("Off")); + WM_bool_as_string(kcd->snap_midpoints), + WM_bool_as_string(kcd->ignore_edge_snapping), + WM_bool_as_string(kcd->angle_snapping), + WM_bool_as_string(kcd->cut_through)); ED_area_headerprint(CTX_wm_area(C), header); } @@ -1546,8 +1546,16 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) knife_project_v2(kcd, v1, s1); knife_project_v2(kcd, v2, s2); - if (len_squared_v2v2(s1, s2) < 1) - return; + if (kcd->is_interactive) { + if (len_squared_v2v2(s1, s2) < 1.0f) { + return; + } + } + else { + if (len_squared_v2v2(s1, s2) < KNIFE_FLT_EPS_SQUARED) { + return; + } + } /* unproject screen line */ ED_view3d_win_to_segment(kcd->ar, kcd->vc.v3d, s1, v1, v3, true); @@ -2123,7 +2131,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) facenet_entry *entry; ListBase *face_nets = MEM_callocN(sizeof(ListBase) * bm->totface, "face_nets"); BMFace **faces = MEM_callocN(sizeof(BMFace *) * bm->totface, "faces knife"); - MemArena *arena = BLI_memarena_new(1 << 16, "knifenet_fill_faces"); + MemArena *arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "knifenet_fill_faces"); SmallHash shash; RNG *rng; int i, j, k = 0, totface = bm->totface; @@ -3151,7 +3159,7 @@ static void knifetool_init(bContext *C, KnifeTool_OpData *kcd, (only_select ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN), kcd->cagecos, false); - kcd->arena = BLI_memarena_new(1 << 15, "knife"); + kcd->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 15), "knife"); kcd->vthresh = KMAXDIST - 1; kcd->ethresh = KMAXDIST; @@ -3517,7 +3525,7 @@ static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, while (p) { const float (*mval_fl)[2] = p->link; const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl); - isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1); + isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1, false); p = p->next; } diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 892b773b1ba..ae1007cb98a 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -537,7 +537,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_PRESS) { /* finish */ ED_region_tag_redraw(lcd->ar); - + ED_area_headerprint(CTX_wm_area(C), NULL); + if (lcd->eed) { /* set for redo */ BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE); @@ -550,9 +551,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) else { return ringcut_cancel(C, op); } - - ED_area_headerprint(CTX_wm_area(C), NULL); - + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 806ae96cb61..f975d801d10 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -31,6 +31,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_bitmap.h" #include "BLI_listbase.h" #include "BLI_linklist.h" #include "BLI_linklist_stack.h" @@ -184,55 +185,13 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag) unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0; /* set in drawobject.c ... for colorindices */ /* facilities for border select and circle select */ -static char *selbuf = NULL; +static BLI_bitmap *selbuf = NULL; -/* opengl doesn't support concave... */ -static void draw_triangulated(const int mcords[][2], const short tot) +static BLI_bitmap *edbm_backbuf_alloc(const int size) { - ListBase lb = {NULL, NULL}; - DispList *dl; - float *fp; - int a; - const float z_up[3] = {0.0f, 0.0f, 1.0f}; - - /* make displist */ - dl = MEM_callocN(sizeof(DispList), "poly disp"); - dl->type = DL_POLY; - dl->parts = 1; - dl->nr = tot; - dl->verts = fp = MEM_callocN(tot * 3 * sizeof(float), "poly verts"); - BLI_addtail(&lb, dl); - - for (a = 0; a < tot; a++, fp += 3) { - fp[0] = (float)mcords[a][0]; - fp[1] = (float)mcords[a][1]; - } - - /* do the fill */ - BKE_displist_fill(&lb, &lb, z_up, false); - - /* do the draw */ - dl = lb.first; /* filldisplist adds in head of list */ - if (dl->type == DL_INDEX3) { - int *index; - - a = dl->parts; - fp = dl->verts; - index = dl->index; - glBegin(GL_TRIANGLES); - while (a--) { - glVertex3fv(fp + 3 * index[0]); - glVertex3fv(fp + 3 * index[1]); - glVertex3fv(fp + 3 * index[2]); - index += 3; - } - glEnd(); - } - - BKE_displist_free(&lb); + return BLI_BITMAP_NEW(size, "selbuf"); } - /* reads rect, and builds selection array for quick lookup */ /* returns if all is OK */ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) @@ -252,24 +211,31 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma dr = buf->rect; /* build selection lookup */ - selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf"); + selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); a = (xmax - xmin + 1) * (ymax - ymin + 1); while (a--) { - if (*dr > 0 && *dr <= bm_vertoffs) - selbuf[*dr] = 1; + if (*dr > 0 && *dr <= bm_vertoffs) { + BLI_BITMAP_SET(selbuf, *dr); + } dr++; } IMB_freeImBuf(buf); return true; } -int EDBM_backbuf_check(unsigned int index) +bool EDBM_backbuf_check(unsigned int index) { - if (selbuf == NULL) return 1; + /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled + * and just ignore the depth buffer, this is error prone since its possible + * code doesn't set the depth buffer by accident, but leave for now. - Campbell */ + if (selbuf == NULL) + return true; + if (index > 0 && index <= bm_vertoffs) - return selbuf[index]; - return 0; + return BLI_BITMAP_GET_BOOL(selbuf, index); + + return false; } void EDBM_backbuf_free(void) @@ -278,6 +244,18 @@ void EDBM_backbuf_free(void) selbuf = NULL; } +struct LassoMaskData { + unsigned int *px; + int width; +}; + +static void edbm_mask_lasso_px_cb(int x, int y, void *user_data) +{ + struct LassoMaskData *data = user_data; + data->px[(y * data->width) + x] = true; +} + + /* mcords is a polygon mask * - grab backbuffer, * - draw with black in backbuffer, @@ -286,9 +264,10 @@ void EDBM_backbuf_free(void) */ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) { - unsigned int *dr, *drm; - struct ImBuf *buf, *bufmask; + unsigned int *dr, *dr_mask, *dr_mask_arr; + struct ImBuf *buf; int a; + struct LassoMaskData lasso_mask_data; /* method in use for face selecting too */ if (vc->obedit == NULL) { @@ -306,49 +285,27 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short dr = buf->rect; - if (vc->rv3d->gpuoffscreen) - GPU_offscreen_bind(vc->rv3d->gpuoffscreen); - - /* draw the mask */ - glDisable(GL_DEPTH_TEST); - - glColor3ub(0, 0, 0); - - /* yah, opengl doesn't do concave... tsk! */ - ED_region_pixelspace(vc->ar); - draw_triangulated(mcords, tot); - - glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */ - for (a = 0; a < tot; a++) { - glVertex2iv(mcords[a]); - } - glEnd(); - - glFinish(); /* to be sure readpixels sees mask */ - - if (vc->rv3d->gpuoffscreen) - GPU_offscreen_unbind(vc->rv3d->gpuoffscreen); - - /* grab mask */ - bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf->x * buf->y, __func__); + lasso_mask_data.px = dr_mask; + lasso_mask_data.width = (xmax - xmin) + 1; - if (bufmask == NULL) { - return false; /* only when mem alloc fails, go crash somewhere else! */ - } - else { - drm = bufmask->rect; - } + fill_poly_v2i_n( + xmin, ymin, xmax + 1, ymax + 1, + mcords, tot, + edbm_mask_lasso_px_cb, &lasso_mask_data); /* build selection lookup */ - selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf"); + selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); a = (xmax - xmin + 1) * (ymax - ymin + 1); while (a--) { - if (*dr > 0 && *dr <= bm_vertoffs && *drm == 0) selbuf[*dr] = 1; - dr++; drm++; + if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) { + BLI_BITMAP_SET(selbuf, *dr); + } + dr++; dr_mask++; } IMB_freeImBuf(buf); - IMB_freeImBuf(bufmask); + MEM_freeN(dr_mask_arr); return true; } @@ -380,12 +337,14 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) dr = buf->rect; /* build selection lookup */ - selbuf = MEM_callocN(bm_vertoffs + 1, "selbuf"); + selbuf = edbm_backbuf_alloc(bm_vertoffs + 1); radsq = rads * rads; for (yc = -rads; yc <= rads; yc++) { for (xc = -rads; xc <= rads; xc++, dr++) { if (xc * xc + yc * yc < radsq) { - if (*dr > 0 && *dr <= bm_vertoffs) selbuf[*dr] = 1; + if (*dr > 0 && *dr <= bm_vertoffs) { + BLI_BITMAP_SET(selbuf, *dr); + } } } } @@ -1897,7 +1856,6 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; BMIter iter; - BMVert *v; BMEdge *e; BMWalker walker; @@ -1911,8 +1869,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BMFace *efa; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_set(efa, BM_ELEM_TAG, (BM_elem_flag_test(efa, BM_ELEM_SELECT) && - !BM_elem_flag_test(efa, BM_ELEM_HIDDEN))); + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_elem_flag_test(efa, BM_ELEM_SELECT)); } if (limit) { @@ -1932,6 +1889,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { BM_face_select_set(bm, efa, true); + BM_elem_flag_disable(efa, BM_ELEM_TAG); } } } @@ -1942,13 +1900,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } } else { + BMVert *v; + BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BM_elem_flag_enable(v, BM_ELEM_TAG); - } - else { - BM_elem_flag_disable(v, BM_ELEM_TAG); - } + BM_elem_flag_set(v, BM_ELEM_TAG, BM_elem_flag_test(v, BM_ELEM_SELECT)); } BMW_init(&walker, em->bm, BMW_SHELL, @@ -1960,6 +1915,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) if (BM_elem_flag_test(v, BM_ELEM_TAG)) { for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) { BM_edge_select_set(em->bm, e, true); + BM_elem_flag_disable(e, BM_ELEM_TAG); } } } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index f0e5a64b1bd..9e5782c12f2 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -983,12 +983,6 @@ void MESH_OT_flip_normals(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static const EnumPropertyItem direction_items[] = { - {false, "CW", 0, "Clockwise", ""}, - {true, "CCW", 0, "Counter Clockwise", ""}, - {0, NULL, 0, NULL, NULL} -}; - /* only accepts 1 selected edge, or 2 selected faces */ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) { @@ -3008,7 +3002,7 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) } offset = RNA_property_int_get(op->ptr, prop_offset); - offset = mod_i(offset, clamp); + offset = clamp ? mod_i(offset, clamp) : 0; /* in simple cases, move selection for tags, but also support more advanced cases */ edbm_fill_grid_prepare(em->bm, offset, &span, calc_span); @@ -3342,7 +3336,7 @@ void MESH_OT_dissolve_verts(wmOperatorType *ot) { /* identifiers */ ot->name = "Dissolve Vertices"; - ot->description = "Dissolve geometry"; + ot->description = "Dissolve verts, merge edges and faces"; ot->idname = "MESH_OT_dissolve_verts"; /* api callbacks */ @@ -3379,7 +3373,7 @@ void MESH_OT_dissolve_edges(wmOperatorType *ot) { /* identifiers */ ot->name = "Dissolve Edges"; - ot->description = "Dissolve geometry"; + ot->description = "Dissolve edges, merging faces"; ot->idname = "MESH_OT_dissolve_edges"; /* api callbacks */ @@ -3418,7 +3412,7 @@ void MESH_OT_dissolve_faces(wmOperatorType *ot) { /* identifiers */ ot->name = "Dissolve Faces"; - ot->description = "Dissolve geometry"; + ot->description = "Dissolve faces"; ot->idname = "MESH_OT_dissolve_faces"; /* api callbacks */ @@ -4519,7 +4513,7 @@ void MESH_OT_wireframe(wmOperatorType *ot) /* identifiers */ ot->name = "Wire Frame"; ot->idname = "MESH_OT_wireframe"; - ot->description = "Inset new faces into selected faces"; + ot->description = "Create a solid wire-frame from faces"; /* api callbacks */ ot->exec = edbm_wireframe_exec; @@ -4561,7 +4555,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true); + /* Delete unused vertices, edges, and faces */ if (RNA_boolean_get(op->ptr, "delete_unused")) { if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", @@ -4584,9 +4579,11 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Merge adjacent triangles */ if (RNA_boolean_get(op->ptr, "join_triangles")) { - if (!EDBM_op_callf(em, op, "join_triangles faces=%S limit=%f", - &bmop, "geom.out", - RNA_float_get(op->ptr, "limit"))) + if (!EDBM_op_call_and_selectf(em, op, + "faces.out", true, + "join_triangles faces=%S limit=%f", + &bmop, "geom.out", + RNA_float_get(op->ptr, "limit"))) { EDBM_op_finish(em, &bmop, op, true); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 376f2ed294b..4a8097f260e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -91,20 +91,24 @@ typedef struct MultiresBakerJobData { struct MultiresBakerJobData *next, *prev; DerivedMesh *lores_dm, *hires_dm; - int simple, lvl, tot_lvl; + bool simple; + int lvl, tot_lvl; ListBase images; } MultiresBakerJobData; /* data passing to multires-baker job */ typedef struct { ListBase data; - int bake_clear, bake_filter; - short mode, use_lores_mesh; - int number_of_rays; - float bias; - int raytrace_structure; - int octree_resolution; - int threads; + bool bake_clear; /* Clear the images before baking */ + int bake_filter; /* Bake-filter, aka margin */ + short mode; /* mode of baking (displacement, normals, AO) */ + bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */ + int number_of_rays; /* Number of rays to be cast when doing AO baking */ + float bias; /* Bias between object and start ray point when doing AO baking */ + int raytrace_structure; /* Optimization structure to be used for AO baking */ + int octree_resolution; /* Reslution of octotree when using octotree optimization structure */ + int threads; /* Number of threads to be used for baking */ + float user_scale; /* User scale used to scale displacement when baking derivative map. */ } MultiresBakeJob; static bool multiresbake_check(bContext *C, wmOperator *op) @@ -236,7 +240,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l return dm; } -static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, int *simple) +static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple) { Mesh *me = (Mesh *)ob->data; MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); @@ -253,7 +257,7 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH); *lvl = mmd->totlvl; - *simple = mmd->simple; + *simple = mmd->simple != 0; tmp_mmd.lvl = mmd->totlvl; tmp_mmd.sculptlvl = mmd->totlvl; @@ -349,7 +353,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) if (scene->r.bake_mode == RE_BAKE_NORMALS) { clear_flag = CLEAR_TANGENT_NORMAL; } - else if (scene->r.bake_mode == RE_BAKE_DISPLACEMENT) { + else if (ELEM(scene->r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { clear_flag = CLEAR_DISPLACEMENT; } @@ -376,6 +380,8 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) bkr.raytrace_structure = scene->r.raytrace_structure; bkr.octree_resolution = scene->r.ocres; bkr.threads = BKE_scene_num_threads(scene); + bkr.user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f; + //bkr.reports= op->reports; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); @@ -414,6 +420,8 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) bkj->raytrace_structure = scene->r.raytrace_structure; bkj->octree_resolution = scene->r.ocres; bkj->threads = BKE_scene_num_threads(scene); + bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f; + //bkj->reports = op->reports; CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { @@ -453,7 +461,7 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa if (bkj->mode == RE_BAKE_NORMALS) { clear_flag = CLEAR_TANGENT_NORMAL; } - else if (bkj->mode == RE_BAKE_DISPLACEMENT) { + else if (ELEM(bkj->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { clear_flag = CLEAR_DISPLACEMENT; } @@ -468,6 +476,8 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa bkr.bake_filter = bkj->bake_filter; bkr.mode = bkj->mode; bkr.use_lores_mesh = bkj->use_lores_mesh; + bkr.user_scale = bkj->user_scale; + //bkr.reports = bkj->reports; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ bkr.lores_dm = data->lores_dm; @@ -773,7 +783,7 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const static int is_multires_bake(Scene *scene) { - if (ELEM3(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_AO)) + if (ELEM4(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_AO)) return scene->r.bake_flag & R_BAKE_MULTIRES; return 0; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 96144d13519..bd4c2e997fe 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1471,12 +1471,14 @@ static EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED( ob = CTX_data_active_object(C); if (ob) { + const bool use_mode_particle_edit = (ob->particlesystem.first != NULL) || (ob->soft != NULL) || + (modifiers_findByType(ob, eModifierType_Cloth) != NULL); while (input->identifier) { if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) || (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) || - (input->value == OB_MODE_PARTICLE_EDIT && ob->particlesystem.first) || - ((input->value == OB_MODE_SCULPT || input->value == OB_MODE_VERTEX_PAINT || - input->value == OB_MODE_WEIGHT_PAINT || input->value == OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) || + (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) || + (ELEM4(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, + OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) || (input->value == OB_MODE_OBJECT)) { RNA_enum_item_add(&item, &totitem, input); diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 1f52346222c..a9fd3ce1288 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -289,7 +289,7 @@ void GROUP_OT_objects_remove_all(wmOperatorType *ot) { /* identifiers */ ot->name = "Remove From All Groups"; - ot->description = "Remove selected objects from all groups or a selected group"; + ot->description = "Remove selected objects from all groups"; ot->idname = "GROUP_OT_objects_remove_all"; /* api callbacks */ @@ -335,7 +335,7 @@ void GROUP_OT_objects_remove(wmOperatorType *ot) /* identifiers */ ot->name = "Remove From Group"; - ot->description = "Remove selected objects from all groups or a selected group"; + ot->description = "Remove selected objects from a group"; ot->idname = "GROUP_OT_objects_remove"; /* api callbacks */ diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 5b20489c9cb..37656f82b25 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -569,7 +569,7 @@ void OBJECT_OT_hook_add_selob(wmOperatorType *ot) { /* identifiers */ ot->name = "Hook to Selected Object"; - ot->description = "Hook selected vertices to the first selected Object"; + ot->description = "Hook selected vertices to the first selected object"; ot->idname = "OBJECT_OT_hook_add_selob"; /* api callbacks */ @@ -603,7 +603,7 @@ void OBJECT_OT_hook_add_newob(wmOperatorType *ot) { /* identifiers */ ot->name = "Hook to New Object"; - ot->description = "Hook selected vertices to the first selected Object"; + ot->description = "Hook selected vertices to a newly created object"; ot->idname = "OBJECT_OT_hook_add_newob"; /* api callbacks */ diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 917f816d6b1..d6c365e9247 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -47,6 +47,7 @@ #include "DNA_scene_types.h" #include "DNA_particle_types.h" +#include "BLI_alloca.h" #include "BLI_array.h" #include "BLI_math.h" #include "BLI_blenlib.h" @@ -1480,7 +1481,7 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i const int def_nr_active = ob->actdef - 1; vgroup_validmap = MEM_mallocN(*r_vgroup_tot * sizeof(*vgroup_validmap), __func__); memset(vgroup_validmap, false, *r_vgroup_tot * sizeof(*vgroup_validmap)); - if (def_nr_active < *r_vgroup_tot) { + if ((def_nr_active >= 0) && (def_nr_active < *r_vgroup_tot)) { *r_subset_count = 1; vgroup_validmap[def_nr_active] = true; } @@ -2000,7 +2001,11 @@ static void vgroup_levels_subset(Object *ob, const bool *vgroup_validmap, const } } -static void vgroup_normalize_all(Object *ob, const bool lock_active) +static void vgroup_normalize_all(Object *ob, + const bool *vgroup_validmap, + const int vgroup_tot, + const int subset_count, + const bool lock_active) { MDeformVert *dv, **dvert_array = NULL; int i, dvert_tot = 0; @@ -2008,7 +2013,7 @@ static void vgroup_normalize_all(Object *ob, const bool lock_active) const int use_vert_sel = vertex_group_use_vert_sel(ob); - if (lock_active && !BLI_findlink(&ob->defbase, def_nr)) { + if ((lock_active && !BLI_findlink(&ob->defbase, def_nr)) || subset_count == 0) { return; } @@ -2029,13 +2034,15 @@ static void vgroup_normalize_all(Object *ob, const bool lock_active) /* in case its not selected */ if ((dv = dvert_array[i])) { if (lock_flags) { - defvert_normalize_lock_map(dv, lock_flags, defbase_tot); + defvert_normalize_lock_map(dv, vgroup_validmap, vgroup_tot, + lock_flags, defbase_tot); } else if (lock_active) { - defvert_normalize_lock_single(dv, def_nr); + defvert_normalize_lock_single(dv, vgroup_validmap, vgroup_tot, + def_nr); } else { - defvert_normalize(dv); + defvert_normalize_subset(dv, vgroup_validmap, vgroup_tot); } } } @@ -2262,7 +2269,8 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i MEM_freeN(emap_mem); } - MEM_freeN(dvert_array); + if (dvert_array) + MEM_freeN(dvert_array); BLI_SMALLSTACK_FREE(dv_stack); /* not so efficient to get 'dvert_array' again just so unselected verts are NULL'd */ @@ -2270,7 +2278,8 @@ static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const i ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, true); ED_vgroup_parray_mirror_sync(ob, dvert_array, dvert_tot, vgroup_validmap, vgroup_tot); - MEM_freeN(dvert_array); + if (dvert_array) + MEM_freeN(dvert_array); } } @@ -3471,8 +3480,13 @@ static int vertex_group_normalize_all_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); bool lock_active = RNA_boolean_get(op->ptr, "lock_active"); + eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); - vgroup_normalize_all(ob, lock_active); + int subset_count, vgroup_tot; + + const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count); + vgroup_normalize_all(ob, vgroup_validmap, vgroup_tot, subset_count, lock_active); + MEM_freeN((void *)vgroup_validmap); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -3496,6 +3510,7 @@ void OBJECT_OT_vertex_group_normalize_all(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + vgroup_operator_subset_select_props(ot, false); RNA_def_boolean(ot->srna, "lock_active", true, "Lock Active", "Keep the values of the active group while normalizing others"); } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 1a561efd217..b0e19d04e35 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -4421,7 +4421,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op)) ParticleSystem *psys = psys_get_current(ob); if (psys->edit) { - if (psys->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?")) + if (psys->edit->edited || 1) { PE_free_ptcache_edit(psys->edit); psys->edit = NULL; @@ -4447,6 +4447,11 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static int clear_edited_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + return WM_operator_confirm_message(C, op, "Lose changes done in particle mode? (no undo)"); +} + void PARTICLE_OT_edited_clear(wmOperatorType *ot) { /* identifiers */ @@ -4457,6 +4462,7 @@ void PARTICLE_OT_edited_clear(wmOperatorType *ot) /* api callbacks */ ot->exec = clear_edited_exec; ot->poll = particle_edit_toggle_poll; + ot->invoke = clear_edited_invoke; /* flags */ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 577d8af0caf..df8d5ec4e84 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1152,7 +1152,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) /* Try using GLSL display transform. */ if (force_fallback == false) { - if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, true, false)) { + if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, true)) { glEnable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT, @@ -1170,7 +1170,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) "render_view3d_draw"); IMB_colormanagement_buffer_make_display_space(rres.rectf, display_buffer, rres.rectx, rres.recty, - 4, dither, NULL, &scene->display_settings); + 4, dither, &scene->view_settings, &scene->display_settings); glEnable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index cdebbf4e103..21074bdc47c 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -517,7 +517,7 @@ static int screen_opengl_render_anim_initialize(bContext *C, wmOperator *op) return 1; } -static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) +static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); OGLRender *oglrender = op->customdata; @@ -549,12 +549,9 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) BKE_makepicstring(name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, scene->r.scemode & R_EXTENSION, TRUE); if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) { - printf("skipping existing frame \"%s\"\n", name); - - /* go to next frame */ - oglrender->nfra += scene->r.frame_step; - - return 1; + BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name); + ok = true; + goto finally; } } @@ -656,6 +653,9 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) /* movie stats prints have no line break */ printf("\n"); + +finally: /* Step the frame and bail early if needed */ + /* go to next frame */ oglrender->nfra += scene->r.frame_step; @@ -673,7 +673,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent { OGLRender *oglrender = op->customdata; int anim = RNA_boolean_get(op->ptr, "animation"); - int ret; + bool ret; switch (event->type) { case ESCKEY: @@ -698,11 +698,12 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent screen_opengl_render_end(C, op->customdata); return OPERATOR_FINISHED; } - else + else { ret = screen_opengl_render_anim_step(C, op); + } /* stop at the end or on error */ - if (ret == 0) { + if (ret == false) { return OPERATOR_FINISHED; } @@ -750,7 +751,7 @@ static int screen_opengl_render_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } else { - int ret = 1; + bool ret = true; if (!screen_opengl_render_anim_initialize(C, op)) return OPERATOR_CANCELLED; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 58c244228ed..553a543390f 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -588,6 +588,20 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot) #ifdef WITH_FREESTYLE +static bool freestyle_linestyle_check_report(FreestyleLineSet *lineset, ReportList *reports) +{ + if (!lineset) { + BKE_report(reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to"); + return false; + } + if (!lineset->linestyle) { + BKE_report(reports, RPT_ERROR, "The active lineset does not have a line style (indicating data corruption)"); + return false; + } + + return true; +} + static int freestyle_active_module_poll(bContext *C) { PointerRNA ptr = CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings); @@ -860,8 +874,13 @@ static int freestyle_linestyle_new_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "No active lineset to add a new line style to"); return OPERATOR_CANCELLED; } - lineset->linestyle->id.us--; - lineset->linestyle = BKE_copy_linestyle(lineset->linestyle); + if (lineset->linestyle) { + lineset->linestyle->id.us--; + lineset->linestyle = BKE_copy_linestyle(lineset->linestyle); + } + else { + lineset->linestyle = BKE_new_linestyle("LineStyle", NULL); + } WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene); @@ -890,10 +909,10 @@ static int freestyle_color_modifier_add_exec(bContext *C, wmOperator *op) FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); int type = RNA_enum_get(op->ptr, "type"); - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } + if (BKE_add_linestyle_color_modifier(lineset->linestyle, type) == NULL) { BKE_report(op->reports, RPT_ERROR, "Unknown line color modifier type"); return OPERATOR_CANCELLED; @@ -929,10 +948,10 @@ static int freestyle_alpha_modifier_add_exec(bContext *C, wmOperator *op) FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); int type = RNA_enum_get(op->ptr, "type"); - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } + if (BKE_add_linestyle_alpha_modifier(lineset->linestyle, type) == NULL) { BKE_report(op->reports, RPT_ERROR, "Unknown alpha transparency modifier type"); return OPERATOR_CANCELLED; @@ -968,10 +987,10 @@ static int freestyle_thickness_modifier_add_exec(bContext *C, wmOperator *op) FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); int type = RNA_enum_get(op->ptr, "type"); - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } + if (BKE_add_linestyle_thickness_modifier(lineset->linestyle, type) == NULL) { BKE_report(op->reports, RPT_ERROR, "Unknown line thickness modifier type"); return OPERATOR_CANCELLED; @@ -1007,10 +1026,10 @@ static int freestyle_geometry_modifier_add_exec(bContext *C, wmOperator *op) FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(&srl->freestyleConfig); int type = RNA_enum_get(op->ptr, "type"); - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style to add the modifier to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } + if (BKE_add_linestyle_geometry_modifier(lineset->linestyle, type) == NULL) { BKE_report(op->reports, RPT_ERROR, "Unknown stroke geometry modifier type"); return OPERATOR_CANCELLED; @@ -1060,8 +1079,7 @@ static int freestyle_modifier_remove_exec(bContext *C, wmOperator *op) PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); LineStyleModifier *modifier = ptr.data; - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } @@ -1110,8 +1128,7 @@ static int freestyle_modifier_copy_exec(bContext *C, wmOperator *op) PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_LineStyleModifier); LineStyleModifier *modifier = ptr.data; - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } @@ -1161,8 +1178,7 @@ static int freestyle_modifier_move_exec(bContext *C, wmOperator *op) LineStyleModifier *modifier = ptr.data; int dir = RNA_enum_get(op->ptr, "direction"); - if (!lineset) { - BKE_report(op->reports, RPT_ERROR, "No active lineset and associated line style the modifier belongs to"); + if (!freestyle_linestyle_check_report(lineset, op->reports)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 13befeceee9..d356c3d8de3 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -531,7 +531,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, components = 4; else if (format == GL_RGB) components = 3; - else if (format == GL_LUMINANCE) + else if (ELEM(format, GL_LUMINANCE, GL_ALPHA)) components = 1; else { BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); @@ -1091,18 +1091,15 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter, if (ibuf->rect_float) { if (ibuf->float_colorspace) { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->float_colorspace, - true, false); + ibuf->float_colorspace, true); } else { - ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, - true, false); + ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, true); } } else { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->rect_colorspace, - false, false); + ibuf->rect_colorspace, false); } if (ok) { @@ -1160,57 +1157,3 @@ void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int glaDrawImBuf_glsl(ibuf, x, y, zoomfilter, view_settings, display_settings); } - -/* Transform buffer from role to scene linear space using GLSL OCIO conversion - * - * See IMB_colormanagement_setup_transform_from_role_glsl description for - * some more details - * - * NOTE: this only works for RGBA buffers! - */ -int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role) -{ - GPUOffScreen *ofs; - char err_out[256]; - rcti display_rect; - - ofs = GPU_offscreen_create(width, height, err_out); - - if (!ofs) - return FALSE; - - GPU_offscreen_bind(ofs); - - if (!IMB_colormanagement_setup_transform_from_role_glsl(role, true)) { - GPU_offscreen_unbind(ofs); - GPU_offscreen_free(ofs); - return FALSE; - } - - BLI_rcti_init(&display_rect, 0, width, 0, height); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glaDefine2DArea(&display_rect); - - glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT, - GL_NEAREST, buffer); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer); - - IMB_colormanagement_finish_glsl_transform(); - - /* unbind */ - GPU_offscreen_unbind(ofs); - GPU_offscreen_free(ofs); - - return TRUE; -} diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 40447a0106a..dbe1197436b 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -85,7 +85,7 @@ static void screenshot_read_pixels(int x, int y, int w, int h, unsigned char *re glFinish(); /* clear alpha, it is not set to a meaningful value in opengl */ - for (i = 0, rect += 3; i < w*h; i++, rect += 4) + for (i = 0, rect += 3; i < w * h; i++, rect += 4) *rect = 255; } @@ -327,7 +327,7 @@ static void screenshot_updatejob(void *sjv) if (sj->dumprect == NULL) { dumprect = MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect"); - screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char*)dumprect); + screenshot_read_pixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, (unsigned char *)dumprect); sj->dumprect = dumprect; } diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index c18afd066fa..56143d00afe 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -73,12 +73,38 @@ typedef struct TexSnapshot { GLuint overlay_texture; int winx; int winy; - bool init; int old_size; float old_zoom; bool old_col; } TexSnapshot; +typedef struct CursorSnapshot { + GLuint overlay_texture; + int size; + int zoom; +} CursorSnapshot; + +static TexSnapshot primary_snap = {0}; +static TexSnapshot secondary_snap = {0}; +static CursorSnapshot cursor_snap = {0}; + +/* delete overlay cursor textures to preserve memory and invalidate all overlay flags */ +void paint_cursor_delete_textures(void) +{ + if (primary_snap.overlay_texture) + glDeleteTextures(1, &primary_snap.overlay_texture); + if (secondary_snap.overlay_texture) + glDeleteTextures(1, &secondary_snap.overlay_texture); + if (cursor_snap.overlay_texture) + glDeleteTextures(1, &cursor_snap.overlay_texture); + + memset(&primary_snap, 0, sizeof(TexSnapshot)); + memset(&secondary_snap, 0, sizeof(TexSnapshot)); + memset(&cursor_snap, 0, sizeof(CursorSnapshot)); + + BKE_paint_invalidate_overlay_all(); +} + static int same_tex_snap(TexSnapshot *snap, MTex *mtex, ViewContext *vc, bool col, float zoom) { return (/* make brush smaller shouldn't cause a resample */ @@ -103,9 +129,7 @@ static void make_tex_snap(TexSnapshot *snap, ViewContext *vc, float zoom) static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool primary) { - static int init = 0; - static TexSnapshot primary_snap = {0}; - static TexSnapshot secondary_snap = {0}; + bool init; TexSnapshot *target; MTex *mtex = (primary) ? &br->mtex : &br->mask_mtex; @@ -120,12 +144,14 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima (overlay_flags & PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY); target = (primary) ? &primary_snap : &secondary_snap; - + refresh = !target->overlay_texture || (invalid != 0) || !same_tex_snap(target, mtex, vc, col, zoom); + init = (target->overlay_texture != 0); + if (refresh) { struct ImagePool *pool = NULL; /* stencil is rotated later */ @@ -160,7 +186,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima target->overlay_texture = 0; } - init = 0; + init = false; target->old_size = size; } @@ -267,7 +293,6 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima if (refresh) { if (!init || (target->old_col != col)) { glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, buffer); - init = 1; } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, format, GL_UNSIGNED_BYTE, buffer); @@ -297,10 +322,7 @@ static int load_tex(Brush *br, ViewContext *vc, float zoom, bool col, bool prima static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) { - static GLuint overlay_texture = 0; - static int init = 0; - static int old_size = -1; - static int old_zoom = -1; + bool init; OverlayControlFlags overlay_flags = BKE_paint_get_overlay_flags(); GLubyte *buffer = NULL; @@ -310,14 +332,16 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) int refresh; refresh = - !overlay_texture || + !cursor_snap.overlay_texture || (overlay_flags & PAINT_INVALID_OVERLAY_CURVE) || - old_zoom != zoom; + cursor_snap.zoom != zoom; + + init = (cursor_snap.overlay_texture != 0); if (refresh) { int s, r; - old_zoom = zoom; + cursor_snap.zoom = zoom; s = BKE_brush_size_get(vc->scene, br); r = 1; @@ -330,18 +354,18 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) if (size < 256) size = 256; - if (size < old_size) - size = old_size; + if (size < cursor_snap.size) + size = cursor_snap.size; - if (old_size != size) { - if (overlay_texture) { - glDeleteTextures(1, &overlay_texture); - overlay_texture = 0; + if (cursor_snap.size != size) { + if (cursor_snap.overlay_texture) { + glDeleteTextures(1, &cursor_snap.overlay_texture); + cursor_snap.overlay_texture = 0; } - init = 0; + init = false; - old_size = size; + cursor_snap.size = size; } buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex"); @@ -383,19 +407,18 @@ static int load_tex_cursor(Brush *br, ViewContext *vc, float zoom) } } - if (!overlay_texture) - glGenTextures(1, &overlay_texture); + if (!cursor_snap.overlay_texture) + glGenTextures(1, &cursor_snap.overlay_texture); } else { - size = old_size; + size = cursor_snap.size; } - glBindTexture(GL_TEXTURE_2D, overlay_texture); + glBindTexture(GL_TEXTURE_2D, cursor_snap.overlay_texture); if (refresh) { if (!init) { glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, size, size, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); - init = 1; } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, size, GL_ALPHA, GL_UNSIGNED_BYTE, buffer); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index feff02fa121..a5d4ff98b4b 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -792,6 +792,7 @@ static void toggle_paint_cursor(bContext *C, int enable) if (settings->imapaint.paintcursor && !enable) { WM_paint_cursor_end(wm, settings->imapaint.paintcursor); settings->imapaint.paintcursor = NULL; + paint_cursor_delete_textures(); } else if (enable) paint_cursor_start(C, image_paint_poll); @@ -820,6 +821,9 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll); } + else { + paint_cursor_delete_textures(); + } } /************************ grab clone operator ************************/ @@ -922,9 +926,15 @@ void PAINT_OT_grab_clone(wmOperatorType *ot) } /******************** sample color operator ********************/ +typedef struct { + bool show_cursor; + short event_type; +} SampleColorData; + static int sample_color_exec(bContext *C, wmOperator *op) { - Brush *brush = image_paint_brush(C); + Paint *paint = BKE_paint_get_active_from_context(C); + Brush *brush = BKE_paint_brush(paint); ARegion *ar = CTX_wm_region(C); int location[2]; @@ -938,11 +948,17 @@ static int sample_color_exec(bContext *C, wmOperator *op) static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + Paint *paint = BKE_paint_get_active_from_context(C); + SampleColorData *data = MEM_mallocN(sizeof(SampleColorData), "sample color custom data"); + + data->event_type = event->type; + data->show_cursor = ((paint->flags & PAINT_SHOW_BRUSH) != 0); + op->customdata = data; + paint->flags &= ~PAINT_SHOW_BRUSH; + RNA_int_set_array(op->ptr, "location", event->mval); sample_color_exec(C, op); - op->customdata = SET_INT_IN_POINTER(event->type); - WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; @@ -950,8 +966,18 @@ static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) { - if (event->type == (intptr_t)(op->customdata) && event->val == KM_RELEASE) + SampleColorData *data = op->customdata; + + if ((event->type == data->event_type) && (event->val == KM_RELEASE)) { + Paint *paint = BKE_paint_get_active_from_context(C); + + if(data->show_cursor) { + paint->flags |= PAINT_SHOW_BRUSH; + } + + MEM_freeN(data); return OPERATOR_FINISHED; + } switch (event->type) { case MOUSEMOVE: @@ -963,24 +989,9 @@ static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_RUNNING_MODAL; } -/* same as image_paint_poll but fail when face mask mode is enabled */ -static int image_paint_sample_color_poll(bContext *C) +static int sample_color_poll(bContext *C) { - if (image_paint_poll(C)) { - if (CTX_wm_view3d(C)) { - Object *obact = CTX_data_active_object(C); - if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) { - Mesh *me = BKE_mesh_from_object(obact); - if (me) { - return !(me->editflag & ME_EDIT_PAINT_FACE_SEL); - } - } - } - - return 1; - } - - return 0; + return (image_paint_poll(C) || vertex_paint_poll(C)); } void PAINT_OT_sample_color(wmOperatorType *ot) @@ -994,7 +1005,7 @@ void PAINT_OT_sample_color(wmOperatorType *ot) ot->exec = sample_color_exec; ot->invoke = sample_color_invoke; ot->modal = sample_color_modal; - ot->poll = image_paint_sample_color_poll; + ot->poll = sample_color_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index c90f9756707..4a2046f6682 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -3129,7 +3129,7 @@ static void project_paint_begin(ProjPaintState *ps) ps->thread_tot = 1; for (a = 0; a < ps->thread_tot; a++) { - ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena"); + ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena"); } arena = ps->arena_mt[0]; @@ -3841,10 +3841,10 @@ static void *do_projectpaint_thread(void *ph_v) pos_ofs[0] = pos[0] - lastpos[0]; pos_ofs[1] = pos[1] - lastpos[1]; - smearArena = BLI_memarena_new(1 << 16, "paint smear arena"); + smearArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint smear arena"); } else if (tool == PAINT_TOOL_SOFTEN) { - softenArena = BLI_memarena_new(1 << 16, "paint soften arena"); + softenArena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "paint soften arena"); } /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */ diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 6c13f6efb74..2545328ec65 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -74,6 +74,7 @@ bool paint_space_stroke_enabled(struct Brush *br, enum PaintMode mode); bool paint_supports_dynamic_size(struct Brush *br, enum PaintMode mode); bool paint_supports_dynamic_tex_coords(struct Brush *br, enum PaintMode mode); bool paint_supports_smooth_stroke(struct Brush *br, enum PaintMode mode); +bool paint_supports_texture(enum PaintMode mode); bool paint_supports_jitter(enum PaintMode mode); struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf); @@ -86,6 +87,7 @@ void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data); int paint_poll(struct bContext *C); void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C)); void paint_cursor_start_explicit(struct Paint *p, struct wmWindowManager *wm, int (*poll)(struct bContext *C)); +void paint_cursor_delete_textures(void); /* paint_vertex.c */ int weight_paint_poll(struct bContext *C); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 0b0607babc1..8b038973831 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -728,9 +728,16 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve static int stencil_control_poll(bContext *C) { - Paint *paint = BKE_paint_get_active_from_context(C); - Brush *br = BKE_paint_brush(paint); + PaintMode mode = BKE_paintmode_get_active_from_context(C); + + Paint *paint; + Brush *br; + + if (!paint_supports_texture(mode)) + return false; + paint = BKE_paint_get_active_from_context(C); + br = BKE_paint_brush(paint); return (br && (br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL || br->mask_mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL)); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 973f6555deb..b00b1c3ecff 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -572,6 +572,12 @@ bool paint_supports_smooth_stroke(Brush *br, PaintMode mode) return true; } +bool paint_supports_texture(PaintMode mode) +{ + /* ommit: PAINT_WEIGHT, PAINT_SCULPT_UV, PAINT_INVALID */ + return ELEM4(mode, PAINT_SCULPT, PAINT_VERTEX, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D); +} + /* return true if the brush size can change during paint (normally used for pressure) */ bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode) { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index d376bd3180f..bfc431baea5 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -441,7 +441,7 @@ static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wm void PAINT_OT_face_select_linked_pick(wmOperatorType *ot) { ot->name = "Select Linked Pick"; - ot->description = "Select linked faces"; + ot->description = "Select linked faces under the cursor"; ot->idname = "PAINT_OT_face_select_linked_pick"; ot->invoke = paint_select_linked_pick_invoke; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 538e8394b1f..1c3caf5d8bc 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2062,6 +2062,8 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) /* weight paint spesific */ mesh_octree_table(NULL, NULL, NULL, 'e'); mesh_mirrtopo_table(NULL, 'e'); + + paint_cursor_delete_textures(); } else { ob->mode |= mode_flag; @@ -2684,6 +2686,8 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { BKE_mesh_flush_select_from_polys(me); } + + paint_cursor_delete_textures(); } else { ob->mode |= mode_flag; @@ -2784,7 +2788,7 @@ static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) int *origIndex; int i; - vd->polyfacemap_arena = BLI_memarena_new(1 << 13, "vpaint tmp"); + vd->polyfacemap_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "vpaint tmp"); BLI_memarena_use_calloc(vd->polyfacemap_arena); vd->polyfacemap = BLI_memarena_alloc(vd->polyfacemap_arena, sizeof(ListBase) * me->totpoly); @@ -3480,7 +3484,7 @@ void PAINT_OT_weight_gradient(wmOperatorType *ot) /* identifiers */ ot->name = "Weight Gradient"; ot->idname = "PAINT_OT_weight_gradient"; - ot->description = "Sample a line and show it in Scope panels"; + ot->description = "Draw a line to apply a weight gradient to selected vertices"; /* api callbacks */ ot->invoke = paint_weight_gradient_invoke; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 3f58795cae4..2a6b6d4b3d9 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1791,6 +1791,7 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) /* offset with as much as possible factored in already */ mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius); + mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); /* threaded loop over nodes */ @@ -1835,6 +1836,7 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod /* offset with as much as possible factored in already */ mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius); + mul_v3_v3(offset, ss->cache->scale); mul_v3_fl(offset, bstrength); /* we divide out the squared alpha and multiply by the squared crease to give us the pinch strength */ @@ -2263,7 +2265,8 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno if (vd.fno) copy_v3_v3(val, vd.fno); else normal_short_to_float_v3(val, vd.no); - mul_v3_v3fl(proxy[vd.i], val, fade * ss->cache->radius); + mul_v3_fl(val, fade * ss->cache->radius); + mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); if (vd.mvert) vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -2642,7 +2645,8 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno displace = radius * offset; - mul_v3_v3fl(temp, an, displace); + mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_fl(temp, displace); add_v3_v3(fc, temp); #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) @@ -2711,7 +2715,8 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) displace = radius * (0.25f + offset); - mul_v3_v3fl(temp, an, displace); + mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_fl(temp, displace); add_v3_v3(fc, temp); /* add_v3_v3v3(p, ss->cache->location, an); */ @@ -2798,7 +2803,8 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t displace = radius * (0.25f + offset); - mul_v3_v3fl(temp, sn, displace); + mul_v3_v3v3(temp, sn, ss->cache->scale); + mul_v3_fl(temp, displace); add_v3_v3(fc, temp); /* init mat */ @@ -2877,7 +2883,8 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) displace = radius * offset; - mul_v3_v3fl(temp, an, displace); + mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_fl(temp, displace); add_v3_v3(fc, temp); #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) @@ -2940,7 +2947,8 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod displace = -radius * offset; - mul_v3_v3fl(temp, an, displace); + mul_v3_v3v3(temp, an, ss->cache->scale); + mul_v3_fl(temp, displace); add_v3_v3(fc, temp); #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) @@ -3787,15 +3795,26 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio Object *ob = CTX_data_active_object(C); float mat[3][3]; float viewDir[3] = {0.0f, 0.0f, 1.0f}; + float max_scale; int i; int mode; ss->cache = cache; /* Set scaling adjustment */ - cache->scale[0] = 1.0f / ob->size[0]; - cache->scale[1] = 1.0f / ob->size[1]; - cache->scale[2] = 1.0f / ob->size[2]; + if (brush->sculpt_tool == SCULPT_TOOL_LAYER) { + max_scale = 1.0f; + } + else { + max_scale = 0.0f; + for (i = 0; i < 3; i ++) { + max_scale = max_ff(max_scale, fabsf(ob->size[i])); + } + } + cache->scale[0] = max_scale / ob->size[0]; + cache->scale[1] = max_scale / ob->size[1]; + cache->scale[2] = max_scale / ob->size[2]; + cache->plane_trim_squared = brush->plane_trim * brush->plane_trim; @@ -4920,7 +4939,7 @@ int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { GridPaintMask *gmask; int level = max_ii(1, mmd->sculptlvl); - int gridsize = ccg_gridsize(level); + int gridsize = BKE_ccg_gridsize(level); int gridarea = gridsize * gridsize; int i, j; @@ -5020,6 +5039,8 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) ob->mode &= ~mode_flag; free_sculptsession(ob); + + paint_cursor_delete_textures(); } else { /* Enter sculptmode */ diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index d630b6478fb..7a973d8c1ae 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -45,6 +45,7 @@ #include "BKE_brush.h" #include "BKE_paint.h" +#include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_main.h" #include "BKE_depsgraph.h" @@ -538,6 +539,8 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm op->customdata = data; + curvemapping_initialize(ts->uvsculpt->paint.brush->curve); + if (data) { int counter = 0, i; ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 0d64a3ce594..f5db34d87d7 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -710,8 +710,14 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip if (queue->direction > 0) { current_frame = prefetch_find_uncached_frame(clip, queue->current_frame + 1, queue->end_frame, queue->render_size, queue->render_flag, 1); + /* switch direction if read frames from current up to scene end frames */ + if (current_frame >= queue->end_frame) { + queue->current_frame = queue->initial_frame; + queue->direction = -1; + } } - else { + + if (queue->direction < 0) { current_frame = prefetch_find_uncached_frame(clip, queue->current_frame - 1, queue->start_frame, queue->render_size, queue->render_flag, -1); } @@ -736,12 +742,6 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip *queue->do_update = 1; *queue->progress = (float)frames_processed / (queue->end_frame - queue->start_frame); - - /* switch direction if read frames from current up to scene end frames */ - if (current_frame == queue->end_frame) { - queue->current_frame = queue->initial_frame; - queue->direction = -1; - } } } BLI_spin_unlock(&queue->spin); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 3ede63adb72..adc902bf4ba 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1191,7 +1191,9 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) int mask_width, mask_height; ED_mask_get_size(sa, &mask_width, &mask_height); ED_mask_draw_region(mask, ar, - sc->mask_info.draw_flag, sc->mask_info.draw_type, + sc->mask_info.draw_flag, + sc->mask_info.draw_type, + sc->mask_info.overlay_mode, mask_width, mask_height, aspx, aspy, TRUE, TRUE, diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 88a04197847..5c8d1e84fd5 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -317,6 +317,7 @@ static void console_keymap(struct wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "CONSOLE_OT_delete", BACKSPACEKEY, KM_PRESS, KM_CTRL, 0)->ptr, "type", DEL_PREV_WORD); WM_keymap_add_item(keymap, "CONSOLE_OT_clear_line", RETKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "CONSOLE_OT_clear_line", PADENTER, KM_PRESS, KM_SHIFT, 0); #ifdef WITH_PYTHON kmi = WM_keymap_add_item(keymap, "CONSOLE_OT_execute", RETKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt index b30f008e1bf..3b2db3ee7bc 100644 --- a/source/blender/editors/space_file/CMakeLists.txt +++ b/source/blender/editors/space_file/CMakeLists.txt @@ -58,6 +58,10 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_OPENIMAGEIO) + add_definitions(-DWITH_OPENIMAGEIO) +endif() + if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() diff --git a/source/blender/editors/space_file/SConscript b/source/blender/editors/space_file/SConscript index e1eadb66a11..d42394454eb 100644 --- a/source/blender/editors/space_file/SConscript +++ b/source/blender/editors/space_file/SConscript @@ -55,6 +55,9 @@ if env['WITH_BF_OPENEXR']: if env['WITH_BF_TIFF']: defs.append('WITH_TIFF') +if env['WITH_BF_OIIO']: + defs.append('WITH_OPENIMAGEIO') + if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 240106d37d5..d01286442be 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -65,7 +65,7 @@ void FILE_OT_select_all_toggle(struct wmOperatorType *ot); void FILE_OT_select_border(struct wmOperatorType *ot); void FILE_OT_select_bookmark(struct wmOperatorType *ot); void FILE_OT_bookmark_add(struct wmOperatorType *ot); -void FILE_OT_delete_bookmark(struct wmOperatorType *ot); +void FILE_OT_bookmark_delete(struct wmOperatorType *ot); void FILE_OT_reset_recent(wmOperatorType *ot); void FILE_OT_hidedot(struct wmOperatorType *ot); void FILE_OT_execute(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index e3270d9ce8e..a97b3b1d719 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -503,14 +503,14 @@ static int bookmark_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void FILE_OT_delete_bookmark(wmOperatorType *ot) +void FILE_OT_bookmark_delete(wmOperatorType *ot) { PropertyRNA *prop; /* identifiers */ ot->name = "Delete Bookmark"; ot->description = "Delete selected bookmark"; - ot->idname = "FILE_OT_delete_bookmark"; + ot->idname = "FILE_OT_bookmark_delete"; /* api callbacks */ ot->exec = bookmark_delete_exec; diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c index 0efc7b927a9..f4161c7da1c 100644 --- a/source/blender/editors/space_file/file_panels.c +++ b/source/blender/editors/space_file/file_panels.c @@ -121,7 +121,7 @@ static void file_panel_category(const bContext *C, Panel *pa, FSMenuCategory cat /* create delete button */ if (allow_delete && fsmenu_can_save(fsmenu, category, i)) { uiBlockSetEmboss(block, UI_EMBOSSN); - uiItemIntO(layout, "", ICON_X, "FILE_OT_delete_bookmark", "index", i); + uiItemIntO(layout, "", ICON_X, "FILE_OT_bookmark_delete", "index", i); uiBlockSetEmboss(block, UI_EMBOSS); } } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 9758e2e9135..1a8565a58b1 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -387,7 +387,7 @@ static void file_operatortypes(void) WM_operatortype_append(FILE_OT_refresh); WM_operatortype_append(FILE_OT_bookmark_toggle); WM_operatortype_append(FILE_OT_bookmark_add); - WM_operatortype_append(FILE_OT_delete_bookmark); + WM_operatortype_append(FILE_OT_bookmark_delete); WM_operatortype_append(FILE_OT_reset_recent); WM_operatortype_append(FILE_OT_hidedot); WM_operatortype_append(FILE_OT_filenum); diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index 7610f7a9192..23c39a5e99a 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -951,7 +951,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid /* 1) draw curve line */ { /* set color/drawing style for curve itself */ - if (((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED)) { + if (BKE_fcurve_is_protected(fcu)) { /* protected curves (non editable) are drawn with dotted lines */ setlinestyle(2); } diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index 6509af179e7..50d8051a73e 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -50,6 +50,10 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_OPENIMAGEIO) + add_definitions(-DWITH_OPENIMAGEIO) +endif() + if(WITH_IMAGE_OPENJPEG) add_definitions(-DWITH_OPENJPEG) endif() diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript index 268172b300d..89def32e70f 100644 --- a/source/blender/editors/space_image/SConscript +++ b/source/blender/editors/space_image/SConscript @@ -57,6 +57,8 @@ if env['WITH_BF_TIFF']: defs.append('WITH_TIFF') if env['WITH_BF_CINEON']: defs.append('WITH_CINEON') +if env['WITH_BF_OIIO']: + defs.append('WITH_OPENIMAGEIO') if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 144d2c14e9f..3ff404d38a9 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -640,7 +640,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char else uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); - row = uiLayoutRow(row, FALSE); + row = uiLayoutRow(row, TRUE); uiLayoutSetEnabled(row, ima->packedfile == NULL); uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 23c85699b00..89e57955339 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -268,8 +268,6 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def else rgba[3] = linearcol[3]; - (void)color_manage; - if (use_default_view) IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings); else @@ -360,14 +358,8 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_def dx += BLF_width(blf_mono_font, str); } else if (channels >= 3) { - if (fp) { - rgb_to_hsv(fp[0], fp[1], fp[2], &hue, &sat, &val); - rgb_to_yuv(fp[0], fp[1], fp[2], &lum, &u, &v); - } - else if (cp) { - rgb_to_hsv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &hue, &sat, &val); - rgb_to_yuv((float)cp[0] / 255.0f, (float)cp[1] / 255.0f, (float)cp[2] / 255.0f, &lum, &u, &v); - } + rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val); + rgb_to_yuv(finalcol[0], finalcol[1], finalcol[2], &lum, &u, &v); BLI_snprintf(str, sizeof(str), "H:%-.4f", hue); BLF_position(blf_mono_font, dx, 0.3f * UI_UNIT_X, 0); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 2da109d281b..710d5c8cd81 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1804,7 +1804,7 @@ static int image_new_exec(bContext *C, wmOperator *op) BKE_image_signal(ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_USER_NEW_IMAGE); - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima); return OPERATOR_FINISHED; } @@ -2417,6 +2417,9 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) hist->co[1][0] = x2f; hist->co[1][1] = y2f; + /* enable line drawing */ + hist->flag |= HISTO_FLAG_SAMPLELINE; + BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings); /* reset y zoom */ diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 5a8292abcab..7b20af340ae 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -674,7 +674,6 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) } else if (sima->mode == SI_MODE_MASK) { mask = ED_space_image_get_mask(sima); - draw_image_cursor(ar, sima->cursor); } ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); @@ -715,7 +714,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) BLI_unlock_thread(LOCK_DRAW_IMAGE); ED_mask_draw_region(mask, ar, - sima->mask_info.draw_flag, sima->mask_info.draw_type, + sima->mask_info.draw_flag, + sima->mask_info.draw_type, + sima->mask_info.overlay_mode, width, height, aspx, aspy, TRUE, FALSE, @@ -723,7 +724,9 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) ED_mask_draw_frames(mask, ar, CFRA, mask->sfra, mask->efra); + UI_view2d_view_ortho(v2d); draw_image_cursor(ar, sima->cursor); + UI_view2d_view_restore(C); } /* scrollers? */ diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index c1cddf092aa..9686c6dfc29 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -194,9 +194,9 @@ static void stats_object_edit(Object *obedit, SceneStats *stats) a = nu->pntsu; while (a--) { stats->totvert += 3; - if (bezt->f1) stats->totvertsel++; - if (bezt->f2) stats->totvertsel++; - if (bezt->f3) stats->totvertsel++; + if (bezt->f1 & SELECT) stats->totvertsel++; + if (bezt->f2 & SELECT) stats->totvertsel++; + if (bezt->f3 & SELECT) stats->totvertsel++; bezt++; } } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 913e48ebb7d..ba28f502349 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -86,18 +86,6 @@ static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, Poin uiItemL(layout, text, 0); } -static void node_draw_input_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr) -{ - bNodeSocket *sock = (bNodeSocket *)ptr->data; - sock->typeinfo->draw(C, layout, ptr, node_ptr, IFACE_(sock->name)); -} - -static void node_draw_output_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr) -{ - bNodeSocket *sock = ptr->data; - node_socket_button_label(C, layout, ptr, node_ptr, IFACE_(sock->name)); -} - /* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */ @@ -339,7 +327,7 @@ static int node_resize_area_default(bNode *node, int x, int y) /* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */ -static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_draw_buttons_group(uiLayout *layout, bContext *C, PointerRNA *ptr) { uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL); } @@ -348,7 +336,7 @@ static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr) * Not ideal to do this in every draw call, but doing as transform callback doesn't work, * since the child node totr rects are not updated properly at that point. */ -static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node) +static void node_draw_frame_prepare(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node) { const float margin = 1.5f * U.widget_unit; NodeFrame *data = (NodeFrame *)node->storage; @@ -511,7 +499,7 @@ static int node_resize_area_frame(bNode *node, int x, int y) return dir; } -static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE); uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE); @@ -520,7 +508,7 @@ static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), Point #define NODE_REROUTE_SIZE 8.0f -static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node) +static void node_draw_reroute_prepare(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *nsock; float locx, locy; @@ -571,7 +559,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( */ #if 0 /* body */ - uiSetRoundBox(15); + uiSetRoundBox(UI_CNR_ALL); UI_ThemeColor4(TH_NODE); glEnable(GL_BLEND); uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size); @@ -632,17 +620,17 @@ static void node_common_set_butfunc(bNodeType *ntype) { switch (ntype->type) { case NODE_GROUP: - ntype->uifunc = node_uifunc_group; + ntype->draw_buttons = node_draw_buttons_group; break; case NODE_FRAME: - ntype->drawfunc = node_draw_frame; - ntype->drawupdatefunc = node_update_frame; - ntype->uifuncbut = node_buts_frame_details; + ntype->draw_nodetype = node_draw_frame; + ntype->draw_nodetype_prepare = node_draw_frame_prepare; + ntype->draw_buttons_ex = node_buts_frame_ex; ntype->resize_area_func = node_resize_area_frame; break; case NODE_REROUTE: - ntype->drawfunc = node_draw_reroute; - ntype->drawupdatefunc = node_update_reroute; + ntype->draw_nodetype = node_draw_reroute; + ntype->draw_nodetype_prepare = node_draw_reroute_prepare; ntype->tweak_area_func = node_tweak_area_reroute; break; } @@ -709,7 +697,7 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin { uiLayout *row; - uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); uiItemL(layout, IFACE_("Location:"), ICON_NONE); row = uiLayoutRow(layout, TRUE); @@ -739,7 +727,7 @@ static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), Po static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE); uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE); } @@ -792,7 +780,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr); } -static void node_shader_buts_tex_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0); @@ -920,7 +908,7 @@ static void node_shader_buts_subsurface(uiLayout *layout, bContext *C, PointerRN if (scene.data) { PointerRNA cscene = RNA_pointer_get(&scene, "cycles"); if (cscene.data && RNA_enum_get(&cscene, "device") == 1) - uiItemL(layout, IFACE_("SSS not supported on GPU"), ICON_NONE); + uiItemL(layout, IFACE_("SSS not supported on GPU"), ICON_ERROR); } uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE); @@ -953,7 +941,7 @@ static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), Point uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update"); } -static void node_shader_buts_script_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { uiItemS(layout); @@ -971,110 +959,110 @@ static void node_shader_set_butfunc(bNodeType *ntype) switch (ntype->type) { case SH_NODE_MATERIAL: case SH_NODE_MATERIAL_EXT: - ntype->uifunc = node_shader_buts_material; + ntype->draw_buttons = node_shader_buts_material; break; case SH_NODE_TEXTURE: - ntype->uifunc = node_buts_texture; + ntype->draw_buttons = node_buts_texture; break; case SH_NODE_NORMAL: - ntype->uifunc = node_buts_normal; + ntype->draw_buttons = node_buts_normal; break; case SH_NODE_CURVE_VEC: - ntype->uifunc = node_buts_curvevec; + ntype->draw_buttons = node_buts_curvevec; break; case SH_NODE_CURVE_RGB: - ntype->uifunc = node_buts_curvecol; + ntype->draw_buttons = node_buts_curvecol; break; case SH_NODE_MAPPING: - ntype->uifunc = node_shader_buts_mapping; + ntype->draw_buttons = node_shader_buts_mapping; break; case SH_NODE_VALUE: - ntype->uifunc = node_buts_value; + ntype->draw_buttons = node_buts_value; break; case SH_NODE_RGB: - ntype->uifunc = node_buts_rgb; + ntype->draw_buttons = node_buts_rgb; break; case SH_NODE_MIX_RGB: - ntype->uifunc = node_buts_mix_rgb; + ntype->draw_buttons = node_buts_mix_rgb; break; case SH_NODE_VALTORGB: - ntype->uifunc = node_buts_colorramp; + ntype->draw_buttons = node_buts_colorramp; break; case SH_NODE_MATH: - ntype->uifunc = node_buts_math; + ntype->draw_buttons = node_buts_math; break; case SH_NODE_VECT_MATH: - ntype->uifunc = node_shader_buts_vect_math; + ntype->draw_buttons = node_shader_buts_vect_math; break; case SH_NODE_VECT_TRANSFORM: - ntype->uifunc = node_shader_buts_vect_transform; + ntype->draw_buttons = node_shader_buts_vect_transform; break; case SH_NODE_GEOMETRY: - ntype->uifunc = node_shader_buts_geometry; + ntype->draw_buttons = node_shader_buts_geometry; break; case SH_NODE_ATTRIBUTE: - ntype->uifunc = node_shader_buts_attribute; + ntype->draw_buttons = node_shader_buts_attribute; break; case SH_NODE_WIREFRAME: - ntype->uifunc = node_shader_buts_wireframe; + ntype->draw_buttons = node_shader_buts_wireframe; break; case SH_NODE_TEX_SKY: - ntype->uifunc = node_shader_buts_tex_sky; + ntype->draw_buttons = node_shader_buts_tex_sky; break; case SH_NODE_TEX_IMAGE: - ntype->uifunc = node_shader_buts_tex_image; - ntype->uifuncbut = node_shader_buts_tex_image_details; + ntype->draw_buttons = node_shader_buts_tex_image; + ntype->draw_buttons_ex = node_shader_buts_tex_image_ex; break; case SH_NODE_TEX_ENVIRONMENT: - ntype->uifunc = node_shader_buts_tex_environment; + ntype->draw_buttons = node_shader_buts_tex_environment; break; case SH_NODE_TEX_GRADIENT: - ntype->uifunc = node_shader_buts_tex_gradient; + ntype->draw_buttons = node_shader_buts_tex_gradient; break; case SH_NODE_TEX_MAGIC: - ntype->uifunc = node_shader_buts_tex_magic; + ntype->draw_buttons = node_shader_buts_tex_magic; break; case SH_NODE_TEX_BRICK: - ntype->uifunc = node_shader_buts_tex_brick; + ntype->draw_buttons = node_shader_buts_tex_brick; break; case SH_NODE_TEX_WAVE: - ntype->uifunc = node_shader_buts_tex_wave; + ntype->draw_buttons = node_shader_buts_tex_wave; break; case SH_NODE_TEX_MUSGRAVE: - ntype->uifunc = node_shader_buts_tex_musgrave; + ntype->draw_buttons = node_shader_buts_tex_musgrave; break; case SH_NODE_TEX_VORONOI: - ntype->uifunc = node_shader_buts_tex_voronoi; + ntype->draw_buttons = node_shader_buts_tex_voronoi; break; case SH_NODE_TEX_COORD: - ntype->uifunc = node_shader_buts_tex_coord; + ntype->draw_buttons = node_shader_buts_tex_coord; break; case SH_NODE_BUMP: - ntype->uifunc = node_shader_buts_bump; + ntype->draw_buttons = node_shader_buts_bump; break; case SH_NODE_NORMAL_MAP: - ntype->uifunc = node_shader_buts_normal_map; + ntype->draw_buttons = node_shader_buts_normal_map; break; case SH_NODE_TANGENT: - ntype->uifunc = node_shader_buts_tangent; + ntype->draw_buttons = node_shader_buts_tangent; break; case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: case SH_NODE_BSDF_REFRACTION: - ntype->uifunc = node_shader_buts_glossy; + ntype->draw_buttons = node_shader_buts_glossy; break; case SH_NODE_SUBSURFACE_SCATTERING: - ntype->uifunc = node_shader_buts_subsurface; + ntype->draw_buttons = node_shader_buts_subsurface; break; case SH_NODE_BSDF_TOON: - ntype->uifunc = node_shader_buts_toon; + ntype->draw_buttons = node_shader_buts_toon; break; case SH_NODE_BSDF_HAIR: - ntype->uifunc = node_shader_buts_hair; + ntype->draw_buttons = node_shader_buts_hair; break; case SH_NODE_SCRIPT: - ntype->uifunc = node_shader_buts_script; - ntype->uifuncbut = node_shader_buts_script_details; + ntype->draw_buttons = node_shader_buts_script; + ntype->draw_buttons_ex = node_shader_buts_script_ex; break; } } @@ -1096,7 +1084,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr); } -static void node_composit_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; PointerRNA iuserptr; @@ -1578,46 +1566,6 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE); } -/* draw function for file output node sockets, displays only sub-path and format, no value button */ -static void node_draw_input_file_output(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr) -{ - bNodeTree *ntree = ptr->id.data; - bNodeSocket *sock = ptr->data; - uiLayout *row; - PointerRNA inputptr, imfptr; - int imtype; - - row = uiLayoutRow(layout, FALSE); - - imfptr = RNA_pointer_get(node_ptr, "format"); - imtype = RNA_enum_get(&imfptr, "file_format"); - if (imtype == R_IMF_IMTYPE_MULTILAYER) { - NodeImageMultiFileSocket *input = sock->storage; - RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr); - - uiItemL(row, input->layer, ICON_NONE); - } - else { - NodeImageMultiFileSocket *input = sock->storage; - PropertyRNA *imtype_prop; - const char *imtype_name; - uiBlock *block; - RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr); - - uiItemL(row, input->path, ICON_NONE); - - if (!RNA_boolean_get(&inputptr, "use_node_format")) - imfptr = RNA_pointer_get(&inputptr, "format"); - - imtype_prop = RNA_struct_find_property(&imfptr, "file_format"); - RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop, - RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name); - block = uiLayoutGetBlock(row); - uiBlockSetEmboss(block, UI_EMBOSSP); - uiItemL(row, imtype_name, ICON_NONE); - uiBlockSetEmboss(block, UI_EMBOSSN); - } -} static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { PointerRNA imfptr = RNA_pointer_get(ptr, "format"); @@ -1629,7 +1577,7 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C) uiItemL(layout, IFACE_("Base Path:"), ICON_NONE); uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE); } -static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { PointerRNA imfptr = RNA_pointer_get(ptr, "format"); PointerRNA active_input_ptr, op_ptr; @@ -1787,7 +1735,7 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C } } -static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +static void node_composit_buts_colorbalance_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE); @@ -1841,7 +1789,7 @@ static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerR uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL); } -static void node_composit_buts_movieclip_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_composit_buts_movieclip_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; PointerRNA clipptr; @@ -1945,7 +1893,7 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSE uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE); } -static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +static void node_composit_buts_colorcorrection_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *row; @@ -2147,7 +2095,7 @@ static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), Poi uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); } -static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; @@ -2295,222 +2243,221 @@ static void node_composit_set_butfunc(bNodeType *ntype) { switch (ntype->type) { case CMP_NODE_IMAGE: - ntype->uifunc = node_composit_buts_image; - ntype->uifuncbut = node_composit_buts_image_details; + ntype->draw_buttons = node_composit_buts_image; + ntype->draw_buttons_ex = node_composit_buts_image_ex; break; case CMP_NODE_R_LAYERS: - ntype->uifunc = node_composit_buts_renderlayers; + ntype->draw_buttons = node_composit_buts_renderlayers; break; case CMP_NODE_NORMAL: - ntype->uifunc = node_buts_normal; + ntype->draw_buttons = node_buts_normal; break; case CMP_NODE_CURVE_VEC: - ntype->uifunc = node_buts_curvevec; + ntype->draw_buttons = node_buts_curvevec; break; case CMP_NODE_CURVE_RGB: - ntype->uifunc = node_buts_curvecol; + ntype->draw_buttons = node_buts_curvecol; break; case CMP_NODE_VALUE: - ntype->uifunc = node_buts_value; + ntype->draw_buttons = node_buts_value; break; case CMP_NODE_RGB: - ntype->uifunc = node_buts_rgb; + ntype->draw_buttons = node_buts_rgb; break; case CMP_NODE_FLIP: - ntype->uifunc = node_composit_buts_flip; + ntype->draw_buttons = node_composit_buts_flip; break; case CMP_NODE_SPLITVIEWER: - ntype->uifunc = node_composit_buts_splitviewer; + ntype->draw_buttons = node_composit_buts_splitviewer; break; case CMP_NODE_MIX_RGB: - ntype->uifunc = node_buts_mix_rgb; + ntype->draw_buttons = node_buts_mix_rgb; break; case CMP_NODE_VALTORGB: - ntype->uifunc = node_buts_colorramp; + ntype->draw_buttons = node_buts_colorramp; break; case CMP_NODE_CROP: - ntype->uifunc = node_composit_buts_crop; + ntype->draw_buttons = node_composit_buts_crop; break; case CMP_NODE_BLUR: - ntype->uifunc = node_composit_buts_blur; + ntype->draw_buttons = node_composit_buts_blur; break; case CMP_NODE_DBLUR: - ntype->uifunc = node_composit_buts_dblur; + ntype->draw_buttons = node_composit_buts_dblur; break; case CMP_NODE_BILATERALBLUR: - ntype->uifunc = node_composit_buts_bilateralblur; + ntype->draw_buttons = node_composit_buts_bilateralblur; break; case CMP_NODE_DEFOCUS: - ntype->uifunc = node_composit_buts_defocus; + ntype->draw_buttons = node_composit_buts_defocus; break; case CMP_NODE_GLARE: - ntype->uifunc = node_composit_buts_glare; + ntype->draw_buttons = node_composit_buts_glare; break; case CMP_NODE_TONEMAP: - ntype->uifunc = node_composit_buts_tonemap; + ntype->draw_buttons = node_composit_buts_tonemap; break; case CMP_NODE_LENSDIST: - ntype->uifunc = node_composit_buts_lensdist; + ntype->draw_buttons = node_composit_buts_lensdist; break; case CMP_NODE_VECBLUR: - ntype->uifunc = node_composit_buts_vecblur; + ntype->draw_buttons = node_composit_buts_vecblur; break; case CMP_NODE_FILTER: - ntype->uifunc = node_composit_buts_filter; + ntype->draw_buttons = node_composit_buts_filter; break; case CMP_NODE_MAP_VALUE: - ntype->uifunc = node_composit_buts_map_value; + ntype->draw_buttons = node_composit_buts_map_value; break; case CMP_NODE_MAP_RANGE: - ntype->uifunc = node_composit_buts_map_range; + ntype->draw_buttons = node_composit_buts_map_range; break; case CMP_NODE_TIME: - ntype->uifunc = node_buts_time; + ntype->draw_buttons = node_buts_time; break; case CMP_NODE_ALPHAOVER: - ntype->uifunc = node_composit_buts_alphaover; + ntype->draw_buttons = node_composit_buts_alphaover; break; case CMP_NODE_HUE_SAT: - ntype->uifunc = node_composit_buts_hue_sat; + ntype->draw_buttons = node_composit_buts_hue_sat; break; case CMP_NODE_TEXTURE: - ntype->uifunc = node_buts_texture; + ntype->draw_buttons = node_buts_texture; break; case CMP_NODE_DILATEERODE: - ntype->uifunc = node_composit_buts_dilateerode; + ntype->draw_buttons = node_composit_buts_dilateerode; break; case CMP_NODE_INPAINT: - ntype->uifunc = node_composit_buts_inpaint; + ntype->draw_buttons = node_composit_buts_inpaint; break; case CMP_NODE_DESPECKLE: - ntype->uifunc = node_composit_buts_despeckle; + ntype->draw_buttons = node_composit_buts_despeckle; break; case CMP_NODE_OUTPUT_FILE: - ntype->uifunc = node_composit_buts_file_output; - ntype->uifuncbut = node_composit_buts_file_output_details; - ntype->drawinputfunc = node_draw_input_file_output; + ntype->draw_buttons = node_composit_buts_file_output; + ntype->draw_buttons_ex = node_composit_buts_file_output_ex; break; case CMP_NODE_DIFF_MATTE: - ntype->uifunc = node_composit_buts_diff_matte; + ntype->draw_buttons = node_composit_buts_diff_matte; break; case CMP_NODE_DIST_MATTE: - ntype->uifunc = node_composit_buts_distance_matte; + ntype->draw_buttons = node_composit_buts_distance_matte; break; case CMP_NODE_COLOR_SPILL: - ntype->uifunc = node_composit_buts_color_spill; + ntype->draw_buttons = node_composit_buts_color_spill; break; case CMP_NODE_CHROMA_MATTE: - ntype->uifunc = node_composit_buts_chroma_matte; + ntype->draw_buttons = node_composit_buts_chroma_matte; break; case CMP_NODE_COLOR_MATTE: - ntype->uifunc = node_composit_buts_color_matte; + ntype->draw_buttons = node_composit_buts_color_matte; break; case CMP_NODE_SCALE: - ntype->uifunc = node_composit_buts_scale; + ntype->draw_buttons = node_composit_buts_scale; break; case CMP_NODE_ROTATE: - ntype->uifunc = node_composit_buts_rotate; + ntype->draw_buttons = node_composit_buts_rotate; break; case CMP_NODE_CHANNEL_MATTE: - ntype->uifunc = node_composit_buts_channel_matte; + ntype->draw_buttons = node_composit_buts_channel_matte; break; case CMP_NODE_LUMA_MATTE: - ntype->uifunc = node_composit_buts_luma_matte; + ntype->draw_buttons = node_composit_buts_luma_matte; break; case CMP_NODE_MAP_UV: - ntype->uifunc = node_composit_buts_map_uv; + ntype->draw_buttons = node_composit_buts_map_uv; break; case CMP_NODE_ID_MASK: - ntype->uifunc = node_composit_buts_id_mask; + ntype->draw_buttons = node_composit_buts_id_mask; break; case CMP_NODE_DOUBLEEDGEMASK: - ntype->uifunc = node_composit_buts_double_edge_mask; + ntype->draw_buttons = node_composit_buts_double_edge_mask; break; case CMP_NODE_MATH: - ntype->uifunc = node_buts_math; + ntype->draw_buttons = node_buts_math; break; case CMP_NODE_INVERT: - ntype->uifunc = node_composit_buts_invert; + ntype->draw_buttons = node_composit_buts_invert; break; case CMP_NODE_PREMULKEY: - ntype->uifunc = node_composit_buts_premulkey; + ntype->draw_buttons = node_composit_buts_premulkey; break; case CMP_NODE_VIEW_LEVELS: - ntype->uifunc = node_composit_buts_view_levels; + ntype->draw_buttons = node_composit_buts_view_levels; break; case CMP_NODE_COLORBALANCE: - ntype->uifunc = node_composit_buts_colorbalance; - ntype->uifuncbut = node_composit_buts_colorbalance_but; + ntype->draw_buttons = node_composit_buts_colorbalance; + ntype->draw_buttons_ex = node_composit_buts_colorbalance_ex; break; case CMP_NODE_HUECORRECT: - ntype->uifunc = node_composit_buts_huecorrect; + ntype->draw_buttons = node_composit_buts_huecorrect; break; case CMP_NODE_ZCOMBINE: - ntype->uifunc = node_composit_buts_zcombine; + ntype->draw_buttons = node_composit_buts_zcombine; break; case CMP_NODE_COMBYCCA: case CMP_NODE_SEPYCCA: - ntype->uifunc = node_composit_buts_ycc; + ntype->draw_buttons = node_composit_buts_ycc; break; case CMP_NODE_MOVIECLIP: - ntype->uifunc = node_composit_buts_movieclip; - ntype->uifuncbut = node_composit_buts_movieclip_details; + ntype->draw_buttons = node_composit_buts_movieclip; + ntype->draw_buttons_ex = node_composit_buts_movieclip_ex; break; case CMP_NODE_STABILIZE2D: - ntype->uifunc = node_composit_buts_stabilize2d; + ntype->draw_buttons = node_composit_buts_stabilize2d; break; case CMP_NODE_TRANSFORM: - ntype->uifunc = node_composit_buts_transform; + ntype->draw_buttons = node_composit_buts_transform; break; case CMP_NODE_TRANSLATE: - ntype->uifunc = node_composit_buts_translate; + ntype->draw_buttons = node_composit_buts_translate; break; case CMP_NODE_MOVIEDISTORTION: - ntype->uifunc = node_composit_buts_moviedistortion; + ntype->draw_buttons = node_composit_buts_moviedistortion; break; case CMP_NODE_COLORCORRECTION: - ntype->uifunc = node_composit_buts_colorcorrection; - ntype->uifuncbut = node_composit_buts_colorcorrection_but; + ntype->draw_buttons = node_composit_buts_colorcorrection; + ntype->draw_buttons_ex = node_composit_buts_colorcorrection_ex; break; case CMP_NODE_SWITCH: - ntype->uifunc = node_composit_buts_switch; + ntype->draw_buttons = node_composit_buts_switch; break; case CMP_NODE_MASK_BOX: - ntype->uifunc = node_composit_buts_boxmask; - ntype->uibackdropfunc = node_composit_backdrop_boxmask; + ntype->draw_buttons = node_composit_buts_boxmask; + ntype->draw_backdrop = node_composit_backdrop_boxmask; break; case CMP_NODE_MASK_ELLIPSE: - ntype->uifunc = node_composit_buts_ellipsemask; - ntype->uibackdropfunc = node_composit_backdrop_ellipsemask; + ntype->draw_buttons = node_composit_buts_ellipsemask; + ntype->draw_backdrop = node_composit_backdrop_ellipsemask; break; case CMP_NODE_BOKEHIMAGE: - ntype->uifunc = node_composit_buts_bokehimage; + ntype->draw_buttons = node_composit_buts_bokehimage; break; case CMP_NODE_BOKEHBLUR: - ntype->uifunc = node_composit_buts_bokehblur; + ntype->draw_buttons = node_composit_buts_bokehblur; break; case CMP_NODE_VIEWER: - ntype->uifunc = node_composit_buts_viewer; - ntype->uifuncbut = node_composit_buts_viewer_but; - ntype->uibackdropfunc = node_composit_backdrop_viewer; + ntype->draw_buttons = node_composit_buts_viewer; + ntype->draw_buttons_ex = node_composit_buts_viewer_ex; + ntype->draw_backdrop = node_composit_backdrop_viewer; break; case CMP_NODE_COMPOSITE: - ntype->uifunc = node_composit_buts_composite; + ntype->draw_buttons = node_composit_buts_composite; break; case CMP_NODE_MASK: - ntype->uifunc = node_composit_buts_mask; + ntype->draw_buttons = node_composit_buts_mask; break; case CMP_NODE_KEYINGSCREEN: - ntype->uifunc = node_composit_buts_keyingscreen; + ntype->draw_buttons = node_composit_buts_keyingscreen; break; case CMP_NODE_KEYING: - ntype->uifunc = node_composit_buts_keying; + ntype->draw_buttons = node_composit_buts_keying; break; case CMP_NODE_TRACKPOS: - ntype->uifunc = node_composit_buts_trackpos; + ntype->draw_buttons = node_composit_buts_trackpos; break; case CMP_NODE_PLANETRACKDEFORM: - ntype->uifunc = node_composit_buts_planetrackdeform; + ntype->draw_buttons = node_composit_buts_planetrackdeform; break; } } @@ -2615,7 +2562,7 @@ static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *p uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL); } -static void node_texture_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr) +static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { bNode *node = ptr->data; PointerRNA iuserptr; @@ -2633,46 +2580,46 @@ static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), Poin static void node_texture_set_butfunc(bNodeType *ntype) { if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) { - ntype->uifunc = node_texture_buts_proc; + ntype->draw_buttons = node_texture_buts_proc; } else { switch (ntype->type) { case TEX_NODE_MATH: - ntype->uifunc = node_buts_math; + ntype->draw_buttons = node_buts_math; break; case TEX_NODE_MIX_RGB: - ntype->uifunc = node_buts_mix_rgb; + ntype->draw_buttons = node_buts_mix_rgb; break; case TEX_NODE_VALTORGB: - ntype->uifunc = node_buts_colorramp; + ntype->draw_buttons = node_buts_colorramp; break; case TEX_NODE_CURVE_RGB: - ntype->uifunc = node_buts_curvecol; + ntype->draw_buttons = node_buts_curvecol; break; case TEX_NODE_CURVE_TIME: - ntype->uifunc = node_buts_time; + ntype->draw_buttons = node_buts_time; break; case TEX_NODE_TEXTURE: - ntype->uifunc = node_buts_texture; + ntype->draw_buttons = node_buts_texture; break; case TEX_NODE_BRICKS: - ntype->uifunc = node_texture_buts_bricks; + ntype->draw_buttons = node_texture_buts_bricks; break; case TEX_NODE_IMAGE: - ntype->uifunc = node_texture_buts_image; - ntype->uifuncbut = node_texture_buts_image_details; + ntype->draw_buttons = node_texture_buts_image; + ntype->draw_buttons_ex = node_texture_buts_image_ex; break; case TEX_NODE_OUTPUT: - ntype->uifunc = node_texture_buts_output; + ntype->draw_buttons = node_texture_buts_output; break; } } @@ -2746,14 +2693,12 @@ void ED_node_init_butfuncs(void) extern bNodeSocketType NodeSocketTypeUndefined; /* default ui functions */ - NodeTypeUndefined.drawfunc = node_draw_default; - NodeTypeUndefined.drawupdatefunc = node_update_default; + NodeTypeUndefined.draw_nodetype = node_draw_default; + NodeTypeUndefined.draw_nodetype_prepare = node_update_default; NodeTypeUndefined.select_area_func = node_select_area_default; NodeTypeUndefined.tweak_area_func = node_tweak_area_default; - NodeTypeUndefined.uifunc = NULL; - NodeTypeUndefined.uifuncbut = NULL; - NodeTypeUndefined.drawinputfunc = node_draw_input_default; - NodeTypeUndefined.drawoutputfunc = node_draw_output_default; + NodeTypeUndefined.draw_buttons = NULL; + NodeTypeUndefined.draw_buttons_ex = NULL; NodeTypeUndefined.resize_area_func = node_resize_area_default; NodeSocketTypeUndefined.draw = node_socket_undefined_draw; @@ -2764,14 +2709,12 @@ void ED_node_init_butfuncs(void) /* node type ui functions */ NODE_TYPES_BEGIN(ntype) /* default ui functions */ - ntype->drawfunc = node_draw_default; - ntype->drawupdatefunc = node_update_default; + ntype->draw_nodetype = node_draw_default; + ntype->draw_nodetype_prepare = node_update_default; ntype->select_area_func = node_select_area_default; ntype->tweak_area_func = node_tweak_area_default; - ntype->uifunc = NULL; - ntype->uifuncbut = NULL; - ntype->drawinputfunc = node_draw_input_default; - ntype->drawoutputfunc = node_draw_output_default; + ntype->draw_buttons = NULL; + ntype->draw_buttons_ex = NULL; ntype->resize_area_func = node_resize_area_default; node_common_set_butfunc(ntype); @@ -2793,10 +2736,8 @@ void ED_node_init_butfuncs(void) void ED_init_custom_node_type(bNodeType *ntype) { /* default ui functions */ - ntype->drawfunc = node_draw_default; - ntype->drawupdatefunc = node_update_default; - ntype->drawinputfunc = node_draw_input_default; - ntype->drawoutputfunc = node_draw_output_default; + ntype->draw_nodetype = node_draw_default; + ntype->draw_nodetype_prepare = node_update_default; ntype->resize_area_func = node_resize_area_default; ntype->select_area_func = node_select_area_default; ntype->tweak_area_func = node_tweak_area_default; @@ -2834,13 +2775,60 @@ static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA copy_v4_v4(r_color, std_node_socket_colors[type]); } +/* draw function for file output node sockets, displays only sub-path and format, no value button */ +static void node_file_output_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr) +{ + bNodeTree *ntree = ptr->id.data; + bNodeSocket *sock = ptr->data; + uiLayout *row; + PointerRNA inputptr, imfptr; + int imtype; + + row = uiLayoutRow(layout, FALSE); + + imfptr = RNA_pointer_get(node_ptr, "format"); + imtype = RNA_enum_get(&imfptr, "file_format"); + if (imtype == R_IMF_IMTYPE_MULTILAYER) { + NodeImageMultiFileSocket *input = sock->storage; + RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr); + + uiItemL(row, input->layer, ICON_NONE); + } + else { + NodeImageMultiFileSocket *input = sock->storage; + PropertyRNA *imtype_prop; + const char *imtype_name; + uiBlock *block; + RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr); + + uiItemL(row, input->path, ICON_NONE); + + if (!RNA_boolean_get(&inputptr, "use_node_format")) + imfptr = RNA_pointer_get(&inputptr, "format"); + + imtype_prop = RNA_struct_find_property(&imfptr, "file_format"); + RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop, + RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name); + block = uiLayoutGetBlock(row); + uiBlockSetEmboss(block, UI_EMBOSSP); + uiItemL(row, imtype_name, ICON_NONE); + uiBlockSetEmboss(block, UI_EMBOSSN); + } +} + static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, const char *text) { + bNode *node = node_ptr->data; bNodeSocket *sock = ptr->data; int type = sock->typeinfo->type; /*int subtype = sock->typeinfo->subtype;*/ - if ((sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) { + /* XXX not nice, eventually give this node its own socket type ... */ + if (node->type == CMP_NODE_OUTPUT_FILE) { + node_file_output_socket_draw(C, layout, ptr, node_ptr); + } + + if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IN_USE) || (sock->flag & SOCK_HIDE_VALUE)) { node_socket_button_label(C, layout, ptr, node_ptr, text); return; } @@ -3053,8 +3041,8 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b rctf *viewer_border = &snode->nodetree->viewer_border; while (node) { if (node->flag & NODE_SELECT) { - if (node->typeinfo->uibackdropfunc) { - node->typeinfo->uibackdropfunc(snode, ibuf, node, x, y); + if (node->typeinfo->draw_backdrop) { + node->typeinfo->draw_backdrop(snode, ibuf, node, x, y); } } node = node->next; diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 29f796aecb1..65eb75f8523 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -351,7 +351,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) row = uiLayoutRow(layout, 1); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); - node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr); + nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name)); uiBlockEndAlign(node->block); uiBlockLayoutResolve(node->block, NULL, &buty); @@ -402,7 +402,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) } /* buttons rect? */ - if (node->typeinfo->uifunc && (node->flag & NODE_OPTIONS)) { + if (node->typeinfo->draw_buttons && (node->flag & NODE_OPTIONS)) { dy -= NODE_DYS / 2; /* set this for uifunc() that don't use layout engine yet */ @@ -416,7 +416,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle()); uiLayoutSetContextPointer(layout, "node", &nodeptr); - node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr); + node->typeinfo->draw_buttons(layout, (bContext *)C, &nodeptr); uiBlockEndAlign(node->block); uiBlockLayoutResolve(node->block, NULL, &buty); @@ -437,7 +437,9 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) uiLayoutSetContextPointer(layout, "node", &nodeptr); uiLayoutSetContextPointer(layout, "socket", &sockptr); - node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr); + row = uiLayoutRow(layout, 1); + + nsock->typeinfo->draw((bContext *)C, row, &sockptr, &nodeptr, IFACE_(nsock->name)); uiBlockEndAlign(node->block); uiBlockLayoutResolve(node->block, NULL, &buty); @@ -1115,8 +1117,8 @@ void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTr static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) { - if (node->typeinfo->drawupdatefunc) - node->typeinfo->drawupdatefunc(C, ntree, node); + if (node->typeinfo->draw_nodetype_prepare) + node->typeinfo->draw_nodetype_prepare(C, ntree, node); } void node_update_nodetree(const bContext *C, bNodeTree *ntree) @@ -1131,8 +1133,8 @@ void node_update_nodetree(const bContext *C, bNodeTree *ntree) static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) { - if (node->typeinfo->drawfunc) - node->typeinfo->drawfunc(C, ar, snode, ntree, node, key); + if (node->typeinfo->draw_nodetype) + node->typeinfo->draw_nodetype(C, ar, snode, ntree, node, key); } #define USE_DRAW_TOT_UPDATE @@ -1241,7 +1243,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar) /* shade node groups to separate them visually */ UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70); glEnable(GL_BLEND); - uiSetRoundBox(0); + uiSetRoundBox(UI_CNR_NONE); uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0); glDisable(GL_BLEND); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index ff6a8e884a6..1d93fe65c09 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1419,7 +1419,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) continue; - if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->uifunc || node->typeinfo->uifuncbut)) + if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) continue; if (node->flag & toggle_flag) @@ -1433,7 +1433,7 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag) if (toggle_flag == NODE_PREVIEW && (node->typeinfo->flag & NODE_PREVIEW) == 0) continue; - if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->uifunc || node->typeinfo->uifuncbut)) + if (toggle_flag == NODE_OPTIONS && !(node->typeinfo->draw_buttons || node->typeinfo->draw_buttons_ex)) continue; if ((tot_eq && tot_neq) || tot_eq == 0) @@ -1731,7 +1731,7 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op) node = nodeGetActive(snode->edittree); } - if (!node) + if (!node || node->type != CMP_NODE_OUTPUT_FILE) return OPERATOR_CANCELLED; RNA_string_get(op->ptr, "file_path", file_path); @@ -1777,7 +1777,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U node = nodeGetActive(snode->edittree); } - if (!node) + if (!node || node->type != CMP_NODE_OUTPUT_FILE) return OPERATOR_CANCELLED; if (!ntreeCompositOutputFileRemoveActiveSocket(ntree, node)) @@ -1819,7 +1819,7 @@ static int node_output_file_move_active_socket_exec(bContext *C, wmOperator *op) else if (snode && snode->edittree) node = nodeGetActive(snode->edittree); - if (!node) + if (!node || node->type != CMP_NODE_OUTPUT_FILE) return OPERATOR_CANCELLED; nimf = node->storage; diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 83c11e69d84..a67a8791a64 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -207,7 +207,7 @@ static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode * break; if (node_from) - if (node_from->inputs.first || node_from->typeinfo->uifunc || node_from->typeinfo->uifuncbut) + if (node_from->inputs.first || node_from->typeinfo->draw_buttons || node_from->typeinfo->draw_buttons_ex) node_from = NULL; if (node_prev && node_prev->type == type && node_link_item_compare(node_prev, item)) { @@ -586,13 +586,13 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); - if (node->typeinfo->uifunc) { + if (node->typeinfo->draw_buttons) { if (node->type != NODE_GROUP) { split = uiLayoutSplit(layout, 0.35f, FALSE); col = uiLayoutColumn(split, FALSE); col = uiLayoutColumn(split, FALSE); - node->typeinfo->uifunc(col, C, &nodeptr); + node->typeinfo->draw_buttons(col, C, &nodeptr); } } @@ -639,7 +639,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, if (depth > 0) { uiBlockSetEmboss(block, UI_EMBOSSN); - if (lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) { + if (lnode && (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) { int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : ICON_DISCLOSURE_TRI_DOWN; uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); } diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index e4a9c4fa5db..f889a8ec97b 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -373,7 +373,7 @@ void NODE_OT_backimage_fit(wmOperatorType *ot) /* identifiers */ ot->name = "Background Image Fit"; ot->idname = "NODE_OT_backimage_fit"; - ot->description = "Zoom in/out the background image"; + ot->description = "Fit the background image to the view"; /* api callbacks */ ot->exec = backimage_fit_exec; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index b86fba1398a..10890a305fb 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -384,17 +384,21 @@ static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, for (srl = sce->r.layers.first; srl; srl = srl->next) { for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { - lineset->linestyle->id.flag |= LIB_DOIT; + FreestyleLineStyle *linestyle = lineset->linestyle; + if (linestyle) { + linestyle->id.flag |= LIB_DOIT; + } } } for (srl = sce->r.layers.first; srl; srl = srl->next) { for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { FreestyleLineStyle *linestyle = lineset->linestyle; - - if (!(linestyle->id.flag & LIB_DOIT)) - continue; - linestyle->id.flag &= ~LIB_DOIT; - outliner_add_element(soops, lb, linestyle, te, 0, 0); + if (linestyle) { + if (!(linestyle->id.flag & LIB_DOIT)) + continue; + linestyle->id.flag &= ~LIB_DOIT; + outliner_add_element(soops, lb, linestyle, te, 0, 0); + } } } } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index dca1b481334..cb69a7fe654 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1251,7 +1251,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq height = (scene->r.size * scene->r.ysch) / 100; ED_mask_draw_region(mask, ar, - 0, 0, /* TODO */ + 0, 0, 0, /* TODO */ width, height, aspx, aspy, FALSE, TRUE, diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index d8b4824b528..8b2e7067eb9 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2960,7 +2960,7 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot) /* identifiers */ ot->name = "Border Offset View"; ot->idname = "SEQUENCER_OT_view_ghost_border"; - ot->description = "Enable border select mode"; + ot->description = "Set the boundaries of the border used for offset-view"; /* api callbacks */ ot->invoke = WM_border_select_invoke; diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index 51df21e509a..c8fd6e4b6ea 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -99,7 +99,7 @@ void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot) /* identifiers */ ot->name = "Add Strip Modifier"; ot->idname = "SEQUENCER_OT_strip_modifier_add"; - ot->description = "Add a modifier to strip"; + ot->description = "Add a modifier to the strip"; /* api callbacks */ ot->exec = strip_modifier_add_exec; @@ -142,7 +142,7 @@ void SEQUENCER_OT_strip_modifier_remove(wmOperatorType *ot) /* identifiers */ ot->name = "Remove Strip Modifier"; ot->idname = "SEQUENCER_OT_strip_modifier_remove"; - ot->description = "Add a modifier to strip"; + ot->description = "Remove a modifier from the strip"; /* api callbacks */ ot->exec = strip_modifier_remove_exec; diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 254d15341cd..45f05d56076 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -892,7 +892,7 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot) /* identifiers */ ot->name = "Border Select"; ot->idname = "SEQUENCER_OT_select_border"; - ot->description = "Enable border select mode"; + ot->description = "Select strips using border selection"; /* api callbacks */ ot->invoke = WM_border_select_invoke; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 18733d4e409..deb37f8d943 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -220,7 +220,8 @@ static int sample_cancel(bContext *C, wmOperator *op) static int sample_poll(bContext *C) { - return BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL; + SpaceSeq *sseq = CTX_wm_space_seq(C); + return sseq && BKE_sequencer_editing_get(CTX_data_scene(C), FALSE) != NULL; } void SEQUENCER_OT_sample(wmOperatorType *ot) diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index c5e7a47b7a2..c668c8063a8 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -309,7 +309,7 @@ static void text_keymap(struct wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "selection", TRUE); } - WM_keymap_add_item(keymap, "TEXT_OT_properties", PKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "TEXT_OT_properties", TKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index ba61399f6d5..eaba537c0a8 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -361,6 +361,7 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e } break; case RETKEY: + case PADENTER: if (event->val == KM_PRESS) { if (tools & TOOL_SUGG_LIST) { confirm_suggestion(st->text); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2c2a8b255da..c078e612d68 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -1943,7 +1943,7 @@ void TEXT_OT_move_select(wmOperatorType *ot) /* identifiers */ ot->name = "Move Select"; ot->idname = "TEXT_OT_move_select"; - ot->description = "Make selection from current cursor position to new cursor position type"; + ot->description = "Move the cursor while selecting"; /* api callbacks */ ot->exec = text_move_select_exec; @@ -2291,7 +2291,7 @@ void TEXT_OT_scroll(wmOperatorType *ot) * scroll_bar. Both do basically the same thing (aside * from keymaps).*/ ot->idname = "TEXT_OT_scroll"; - ot->description = "Scroll text screen"; + ot->description = ""; /* api callbacks */ ot->exec = text_scroll_exec; @@ -2301,7 +2301,7 @@ void TEXT_OT_scroll(wmOperatorType *ot) ot->poll = text_scroll_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL; /* properties */ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); @@ -2385,7 +2385,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot) * scroll. Both do basically the same thing (aside * from keymaps).*/ ot->idname = "TEXT_OT_scroll_bar"; - ot->description = "Scroll text screen"; + ot->description = ""; /* api callbacks */ ot->invoke = text_scroll_bar_invoke; @@ -2394,7 +2394,7 @@ void TEXT_OT_scroll_bar(wmOperatorType *ot) ot->poll = text_region_scroll_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING; + ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL; /* properties */ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index 2634dd3ec08..de6fafb2cd8 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -304,7 +304,7 @@ static void set_ebone_glColor(const unsigned int boneflag) /* *************** Armature drawing, helper calls for parts ******************* */ /* half the cube, in Y */ -static float cube[8][3] = { +static const float cube[8][3] = { {-1.0, 0.0, -1.0}, {-1.0, 0.0, 1.0}, {-1.0, 1.0, 1.0}, @@ -440,7 +440,7 @@ static void draw_bonevert_solid(void) glCallList(displist); } -static float bone_octahedral_verts[6][3] = { +static const float bone_octahedral_verts[6][3] = { { 0.0f, 0.0f, 0.0f}, { 0.1f, 0.1f, 0.1f}, { 0.1f, 0.1f, -0.1f}, @@ -449,10 +449,10 @@ static float bone_octahedral_verts[6][3] = { { 0.0f, 1.0f, 0.0f} }; -static unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2}; -static unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1}; +static const unsigned int bone_octahedral_wire_sides[8] = {0, 1, 5, 3, 0, 4, 5, 2}; +static const unsigned int bone_octahedral_wire_square[8] = {1, 2, 3, 4, 1}; -static unsigned int bone_octahedral_solid_tris[8][3] = { +static const unsigned int bone_octahedral_solid_tris[8][3] = { {2, 1, 0}, /* bottom */ {3, 2, 0}, {4, 3, 0}, @@ -465,7 +465,7 @@ static unsigned int bone_octahedral_solid_tris[8][3] = { }; /* aligned with bone_octahedral_solid_tris */ -static float bone_octahedral_solid_normals[8][3] = { +static const float bone_octahedral_solid_normals[8][3] = { { 0.70710683f, -0.70710683f, 0.00000000f}, {-0.00000000f, -0.70710683f, -0.70710683f}, {-0.70710683f, -0.70710683f, 0.00000000f}, @@ -599,7 +599,7 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag, } /* 16 values of sin function (still same result!) */ -static float si[16] = { +static const float si[16] = { 0.00000000f, 0.20129852f, 0.39435585f, 0.57126821f, 0.72479278f, @@ -611,7 +611,7 @@ static float si[16] = { 0.10116832f }; /* 16 values of cos function (still same result!) */ -static float co[16] = { +static const float co[16] = { 1.00000000f, 0.97952994f, 0.91895781f, 0.82076344f, 0.68896691f, diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 82bc0dfb00d..1ea1dcfb33d 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2043,7 +2043,7 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { if (!data->uniform_scale) { - mul_v3_m3v3(n, data->tmat, (float *) no); + mul_v3_m3v3(n, data->tmat, no); normalize_v3(n); mul_m3_v3(data->imat, n); } @@ -2108,7 +2108,7 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float } if (!data->uniform_scale) { - mul_v3_m3v3(n, data->tmat, (float *) no); + mul_v3_m3v3(n, data->tmat, no); normalize_v3(n); mul_m3_v3(data->imat, n); } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 6c61c2af816..58c0df6b6bd 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -44,6 +44,7 @@ #include "BKE_context.h" #include "BKE_icons.h" +#include "BKE_main.h" #include "BKE_object.h" #include "BKE_screen.h" @@ -258,6 +259,25 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d) } #endif +void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa) +{ + wmWindowManager *wm = bmain->wm.first; + + if (v3d->drawtype != OB_RENDER) { + ARegion *ar; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + RegionView3D *rv3d = ar->regiondata; + + if (rv3d && rv3d->render_engine) { + WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW); + RE_engine_free(rv3d->render_engine); + rv3d->render_engine = NULL; + } + } + } +} + /* ******************** default callbacks for view3d space ***************** */ static SpaceLink *view3d_new(const bContext *C) diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 75e7605df6b..eea084b4750 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -682,7 +682,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } } BKE_nurb_test2D(nu); - BKE_nurb_handles_test(nu); /* test for bezier too */ + BKE_nurb_handles_test(nu, true); /* test for bezier too */ nu = nu->next; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e808869abc7..e8e4e75472f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -113,9 +113,9 @@ static void star_stuff_init_func(void) glPointSize(1.0); glBegin(GL_POINTS); } -static void star_stuff_vertex_func(float *i) +static void star_stuff_vertex_func(const float vec[3]) { - glVertex3fv(i); + glVertex3fv(vec); } static void star_stuff_term_func(void) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 005bb5940bc..67c9ea4599c 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1257,7 +1257,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) { /* identifiers */ ot->name = "NDOF Orbit View"; - ot->description = "Explore every angle of an object using the 3D mouse"; + ot->description = "Orbit the view using the 3D mouse"; ot->idname = "VIEW3D_OT_ndof_orbit"; /* api callbacks */ @@ -1355,7 +1355,7 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot) { /* identifiers */ ot->name = "NDOF Orbit View with Zoom"; - ot->description = "Explore every angle of an object using the 3D mouse"; + ot->description = "Orbit and zoom the view using the 3D mouse"; ot->idname = "VIEW3D_OT_ndof_orbit_zoom"; /* api callbacks */ @@ -1452,7 +1452,7 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) { /* identifiers */ ot->name = "NDOF Pan View"; - ot->description = "Position your viewpoint with the 3D mouse"; + ot->description = "Pan the view with the 3D mouse"; ot->idname = "VIEW3D_OT_ndof_pan"; /* api callbacks */ @@ -1543,7 +1543,7 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) { /* identifiers */ ot->name = "NDOF Move View"; - ot->description = "Position your viewpoint with the 3D mouse"; + ot->description = "Pan and rotate the view with the 3D mouse"; ot->idname = "VIEW3D_OT_ndof_all"; /* api callbacks */ diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index c812f1084e2..c48ce8a2343 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -160,7 +160,7 @@ static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const bool selec { BMEdge *eed; BMIter iter; - int index = bm_solidoffs; + unsigned int index = bm_solidoffs; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { @@ -288,12 +288,12 @@ static int view3d_selectable_data(bContext *C) /* helper also for borderselect */ -static int edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) +static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) { return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2); } -static int edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) +static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) { int d1, d2, d3, d4; @@ -725,7 +725,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh { const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); Object *ob = vc->obact; - Mesh *me = ob ? ob->data : NULL; + Mesh *me = ob->data; rcti rect; if (me == NULL || me->totvert == 0) @@ -764,7 +764,7 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { Object *ob = vc->obact; - Mesh *me = ob ? ob->data : NULL; + Mesh *me = ob->data; rcti rect; if (me == NULL || me->totpoly == 0) @@ -2405,13 +2405,13 @@ static void mesh_circle_select(ViewContext *vc, const bool select, const int mva static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { Object *ob = vc->obact; - Mesh *me = ob ? ob->data : NULL; - /* int bbsel; */ /* UNUSED */ + Mesh *me = ob->data; + bool bbsel; - if (me) { - bm_vertoffs = me->totpoly + 1; /* max index array */ + bm_vertoffs = me->totpoly + 1; /* max index array */ - /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + if (bbsel) { edbm_backbuf_check_and_select_tfaces(me, select); EDBM_backbuf_free(); paintface_flush_flags(ob); @@ -2431,15 +2431,17 @@ static void paint_vertsel_circle_select(ViewContext *vc, const bool select, cons const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); Object *ob = vc->obact; Mesh *me = ob->data; - /* int bbsel; */ /* UNUSED */ + bool bbsel; /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ if (use_zbuf) { bm_vertoffs = me->totvert + 1; /* max index array */ - /* bbsel = */ /* UNUSED */ EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - edbm_backbuf_check_and_select_verts_obmode(me, select); - EDBM_backbuf_free(); + bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + if (bbsel) { + edbm_backbuf_check_and_select_verts_obmode(me, select); + EDBM_backbuf_free(); + } } else { CircleSelectUserData data; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 5f988edb950..7c29ab01c24 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -143,7 +143,7 @@ static void special_transvert_update(Object *obedit) } BKE_nurb_test2D(nu); - BKE_nurb_handles_test(nu); /* test for bezier too */ + BKE_nurb_handles_test(nu, true); /* test for bezier too */ nu = nu->next; } } diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 7e39c0b6be0..74d72061995 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -378,12 +378,15 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot) /* identifiers */ ot->name = "Smooth View"; + ot->description = ""; ot->idname = "VIEW3D_OT_smoothview"; - ot->description = "The time to animate the change of view (in milliseconds)"; /* api callbacks */ ot->invoke = view3d_smoothview_invoke; + /* flags */ + ot->flag = OPTYPE_INTERNAL; + ot->poll = ED_operator_view3d_active; } @@ -1177,7 +1180,7 @@ static bool view3d_localview_init(Main *bmain, Scene *scene, ScrArea *sa, Report return ok; } -static void restore_localviewdata(ScrArea *sa, int free) +static void restore_localviewdata(Main *bmain, ScrArea *sa, int free) { ARegion *ar; View3D *v3d = sa->spacedata.first; @@ -1214,12 +1217,7 @@ static void restore_localviewdata(ScrArea *sa, int free) } } - if (v3d->drawtype != OB_RENDER) { - if (rv3d->render_engine) { - RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; - } - } + ED_view3d_shade_update(bmain, v3d, sa); } } } @@ -1234,7 +1232,7 @@ static bool view3d_localview_exit(Main *bmain, Scene *scene, ScrArea *sa) locallay = v3d->lay & 0xFF000000; - restore_localviewdata(sa, 1); /* 1 = free */ + restore_localviewdata(bmain, sa, 1); /* 1 = free */ /* for when in other window the layers have changed */ if (v3d->scenelock) v3d->lay = scene->lay; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 87ef3d6742a..ea039c15be4 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -105,6 +105,8 @@ static int doVertSlide(TransInfo *t, float perc); static void drawEdgeSlide(const struct bContext *C, TransInfo *t); static void drawVertSlide(const struct bContext *C, TransInfo *t); +static void len_v3_ensure(float v[3], const float length); +static void postInputRotation(TransInfo *t, float values[3]); static bool transdata_check_local_center(TransInfo *t) { @@ -1360,7 +1362,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } } -int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int cent2d[2]) +int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2]) { TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); int success; @@ -1390,7 +1392,7 @@ int calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], int c calculateCenter(t); if (cent2d) { - copy_v2_v2_int(cent2d, t->center2d); + copy_v2_v2(cent2d, t->center2d); } if (cent3d) { @@ -2576,58 +2578,67 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* ************************** WARP *************************** */ -static void postInputWarp(TransInfo *t, float values[3]) -{ - mul_v3_fl(values, (float)(M_PI * 2)); +struct WarpCustomData { + float warp_sta[3]; + float warp_end[3]; - if (t->customData) { /* non-null value indicates reversed input */ - negate_v3(values); - } -} + float warp_nor[3]; + float warp_tan[3]; + + /* for applying the mouse distance */ + float warp_init_dist; +}; void initWarp(TransInfo *t) { - float max[3], min[3]; - int i; + const float mval_fl[2] = {UNPACK2(t->mval)}; + const float *curs; + float tvec[3]; + struct WarpCustomData *data; t->mode = TFM_WARP; t->transform = Warp; t->handleEvent = handleEventWarp; - setInputPostFct(&t->mouse, postInputWarp); - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); + setInputPostFct(&t->mouse, postInputRotation); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING); - t->idx_max = 0; - t->num.idx_max = 0; + t->idx_max = 1; + t->num.idx_max = 1; t->snap[0] = 0.0f; - t->snap[1] = 5.0f / 180.0f * (float)M_PI; - t->snap[2] = 1.0f / 180.0f * (float)M_PI; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); t->num.increment = 1.0f; t->flag |= T_NO_CONSTRAINT; - - /* we need min/max in view space */ - for (i = 0; i < t->total; i++) { - float center[3]; - copy_v3_v3(center, t->data[i].center); - mul_m3_v3(t->data[i].mtx, center); - mul_m4_v3(t->viewmat, center); - sub_v3_v3(center, t->viewmat[3]); - if (i) { - minmax_v3v3_v3(min, max, center); - } - else { - copy_v3_v3(max, center); - copy_v3_v3(min, center); - } + + //copy_v3_v3(t->center, give_cursor(t->scene, t->view)); + calculateCenterCursor(t); + + t->val = 0.0f; + + data = MEM_callocN(sizeof(*data), __func__); + + curs = give_cursor(t->scene, t->view); + copy_v3_v3(data->warp_sta, curs); + ED_view3d_win_to_3d(t->ar, curs, mval_fl, data->warp_end); + + copy_v3_v3(data->warp_nor, t->viewinv[2]); + if (t->flag & T_EDIT) { + sub_v3_v3(data->warp_sta, t->obedit->obmat[3]); + sub_v3_v3(data->warp_end, t->obedit->obmat[3]); } + normalize_v3(data->warp_nor); + + /* tangent */ + sub_v3_v3v3(tvec, data->warp_end, data->warp_sta); + cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor); + normalize_v3(data->warp_tan); - mid_v3_v3v3(t->center, min, max); + data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta); - if (max[0] == min[0]) - max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */ - t->val = (max[0] - min[0]) / 2.0f; /* t->val is X dimension projected boundbox */ + t->customData = data; } int handleEventWarp(TransInfo *t, const wmEvent *event) @@ -2635,11 +2646,7 @@ int handleEventWarp(TransInfo *t, const wmEvent *event) int status = 0; if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { - // Use customData pointer to signal warp direction - if (t->customData == NULL) - t->customData = (void *)1; - else - t->customData = NULL; + (void)t; status = 1; } @@ -2650,91 +2657,115 @@ int handleEventWarp(TransInfo *t, const wmEvent *event) int Warp(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; - float vec[3], circumfac, dist, phi0, co, si, cursor[3], gcursor[3]; - const float *curs; + float vec[3]; + float pivot[3]; + float warp_end_radius[3]; int i; char str[MAX_INFO_LEN]; - - curs = give_cursor(t->scene, t->view); - /* - * gcursor is the one used for helpline. - * It has to be in the same space as the drawing loop - * (that means it needs to be in the object's space when in edit mode and - * in global space in object mode) - * - * cursor is used for calculations. - * It needs to be in view space, but we need to take object's offset - * into account if in Edit mode. - */ - copy_v3_v3(cursor, curs); - copy_v3_v3(gcursor, cursor); - if (t->flag & T_EDIT) { - sub_v3_v3(cursor, t->obedit->obmat[3]); - sub_v3_v3(gcursor, t->obedit->obmat[3]); - mul_m3_v3(t->data->smtx, gcursor); - } - mul_m4_v3(t->viewmat, cursor); - sub_v3_v3(cursor, t->viewmat[3]); - + const struct WarpCustomData *data = t->customData; + const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0; + + union { + struct { float angle, scale; }; + float vector[2]; + } values; + /* amount of radians for warp */ - circumfac = t->values[0]; - - snapGrid(t, &circumfac); - applyNumInput(&t->num, &circumfac); + copy_v2_v2(values.vector, t->values); + +#if 0 + snapGrid(t, angle_rad); +#else + /* hrmf, snapping radius is using 'angle' steps, need to convert to something else + * this isnt essential but nicer to give reasonable snapping values for radius */ + if (t->tsnap.mode == SCE_SNAP_MODE_INCREMENT) { + const float radius_snap = 0.1f; + const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap; + values.scale *= snap_hack; + snapGrid(t, values.vector); + values.scale /= snap_hack; + } +#endif /* header print for NumInput */ if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + char c[NUM_STR_REP_LEN * 2]; + applyNumInput(&t->num, values.vector); + outputNumInput(&(t->num), c); - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %s"), c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp Angle: %s Radius: %s Alt, Clamp %s"), + &c[0], &c[NUM_STR_REP_LEN], + WM_bool_as_string(is_clamp)); - circumfac = DEG2RADF(circumfac); + values.angle = DEG2RADF(values.angle); + values.scale = values.scale / data->warp_init_dist; } else { /* default header print */ - BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac)); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp Angle: %.3f Radius: %.4f, Alt, Clamp %s"), + RAD2DEGF(values.angle), values.scale * data->warp_init_dist, + WM_bool_as_string(is_clamp)); } - t->values[0] = circumfac; + copy_v2_v2(t->values, values.vector); - circumfac /= 2; /* only need 180 on each side to make 360 */ + values.angle *= -1.0f; + values.scale *= data->warp_init_dist; + /* calc 'data->warp_end' from 'data->warp_end_init' */ + copy_v3_v3(warp_end_radius, data->warp_end); + dist_ensure_v3_v3fl(warp_end_radius, data->warp_sta, values.scale); + /* done */ + + /* calculate pivot */ + copy_v3_v3(pivot, data->warp_sta); + if (values.angle > 0.0f) { + madd_v3_v3fl(pivot, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle)); + } + else { + madd_v3_v3fl(pivot, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); + } + for (i = 0; i < t->total; i++, td++) { - float loc[3]; + float mat[3][3]; + float delta[3]; + float fac, fac_scaled; + if (td->flag & TD_NOACTION) break; if (td->flag & TD_SKIP) continue; - - /* translate point to center, rotate in such a way that outline==distance */ + + if (UNLIKELY(values.angle == 0.0f)) { + copy_v3_v3(td->loc, td->iloc); + continue; + } + copy_v3_v3(vec, td->iloc); mul_m3_v3(td->mtx, vec); - mul_m4_v3(t->viewmat, vec); - sub_v3_v3(vec, t->viewmat[3]); - - dist = vec[0] - cursor[0]; - - /* t->val is X dimension projected boundbox */ - phi0 = (circumfac * dist / t->val); - - vec[1] = (vec[1] - cursor[1]); - - co = cosf(phi0); - si = sinf(phi0); - loc[0] = -si * vec[1] + cursor[0]; - loc[1] = co * vec[1] + cursor[1]; - loc[2] = vec[2]; - - mul_m4_v3(t->viewinv, loc); - sub_v3_v3(loc, t->viewinv[3]); - mul_m3_v3(td->smtx, loc); - - sub_v3_v3(loc, td->iloc); - mul_v3_fl(loc, td->factor); - add_v3_v3v3(td->loc, td->iloc, loc); + + fac = line_point_factor_v3(vec, data->warp_sta, warp_end_radius); + if (is_clamp) { + CLAMP(fac, 0.0f, 1.0f); + } + + fac_scaled = fac * td->factor; + axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled); + interp_v3_v3v3(delta, data->warp_sta, warp_end_radius, fac_scaled); + sub_v3_v3(delta, data->warp_sta); + + /* delta is subtracted, rotation adds back this offset */ + sub_v3_v3(vec, delta); + + sub_v3_v3(vec, pivot); + mul_m3_v3(mat, vec); + add_v3_v3(vec, pivot); + + mul_m3_v3(td->smtx, vec); + copy_v3_v3(td->loc, vec); } recalcData(t); @@ -3369,8 +3400,8 @@ void initRotation(TransInfo *t) t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; - t->snap[1] = (float)((5.0 / 180) * M_PI); - t->snap[2] = t->snap[1] * 0.2f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); t->num.increment = 1.0f; @@ -3701,8 +3732,8 @@ void initTrackball(TransInfo *t) t->idx_max = 1; t->num.idx_max = 1; t->snap[0] = 0.0f; - t->snap[1] = (float)((5.0 / 180) * M_PI); - t->snap[2] = t->snap[1] * 0.2f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); t->num.increment = 1.0f; @@ -4107,7 +4138,7 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } } BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Even Thickness %s"), - (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); + WM_bool_as_string(t->flag & T_ALT_TRANSFORM)); /* done with header string */ @@ -4149,8 +4180,8 @@ void initTilt(TransInfo *t) t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; - t->snap[1] = (float)((5.0 / 180) * M_PI); - t->snap[2] = t->snap[1] * 0.2f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); t->num.increment = t->snap[1]; @@ -4804,6 +4835,26 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e) return NULL; } +/* interpoaltes along a line made up of 2 segments (used for edge slide) */ +static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float t) +{ + float t_mid, t_delta; + + /* could be pre-calculated */ + t_mid = line_point_factor_v3(v2, v1, v3); + + t_delta = t - t_mid; + if (fabsf(t_delta) < FLT_EPSILON) { + copy_v3_v3(p, v2); + } + else if (t_delta < 0.0f) { + interp_v3_v3v3(p, v1, v2, t / t_mid); + } + else { + interp_v3_v3v3(p, v2, v3, (t - t_mid) / (1.0f - t_mid)); + } +} + static void len_v3_ensure(float v[3], const float length) { normalize_v3(v); @@ -5716,20 +5767,16 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t) /* Non-Prop mode */ if (sld && sld->is_proportional == FALSE) { View3D *v3d = CTX_wm_view3d(C); - float marker[3]; - float v1[3], v2[3]; - float interp_v; + float co_a[3], co_b[3], co_mark[3]; TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float fac = (sld->perc + 1.0f) / 2.0f; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float guide_size = ctrl_size - 0.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; const int alpha_shade = -30; - add_v3_v3v3(v1, curr_sv->v_co_orig, curr_sv->dir_a); - add_v3_v3v3(v2, curr_sv->v_co_orig, curr_sv->dir_b); - - interp_v = (sld->perc + 1.0f) / 2.0f; - interp_v3_v3v3(marker, v2, v1, interp_v); + add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_a); + add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_b); if (v3d && v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -5770,7 +5817,12 @@ static void drawEdgeSlide(const struct bContext *C, TransInfo *t) UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); glPointSize(guide_size); bglBegin(GL_POINTS); - bglVertex3fv(marker); +#if 0 + interp_v3_v3v3(co_mark, co_b, co_a, fac); + bglVertex3fv(co_mark); +#endif + interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); + bglVertex3fv(co_mark); bglEnd(); @@ -5832,10 +5884,10 @@ static int doEdgeSlide(TransInfo *t, float perc) add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_b); if (sld->flipped_vtx) { - interp_v3_v3v3(sv->v->co, co_b, co_a, fac); + interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); } else { - interp_v3_v3v3(sv->v->co, co_a, co_b, fac); + interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac); } } } @@ -5854,9 +5906,6 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) bool flipped = sld->flipped_vtx; bool is_proportional = sld->is_proportional; - const char *on_str = IFACE_("ON"); - const char *off_str = IFACE_("OFF"); - final = t->values[0]; snapGrid(t, &final); @@ -5872,11 +5921,11 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"), - &c[0], !is_proportional ? on_str : off_str, flipped ? on_str : off_str); + &c[0], WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped)); } else { BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"), - final, !is_proportional ? on_str : off_str, flipped ? on_str : off_str); + final, WM_bool_as_string(!is_proportional), WM_bool_as_string(flipped)); } CLAMP(final, -1.0f, 1.0f); @@ -6361,9 +6410,6 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); - const char *on_str = IFACE_("ON"); - const char *off_str = IFACE_("OFF"); - final = t->values[0]; snapGrid(t, &final); @@ -6384,11 +6430,11 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) else { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final); } - ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), !is_proportional ? on_str : off_str); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional)); if (!is_proportional) { - ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), flipped ? on_str : off_str); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); } - ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), is_clamp ? on_str : off_str); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); /* done with header string */ /* do stuff here */ @@ -6414,8 +6460,8 @@ void initBoneRoll(TransInfo *t) t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; - t->snap[1] = (float)((5.0 / 180) * M_PI); - t->snap[2] = t->snap[1] * 0.2f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); t->num.increment = 1.0f; @@ -6720,7 +6766,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char *str) } } ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Expand to fit %s"), - (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); + WM_bool_as_string(t->flag & T_ALT_TRANSFORM)); } static void applySeqSlide(TransInfo *t, const float val[2]) @@ -7217,7 +7263,7 @@ int TimeSlide(TransInfo *t, const int mval[2]) void initTimeScale(TransInfo *t) { - int center[2]; + float center[2]; /* this tool is only really available in the Action Editor * AND NLA Editor (for strip scaling) @@ -7232,7 +7278,7 @@ void initTimeScale(TransInfo *t) /* recalculate center2d to use CFRA and mouse Y, since that's * what is used in time scale */ t->center[0] = t->scene->r.cfra; - projectIntView(t, t->center, center); + projectFloatView(t, t->center, center); center[1] = t->imval[1]; /* force a reinit with the center2d used here */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a4828317604..b32ba5ad527 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -271,7 +271,7 @@ typedef struct MouseInput { int imval[2]; /* initial mouse position */ char precision; int precision_mval[2]; /* mouse position when precision key was pressed */ - int center[2]; + float center[2]; float factor; void *data; /* additional data, if needed by the particular function */ } MouseInput; @@ -300,7 +300,7 @@ typedef struct TransInfo { float prop_size; /* proportional circle radius */ char proptext[20]; /* proportional falloff text */ float center[3]; /* center of transformation */ - int center2d[2]; /* center in screen coordinates */ + float center2d[2]; /* center in screen coordinates */ int imval[2]; /* initial mouse position */ short event_type; /* event->type used to invoke transform */ short idx_max; /* maximum index on the input vector */ @@ -678,6 +678,7 @@ typedef enum { INPUT_SPRING, INPUT_SPRING_FLIP, INPUT_ANGLE, + INPUT_ANGLE_SPRING, INPUT_TRACKBALL, INPUT_HORIZONTAL_RATIO, INPUT_HORIZONTAL_ABSOLUTE, @@ -687,7 +688,7 @@ typedef enum { INPUT_CUSTOM_RATIO_FLIP } MouseInputMode; -void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]); +void initMouseInput(TransInfo *t, MouseInput *mi, const float center[2], const int mval[2]); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index a4299fe688c..f5a12fed076 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -123,6 +123,20 @@ #include "transform.h" #include "bmesh.h" +/** + * Transforming around ourselves is no use, fallback to individual origins, + * useful for curve/armatures. + */ +static void transform_around_single_fallback(TransInfo *t) +{ + if ((t->total == 1) && + (ELEM3(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) && + (ELEM3(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) + { + t->around = V3D_LOCAL; + } +} + /* when transforming islands */ struct TransIslandData { float co[3]; @@ -1084,6 +1098,8 @@ static void createTransArmatureVerts(TransInfo *t) if (!t->total) return; + transform_around_single_fallback(t); + copy_m3_m4(mtx, t->obedit->obmat); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); @@ -1408,6 +1424,8 @@ static void createTransCurveVerts(TransInfo *t) else t->total = countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)"); + transform_around_single_fallback(t); + copy_m3_m4(mtx, t->obedit->obmat); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); @@ -1443,7 +1461,9 @@ static void createTransCurveVerts(TransInfo *t) { copy_v3_v3(td->iloc, bezt->vec[0]); td->loc = bezt->vec[0]; - copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1 : 0]); + copy_v3_v3(td->center, bezt->vec[(hide_handles || + (t->around == V3D_LOCAL) || + (bezt->f2 & SELECT)) ? 1 : 0]); if (hide_handles) { if (bezt->f2 & SELECT) td->flag = TD_SELECTED; else td->flag = 0; @@ -1511,7 +1531,9 @@ static void createTransCurveVerts(TransInfo *t) { copy_v3_v3(td->iloc, bezt->vec[2]); td->loc = bezt->vec[2]; - copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1 : 2]); + copy_v3_v3(td->center, bezt->vec[(hide_handles || + (t->around == V3D_LOCAL) || + (bezt->f2 & SELECT)) ? 1 : 2]); if (hide_handles) { if (bezt->f2 & SELECT) td->flag = TD_SELECTED; else td->flag = 0; @@ -1552,7 +1574,7 @@ static void createTransCurveVerts(TransInfo *t) * but for now just don't change handle types */ if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) { /* sets the handles based on their selection, do this after the data is copied to the TransData */ - BKE_nurb_handles_test(nu); + BKE_nurb_handles_test(nu, !hide_handles); } } else { @@ -3872,7 +3894,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } /* if handles were not selected, store their selection status */ - if (!(sel1) && !(sel3)) { + if (!(sel1) || !(sel3)) { if (hdata == NULL) hdata = initTransDataCurveHandles(td, bezt); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 233ef1d18a5..94f481d8dfc 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1145,6 +1145,11 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even if (v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN; t->around = v3d->around; + /* warp always uses the cursor */ + if (t->mode == TFM_WARP) { + t->around = V3D_CURSOR; + } + if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) && RNA_property_is_set(op->ptr, prop))) { @@ -1484,10 +1489,10 @@ void calculateCenter2D(TransInfo *t) copy_v3_v3(vec, t->center); mul_m4_v3(ob->obmat, vec); - projectIntView(t, vec, t->center2d); + projectFloatView(t, vec, t->center2d); } else { - projectIntView(t, t->center, t->center2d); + projectFloatView(t, t->center, t->center2d); } } @@ -1691,7 +1696,7 @@ void calculateCenter(TransInfo *t) Object *ob = OBACT; if (ob) { copy_v3_v3(t->center, ob->obmat[3]); - projectIntView(t, t->center, t->center2d); + projectFloatView(t, t->center, t->center2d); } } break; @@ -1723,7 +1728,7 @@ void calculateCenter(TransInfo *t) axis[1] = t->center[1] - 6.0f * axis[1]; axis[2] = t->center[2] - 6.0f * axis[2]; - projectIntView(t, axis, t->center2d); + projectFloatView(t, axis, t->center2d); /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */ if (t->mode == TFM_TRANSLATION) { diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index c035b6173c8..ee993129303 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -279,7 +279,17 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], output[0] = *angle; } -void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const int center[2], const int mval[2]) +static void InputAngleSpring(TransInfo *t, MouseInput *mi, const int mval[2], float output[3]) +{ + float toutput[3]; + + InputAngle(t, mi, mval, output); + InputSpring(t, mi, mval, toutput); + + output[1] = toutput[0]; +} + +void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2]) { mi->factor = 0; mi->precision = 0; @@ -328,6 +338,12 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) mi->apply = InputAngle; t->helpline = HLP_ANGLE; break; + case INPUT_ANGLE_SPRING: + calcSpringFactor(mi); + mi->data = MEM_callocN(sizeof(double), "angle accumulator"); + mi->apply = InputAngleSpring; + t->helpline = HLP_ANGLE; + break; case INPUT_TRACKBALL: /* factor has to become setting or so */ mi->factor = 0.01f; diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 6fecf0d6642..f667a98812b 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -428,12 +428,12 @@ int calc_manipulator_stats(const bContext *C) totsel++; } else { - if (bezt->f1) { - calc_tw_center(scene, bezt->vec[0]); + if (bezt->f1 & SELECT) { + calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 0]); totsel++; } - if (bezt->f3) { - calc_tw_center(scene, bezt->vec[2]); + if (bezt->f3 & SELECT) { + calc_tw_center(scene, bezt->vec[(v3d->around == V3D_LOCAL) ? 1 : 2]); totsel++; } } @@ -1858,11 +1858,12 @@ int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) * See [#34621], it's a miracle it did not cause more problems!!! */ /* However, we need to copy the "release_confirm" property... */ PointerRNA props_ptr; - WM_operator_properties_create(&props_ptr, "TRANSFORM_OT_trackball"); + wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_trackball", true); + WM_operator_properties_create_ptr(&props_ptr, ot); RNA_boolean_set(&props_ptr, "release_confirm", RNA_boolean_get(op->ptr, "release_confirm")); - - WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, &props_ptr); - //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, NULL, NULL, FALSE); + WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, &props_ptr); + //wm_operator_invoke(C, WM_operatortype_find(ot->idname, 0), event, NULL, NULL, FALSE); + WM_operator_properties_free(&props_ptr); } else if (drawflags & MAN_ROT_C) { switch (drawflags) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index e7c22fc0899..2904b37c2e5 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -60,7 +60,7 @@ typedef struct TransformModeItem { void (*opfunc)(wmOperatorType *); } TransformModeItem; -static float VecOne[3] = {1, 1, 1}; +static const float VecOne[3] = {1, 1, 1}; static char OP_TRANSLATION[] = "TRANSFORM_OT_translate"; static char OP_ROTATION[] = "TRANSFORM_OT_rotate"; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 55d80d63234..cd6a2e6712e 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -728,31 +728,46 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } } else { + const bool use_handle = (cu->drawflag & CU_HIDE_HANDLES) == 0; + for (nu = nurbs->first; nu; nu = nu->next) { /* only bezier has a normal */ if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; while (a--) { + short flag = 0; + +#define SEL_F1 (1 << 0) +#define SEL_F2 (1 << 1) +#define SEL_F3 (1 << 2) + + if (use_handle) { + if (bezt->f1 & SELECT) flag |= SEL_F1; + if (bezt->f2 & SELECT) flag |= SEL_F2; + if (bezt->f3 & SELECT) flag |= SEL_F3; + } + else { + flag = (bezt->f2 & SELECT) ? (SEL_F1 | SEL_F2 | SEL_F3) : 0; + } + /* exception */ - if ((bezt->f1 | bezt->f2 | bezt->f3) & SELECT) { + if (flag) { float tvec[3]; - if ((bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT) { + if ((v3d->around == V3D_LOCAL) || + ELEM3(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) + { BKE_nurb_bezt_calc_normal(nu, bezt, tvec); add_v3_v3(normal, tvec); } else { - if (bezt->f1 & SELECT) { + /* ignore bezt->f2 in this case */ + if (flag & SEL_F1) { sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]); normalize_v3(tvec); add_v3_v3(normal, tvec); } - if (bezt->f2 & SELECT) { - sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[2]); - normalize_v3(tvec); - add_v3_v3(normal, tvec); - } - if (bezt->f3 & SELECT) { + if (flag & SEL_F3) { sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]); normalize_v3(tvec); add_v3_v3(normal, tvec); @@ -762,6 +777,11 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], BKE_nurb_bezt_calc_plane(nu, bezt, tvec); add_v3_v3(plane, tvec); } + +#undef SEL_F1 +#undef SEL_F2 +#undef SEL_F3 + bezt++; } } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 4a208f6eee1..04bccac2a15 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -134,7 +134,8 @@ bool validSnap(TransInfo *t) bool activeSnap(TransInfo *t) { - return (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT; + return ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP) || + ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT); } void drawSnapping(const struct bContext *C, TransInfo *t) diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 35e6c40c36b..7424acd752f 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -258,7 +258,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info) { wmWindow *win = CTX_wm_window(C); - const int *mval_src = (int *)arg_info; + const float *mval_src = (float *)arg_info; const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin}; @@ -266,7 +266,7 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info setlinestyle(3); glBegin(GL_LINE_STRIP); glVertex2iv(mval_dst); - glVertex2iv(mval_src); + glVertex2fv(mval_src); glEnd(); setlinestyle(0); } diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index b8a54c56c63..2d33a2d3937 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -4123,7 +4123,7 @@ static void p_smooth(PChart *chart) MEM_freeN(nodesx); MEM_freeN(nodesy); - arena = BLI_memarena_new(1 << 16, "param smooth arena"); + arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param smooth arena"); root = p_node_new(arena, tri, esize * 2, minv, maxv, 0); for (v = chart->verts; v; v = v->nextlink) @@ -4143,7 +4143,7 @@ ParamHandle *param_construct_begin(void) PHandle *handle = MEM_callocN(sizeof(*handle), "PHandle"); handle->construction_chart = p_chart_new(handle); handle->state = PHANDLE_STATE_ALLOCATED; - handle->arena = BLI_memarena_new((1 << 16), "param construct arena"); + handle->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "param construct arena"); handle->aspx = 1.0f; handle->aspy = 1.0f; handle->do_aspect = FALSE; diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 8cb44d05b84..7dc218c74df 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -369,7 +369,7 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) if (lineset->flags & FREESTYLE_LINESET_ENABLED) { if (G.debug & G_DEBUG_FREESTYLE) { cout << " " << layer_count+1 << ": " << lineset->name << " - " << - lineset->linestyle->id.name + 2 << endl; + (lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl; } Text *text = create_lineset_handler(bmain, srl->name, lineset->name); controller->InsertStyleModule(layer_count, lineset->name, text); @@ -680,9 +680,11 @@ void FRS_paste_active_lineset(FreestyleConfig *config) FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); if (lineset) { - lineset->linestyle->id.us--; + if (lineset->linestyle) + lineset->linestyle->id.us--; lineset->linestyle = lineset_buffer.linestyle; - lineset->linestyle->id.us++; + if (lineset->linestyle) + lineset->linestyle->id.us++; lineset->flags = lineset_buffer.flags; lineset->selection = lineset_buffer.selection; lineset->qi = lineset_buffer.qi; @@ -711,10 +713,10 @@ void FRS_delete_active_lineset(FreestyleConfig *config) if (lineset) { if (lineset->group) { lineset->group->id.us--; - lineset->group = NULL; } - lineset->linestyle->id.us--; - lineset->linestyle = NULL; + if (lineset->linestyle) { + lineset->linestyle->id.us--; + } BLI_remlink(&config->linesets, lineset); MEM_freeN(lineset); BKE_freestyle_lineset_set_active_index(config, 0); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 9319ac53db6..ed7a2f4ede0 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1126,10 +1126,12 @@ static void do_material_tex(GPUShadeInput *shi) else { /* otherwise use accumulated perturbations */ GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor); } - } else if (mtex->normapspace == MTEX_NSPACE_OBJECT) { + } + else if (mtex->normapspace == MTEX_NSPACE_OBJECT) { /* transform normal by object then view matrix */ GPU_link(mat, "mtex_nspace_object", GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), tnor, &newnor); - } else if (mtex->normapspace == MTEX_NSPACE_WORLD) { + } + else if (mtex->normapspace == MTEX_NSPACE_WORLD) { /* transform normal by view matrix */ GPU_link(mat, "mtex_nspace_world", GPU_builtin(GPU_VIEW_MATRIX), tnor, &newnor); } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index bab677da842..633112095a7 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2134,6 +2134,20 @@ void node_fresnel(float ior, vec3 N, vec3 I, out float result) result = fresnel_dielectric(I, N, (gl_FrontFacing)? eta: 1.0/eta); } +/* gamma */ + +void node_gamma(vec4 col, float gamma, out vec4 outcol) +{ + outcol = col; + + if(col.r > 0.0) + outcol.r = compatible_pow(col.r, gamma); + if(col.g > 0.0) + outcol.g = compatible_pow(col.g, gamma); + if(col.b > 0.0) + outcol.b = compatible_pow(col.b, gamma); +} + /* geometry */ void node_attribute(vec3 attr_uv, out vec4 outcol, out vec3 outvec, out float outf) diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt index 29ed8c95fc6..4025a41b6a7 100644 --- a/source/blender/imbuf/CMakeLists.txt +++ b/source/blender/imbuf/CMakeLists.txt @@ -105,6 +105,11 @@ if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() + +if(WITH_OPENIMAGEIO) + add_definitions(-DWITH_OPENIMAGEIO) +endif() + if(WITH_IMAGE_OPENJPEG) list(APPEND INC_SYS ${OPENJPEG_INCLUDE_DIRS} diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 64a2bbb72d9..8af86389db3 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -174,19 +174,16 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo /* ** OpenGL drawing routines using GLSL for color space transform ** */ /* Test if GLSL drawing is supported for combination of graphics card and this configuration */ -bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings, - bool skip_curves); +bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings); /* Configures GLSL shader for conversion from scene linear to display space */ bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, - bool predivide, - bool skip_curves); + bool predivide); /* Same as above, but display space conversion happens from a specified space */ bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, struct ColorSpace *colorspace, - bool predivide, - bool skip_curves); + bool predivide); /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, bool predivide); /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 8c2e79ab7d8..c70ab5d7189 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -429,7 +429,7 @@ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol * * \attention defined in readimage.c */ -struct ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr); +struct ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr); /** * diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 1734073dd6c..d20130805c0 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -180,6 +180,10 @@ typedef struct ImBuf { */ #define IB_CUSTOM_FLAGS_MASK 0x7ff +#ifdef WITH_OPENIMAGEIO +#define PSD (1 << 31) +#endif + #define PNG (1 << 30) #define TGA (1 << 28) #define JPG (1 << 27) @@ -273,6 +277,9 @@ extern const char *imb_ext_image_qt[]; extern const char *imb_ext_movie[]; extern const char *imb_ext_audio[]; +/* image formats that can only be loaded via filepath */ +extern const char *imb_ext_image_filepath_only[]; + enum { IMB_COLORMANAGE_IS_DATA = (1 << 0) }; diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript index 03064df293d..ccee3ebcc85 100644 --- a/source/blender/imbuf/SConscript +++ b/source/blender/imbuf/SConscript @@ -55,6 +55,9 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', ' incs += ' ' + env['BF_PTHREADS_INC'] incs += ' ../../../intern/utfconv' +if env['WITH_BF_OIIO']: + defs.append('WITH_OPENIMAGEIO') + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') else: diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 3c8b29cf68a..9327c15c415 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -39,8 +39,10 @@ typedef struct ImFileType { void (*exit)(void); int (*is_a)(unsigned char *buf); + int (*is_a_filepath)(const char *name); int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf); struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]); + struct ImBuf *(*load_filepath)(const char *name, int flags, char colorspace[IM_MAX_SPACE]); int (*save)(struct ImBuf *ibuf, const char *name, int flags); void (*load_tile)(struct ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect); @@ -50,6 +52,7 @@ typedef struct ImFileType { } ImFileType; extern ImFileType IMB_FILE_TYPES[]; +extern ImFileType *IMB_FILE_TYPES_LAST; void imb_filetypes_init(void); void imb_filetypes_exit(void); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 4c4c82a0bb4..cf9cc0c2e6f 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -119,6 +119,11 @@ static struct global_glsl_state { char input[MAX_COLORSPACE_NAME]; float exposure, gamma; + CurveMapping *curve_mapping, *orig_curve_mapping; + bool use_curve_mapping; + int curve_mapping_timestamp; + OCIO_CurveMappingSettings curve_mapping_settings; + /* Container for GLSL state needed for OCIO module. */ struct OCIO_GLSLDrawState *ocio_glsl_state; struct OCIO_GLSLDrawState *transform_ocio_glsl_state; @@ -196,6 +201,7 @@ typedef struct ColormanageCacheViewSettings { int view; float exposure; float gamma; + float dither; CurveMapping *curve_mapping; } ColormanageCacheViewSettings; @@ -213,6 +219,7 @@ typedef struct ColormnaageCacheData { int look; /* Additional artistics transform */ float exposure; /* exposure value cached buffer is calculated with */ float gamma; /* gamma value cached buffer is calculated with */ + float dither; /* dither value cached buffer is calculated with */ CurveMapping *curve_mapping; /* curve mapping used for cached buffer */ int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */ } ColormnaageCacheData; @@ -291,7 +298,8 @@ static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data) ibuf->colormanage_cache->data = data; } -static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cache_view_settings, +static void colormanage_view_settings_to_cache(ImBuf *ibuf, + ColormanageCacheViewSettings *cache_view_settings, const ColorManagedViewSettings *view_settings) { int look = IMB_colormanagement_look_get_named_index(view_settings->look); @@ -301,6 +309,7 @@ static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cac cache_view_settings->view = view; cache_view_settings->exposure = view_settings->exposure; cache_view_settings->gamma = view_settings->gamma; + cache_view_settings->dither = ibuf->dither; cache_view_settings->flag = view_settings->flag; cache_view_settings->curve_mapping = view_settings->curve_mapping; } @@ -378,6 +387,7 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV if (cache_data->look != view_settings->look || cache_data->exposure != view_settings->exposure || cache_data->gamma != view_settings->gamma || + cache_data->dither != view_settings->dither || cache_data->flag != view_settings->flag || cache_data->curve_mapping != curve_mapping || cache_data->curve_mapping_timestamp != curve_mapping_timestamp) @@ -424,6 +434,7 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting cache_data->look = view_settings->look; cache_data->exposure = view_settings->exposure; cache_data->gamma = view_settings->gamma; + cache_data->dither = view_settings->dither; cache_data->flag = view_settings->flag; cache_data->curve_mapping = curve_mapping; cache_data->curve_mapping_timestamp = curve_mapping_timestamp; @@ -657,6 +668,12 @@ void colormanagement_exit(void) if (global_glsl_state.processor) OCIO_processorRelease(global_glsl_state.processor); + if (global_glsl_state.curve_mapping) + curvemapping_free(global_glsl_state.curve_mapping); + + if (global_glsl_state.curve_mapping_settings.lut) + MEM_freeN(global_glsl_state.curve_mapping_settings.lut); + if (global_glsl_state.ocio_glsl_state) OCIO_freeOGLState(global_glsl_state.ocio_glsl_state); @@ -1909,7 +1926,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, boo * we need to allocate byte buffer and store color managed * image there */ - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->save && type->ftype(type, colormanaged_ibuf)) { if ((type->flag & IM_FTYPE_FLOAT) == 0) make_byte = true; @@ -2024,7 +2041,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet return (unsigned char *) ibuf->rect; } - colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings); + colormanage_view_settings_to_cache(ibuf, &cache_view_settings, applied_view_settings); colormanage_display_settings_to_cache(&cache_display_settings, display_settings); if (ibuf->invalid_rect.xmin != ibuf->invalid_rect.xmax) { @@ -2445,7 +2462,7 @@ void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSetting { ImFileType *type; - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->save && type->ftype(type, ibuf)) { const char *role_colorspace; @@ -2735,7 +2752,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, unsigned char *display_buffer = NULL; int view_flag, display_index, buffer_width; - colormanage_view_settings_to_cache(&cache_view_settings, view_settings); + colormanage_view_settings_to_cache(ibuf, &cache_view_settings, view_settings); colormanage_display_settings_to_cache(&cache_display_settings, display_settings); view_flag = 1 << (cache_view_settings.view - 1); @@ -2931,16 +2948,61 @@ static bool check_glsl_display_processor_changed(const ColorManagedViewSettings STREQ(global_glsl_state.input, from_colorspace)); } +static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping, + OCIO_CurveMappingSettings *curve_mapping_settings) +{ + int i; + + curvemapping_initialize(curve_mapping); + curvemapping_premultiply(curve_mapping, false); + curvemapping_table_RGBA(curve_mapping, + &curve_mapping_settings->lut, + &curve_mapping_settings->lut_size); + + for (i = 0; i < 4; i++) { + CurveMap *cuma = curve_mapping->cm + i; + curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != 0; + curve_mapping_settings->range[i] = cuma->range; + curve_mapping_settings->mintable[i] = cuma->mintable; + curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0]; + curve_mapping_settings->ext_in_y[i] = cuma->ext_in[1]; + curve_mapping_settings->ext_out_x[i] = cuma->ext_out[0]; + curve_mapping_settings->ext_out_y[i] = cuma->ext_out[1]; + curve_mapping_settings->first_x[i] = cuma->table[0].x; + curve_mapping_settings->first_y[i] = cuma->table[0].y; + curve_mapping_settings->last_x[i] = cuma->table[CM_TABLE].x; + curve_mapping_settings->last_y[i] = cuma->table[CM_TABLE].y; + } + + copy_v3_v3(curve_mapping_settings->black, curve_mapping->black); + copy_v3_v3(curve_mapping_settings->bwmul, curve_mapping->bwmul); + + curve_mapping_settings->cache_id = (size_t) curve_mapping; +} + static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const char *from_colorspace) { + bool use_curve_mapping = (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) != 0; + bool need_update = false; + + need_update = global_glsl_state.processor == NULL || + check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace) || + use_curve_mapping != global_glsl_state.use_curve_mapping; + + if (use_curve_mapping && need_update == false) { + need_update |= view_settings->curve_mapping->changed_timestamp != global_glsl_state.curve_mapping_timestamp || + view_settings->curve_mapping != global_glsl_state.orig_curve_mapping; + } + /* Update state if there's no processor yet or * processor settings has been changed. */ - if (global_glsl_state.processor == NULL || - check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace)) - { + if (need_update) { + OCIO_CurveMappingSettings *curve_mapping_settings = &global_glsl_state.curve_mapping_settings; + CurveMapping *new_curve_mapping = NULL; + /* Store settings of processor for further comparison. */ BLI_strncpy(global_glsl_state.look, view_settings->look, MAX_COLORSPACE_NAME); BLI_strncpy(global_glsl_state.view, view_settings->view_transform, MAX_COLORSPACE_NAME); @@ -2949,6 +3011,35 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s global_glsl_state.exposure = view_settings->exposure; global_glsl_state.gamma = view_settings->gamma; + /* We're using curve mapping's address as a acache ID, + * so we need to make sure re-allocation gives new address here. + * We do this by allocating new curve mapping before freeing ol one. + */ + if (use_curve_mapping) { + new_curve_mapping = curvemapping_copy(view_settings->curve_mapping); + } + + if (global_glsl_state.curve_mapping) { + curvemapping_free(global_glsl_state.curve_mapping); + MEM_freeN(curve_mapping_settings->lut); + global_glsl_state.curve_mapping = NULL; + curve_mapping_settings->lut = NULL; + } + + /* Fill in OCIO's curve mapping settings. */ + if (use_curve_mapping) { + curve_mapping_to_ocio_settings(new_curve_mapping, &global_glsl_state.curve_mapping_settings); + + global_glsl_state.curve_mapping = new_curve_mapping; + global_glsl_state.curve_mapping_timestamp = view_settings->curve_mapping->changed_timestamp; + global_glsl_state.orig_curve_mapping = view_settings->curve_mapping; + global_glsl_state.use_curve_mapping = true; + } + else { + global_glsl_state.orig_curve_mapping = NULL; + global_glsl_state.use_curve_mapping = false; + } + /* Free old processor, if any. */ if (global_glsl_state.processor) OCIO_processorRelease(global_glsl_state.processor); @@ -2964,14 +3055,8 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s } } -bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_settings, - bool skip_curves) +bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *UNUSED(view_settings)) { - /* curves not supported yet */ - if (!skip_curves) - if (view_settings && (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)) - return 0; - return OCIO_supportGLSLDraw(); } @@ -2990,8 +3075,7 @@ bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_ */ bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - struct ColorSpace *from_colorspace, bool predivide, - bool skip_curves) + struct ColorSpace *from_colorspace, bool predivide) { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -3008,25 +3092,22 @@ bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettin applied_view_settings = &default_view_settings; } - /* RGB curves mapping is not supported on GPU yet. */ - if (!skip_curves) - if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) - return false; - /* Make sure OCIO processor is up-to-date. */ update_glsl_display_processor(applied_view_settings, display_settings, from_colorspace ? from_colorspace->name : global_role_scene_linear); - return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, predivide); + return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, + global_glsl_state.use_curve_mapping ? &global_glsl_state.curve_mapping_settings : NULL, + predivide); } /* Configures GLSL shader for conversion from scene linear to display space */ bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - bool predivide, bool skip_curves) + bool predivide) { return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - NULL, predivide, skip_curves); + NULL, predivide); } /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ @@ -3037,7 +3118,7 @@ bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); - return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide, false); + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide); } /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ @@ -3076,7 +3157,7 @@ bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide processor = colorspace_to_scene_linear_processor(colorspace); - return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, predivide); + return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, NULL, predivide); } /* Finish GLSL-based color space conversion */ diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index 37070c7e2bf..f9e05dbd6d6 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -35,6 +35,10 @@ #include "IMB_colormanagement.h" +#ifdef WITH_OPENIMAGEIO +#include "oiio/openimageio_api.h" +#endif + #ifdef WITH_OPENEXR #include "openexr/openexr_api.h" #endif @@ -71,41 +75,46 @@ void quicktime_exit(void); #endif ImFileType IMB_FILE_TYPES[] = { - {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, - {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_jpeg, NULL, imb_ftype_default, imb_load_jpeg, NULL, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_png, NULL, imb_ftype_default, imb_loadpng, NULL, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_bmp, NULL, imb_ftype_default, imb_bmp_decode, NULL, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_targa, NULL, imb_ftype_default, imb_loadtarga, NULL, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_iris, NULL, imb_ftype_iris, imb_loadiris, NULL, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE}, #ifdef WITH_CINEON - {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_load_dpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, - {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_load_cineon, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_dpx, NULL, imb_ftype_default, imb_load_dpx, NULL, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_cineon, NULL, imb_ftype_default, imb_load_cineon, NULL, imb_save_cineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_TIFF - {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, + {imb_inittiff, NULL, imb_is_a_tiff, NULL, imb_ftype_default, imb_loadtiff, NULL, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_HDR - {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT}, + {NULL, NULL, imb_is_a_hdr, NULL, imb_ftype_default, imb_loadhdr, NULL, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENEXR - {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT}, + {imb_initopenexr, NULL, imb_is_a_openexr, NULL, imb_ftype_default, imb_load_openexr, NULL, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT}, #endif #ifdef WITH_OPENJPEG - {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_jp2, NULL, imb_ftype_default, imb_jp2_decode, NULL, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_DDS - {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE}, + {NULL, NULL, imb_is_a_dds, NULL, imb_ftype_default, imb_load_dds, NULL, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE}, #endif #ifdef WITH_QUICKTIME - {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE}, + {quicktime_init, quicktime_exit, imb_is_a_quicktime, NULL, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE}, +#endif +#ifdef WITH_OPENIMAGEIO + {NULL, NULL, NULL, imb_is_a_photoshop, imb_ftype_default, NULL, imb_load_photoshop, NULL, NULL, IM_FTYPE_FLOAT, PSD, COLOR_ROLE_DEFAULT_FLOAT}, #endif - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0} + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0} }; - + +ImFileType *IMB_FILE_TYPES_LAST = &IMB_FILE_TYPES[sizeof(IMB_FILE_TYPES) / sizeof(ImFileType) - 1]; + void imb_filetypes_init(void) { ImFileType *type; - for (type = IMB_FILE_TYPES; type->is_a; type++) + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->init) type->init(); } @@ -114,7 +123,7 @@ void imb_filetypes_exit(void) { ImFileType *type; - for (type = IMB_FILE_TYPES; type->is_a; type++) + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->exit) type->exit(); } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index dd0970a71f2..93324b94cdc 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -55,12 +55,12 @@ #endif -static char magic[] = "BlenMIdx"; -static char temp_ext[] = "_part"; +static const char magic[] = "BlenMIdx"; +static const char temp_ext[] = "_part"; -static int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75, +static const int proxy_sizes[] = { IMB_PROXY_25, IMB_PROXY_50, IMB_PROXY_75, IMB_PROXY_100 }; -static float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 }; +static const float proxy_fac[] = { 0.25, 0.50, 0.75, 1.00 }; #ifdef WITH_FFMPEG static int tc_types[] = {IMB_TC_RECORD_RUN, diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt new file mode 100644 index 00000000000..5fb8f11602e --- /dev/null +++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt @@ -0,0 +1,54 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + .. + ../.. + ../../../blenkernel + ../../../blenlib + ../../../makesdna + ../../../../../intern/guardedalloc + ../../../../../intern/utfconv +) + +set(INC_SYS + +) + +set(SRC + openimageio_api.h + + openimageio_api.cpp +) + +if(WITH_OPENIMAGEIO) + list(APPEND INC_SYS + ${OPENIMAGEIO_INCLUDE_DIRS} + ) + add_definitions(-DWITH_OPENIMAGEIO) +endif() + +blender_add_lib(bf_imbuf_openimageio "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/oiio/SConscript b/source/blender/imbuf/intern/oiio/SConscript new file mode 100644 index 00000000000..82b47e9c46b --- /dev/null +++ b/source/blender/imbuf/intern/oiio/SConscript @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): +# +# ***** END GPL LICENSE BLOCK ***** + +Import ('env') + +source_files = ['openimageio_api.cpp'] + +incs = ['.', + '../../../blenkernel', + '../../', + '..', + '../../../blenlib', + 'intern/include', + '#/intern/guardedalloc', + '../../../makesdna', + '#/intern/utfconv'] + +incs += Split(env['BF_OIIO_INC']) + +defs = ['WITH_OPENIMAGEIO'] + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): + incs.append(env['BF_PTHREADS_INC']) + +env.BlenderLib ('bf_imbuf_openimageio', source_files, incs, defs, libtype=['core','player'], priority = [225,180]) diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp new file mode 100644 index 00000000000..838343dce35 --- /dev/null +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -0,0 +1,256 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Dalai Felinto and Brecht van Lommel + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/oiio/openimageio_api.cpp + * \ingroup openimageio + */ + +#include <set> + +#include <openimageio_api.h> +#include <OpenImageIO/imageio.h> + +OIIO_NAMESPACE_USING + +#if defined(WIN32) && !defined(FREE_WINDOWS) +#include "utfconv.h" +#endif + +extern "C" +{ +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" +} + +using namespace std; + +typedef unsigned char uchar; + +template <class T, class Q> +static void fill_all_channels(T *pixels, int width, int height, int components, Q alpha) +{ + if (components == 2) { + for (int i = width * height - 1; i >= 0; i--) { + pixels[i * 4 + 3] = pixels[i * 2 + 1]; + pixels[i * 4 + 2] = pixels[i * 2 + 0]; + pixels[i * 4 + 1] = pixels[i * 2 + 0]; + pixels[i * 4 + 0] = pixels[i * 2 + 0]; + } + } + else if (components == 3) { + for (int i = width * height - 1; i >= 0; i--) { + pixels[i * 4 + 3] = alpha; + pixels[i * 4 + 2] = pixels[i * 3 + 2]; + pixels[i * 4 + 1] = pixels[i * 3 + 1]; + pixels[i * 4 + 0] = pixels[i * 3 + 0]; + + } + } + else if (components == 1) { + for (int i = width * height - 1; i >= 0; i--) { + pixels[i * 4 + 3] = alpha; + pixels[i * 4 + 2] = pixels[i]; + pixels[i * 4 + 1] = pixels[i]; + pixels[i * 4 + 0] = pixels[i]; + } + } + +} + +static ImBuf *imb_oiio_load_image(ImageInput *in, int width, int height, int components, int flags, bool is_alpha) +{ + ImBuf *ibuf; + int scanlinesize = width * components * sizeof(uchar); + + /* allocate the memory for the image */ + ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rect); + + try + { + in->read_image(TypeDesc::UINT8, + (uchar *)ibuf->rect + (height - 1) * scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); + } + catch (const std::exception &exc) + { + std::cerr << exc.what() << std::endl; + if (ibuf) IMB_freeImBuf(ibuf); + + return NULL; + } + + /* ImBuf always needs 4 channels */ + fill_all_channels((uchar *)ibuf->rect, width, height, components, 0xFF); + + return ibuf; +} + +static ImBuf *imb_oiio_load_image_float(ImageInput *in, int width, int height, int components, int flags, bool is_alpha) +{ + ImBuf *ibuf; + int scanlinesize = width * components * sizeof(float); + + /* allocate the memory for the image */ + ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, flags | IB_rectfloat); + + try + { + in->read_image(TypeDesc::FLOAT, + (uchar *)ibuf->rect_float + (height - 1) * scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); + } + catch (const std::exception &exc) + { + std::cerr << exc.what() << std::endl; + if (ibuf) IMB_freeImBuf(ibuf); + + return NULL; + } + + /* ImBuf always needs 4 channels */ + fill_all_channels((float *)ibuf->rect_float, width, height, components, 1.0f); + + /* note: Photoshop 16 bit files never has alpha with it, so no need to handle associated/unassociated alpha */ + return ibuf; +} + +extern "C" +{ + +int imb_is_a_photoshop(const char *filename) +{ + const char *photoshop_extension[] = { + ".psd", + ".pdd", + ".psb", + NULL + }; + + return BLI_testextensie_array(filename, photoshop_extension); +} + +int imb_save_photoshop(struct ImBuf *ibuf, const char *name, int flags) +{ + if (flags & IB_mem) { + printf("Photoshop PSD-save: Create PSD in memory CURRENTLY NOT SUPPORTED !\n"); + imb_addencodedbufferImBuf(ibuf); + ibuf->encodedsize = 0; + return(0); + } + + return(0); +} + +struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspace[IM_MAX_SPACE]) +{ + ImageInput *in = NULL; + struct ImBuf *ibuf = NULL; + int width, height, components; + bool is_float, is_alpha; + TypeDesc typedesc; + int basesize; + + /* load image from file through OIIO */ + if (imb_is_a_photoshop(filename) == 0) return (NULL); + + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); + + in = ImageInput::create(filename); + if (!in) return NULL; + + ImageSpec spec, config; + config.attribute("oiio:UnassociatedAlpha", (int) 1); + + if (!in->open(filename, spec, config)) { + delete in; + return NULL; + } + + string ics = spec.get_string_attribute("oiio:ColorSpace"); + BLI_strncpy(colorspace, ics.c_str(), IM_MAX_SPACE); + + width = spec.width; + height = spec.height; + components = spec.nchannels; + is_alpha = spec.alpha_channel != -1; + basesize = spec.format.basesize(); + is_float = basesize > 1; + + /* we only handle certain number of components */ + if (!(components >= 1 && components <= 4)) { + if (in) { + in->close(); + delete in; + } + return NULL; + } + + if (is_float) + ibuf = imb_oiio_load_image_float(in, width, height, components, flags, is_alpha); + else + ibuf = imb_oiio_load_image(in, width, height, components, flags, is_alpha); + + if (in) { + in->close(); + delete in; + } + + if (!ibuf) + return NULL; + + /* ImBuf always needs 4 channels */ + ibuf->ftype = PSD; + ibuf->channels = 4; + ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize; + + try + { + return ibuf; + } + catch (const std::exception &exc) + { + std::cerr << exc.what() << std::endl; + if (ibuf) IMB_freeImBuf(ibuf); + + return NULL; + } +} + +} // export "C" + + diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h new file mode 100644 index 00000000000..ad11f4bcfe3 --- /dev/null +++ b/source/blender/imbuf/intern/oiio/openimageio_api.h @@ -0,0 +1,53 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/imbuf/intern/oiio/openimageio_api.h + * \ingroup openimageio + */ + + +#ifndef __OPENIMAGEIO_API_H__ +#define __OPENIMAGEIO_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +int imb_is_a_photoshop (const char *name); + +int imb_save_photoshop (struct ImBuf *ibuf, const char *name, int flags); + +struct ImBuf *imb_load_photoshop (const char *name, int flags, char *colorspace); + +#ifdef __cplusplus +} + +#endif + +#endif /* __OPENIMAGEIO_API_H__ */ diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index d73fa9a7ab7..6988687e4ed 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -56,6 +56,53 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" +static void imb_handle_alpha(ImBuf *ibuf, int flags, char colorspace[IM_MAX_SPACE], char effective_colorspace[IM_MAX_SPACE]) +{ + int alpha_flags; + + if (colorspace) { + if (ibuf->rect) { + /* byte buffer is never internally converted to some standard space, + * store pointer to it's color space descriptor instead + */ + ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace); + } + + BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); + } + + if (flags & IB_alphamode_detect) + alpha_flags = ibuf->flags & IB_alphamode_premul; + else + alpha_flags = flags & IB_alphamode_premul; + + if (flags & IB_ignore_alpha) { + IMB_rectfill_alpha(ibuf, 1.0f); + } + else { + if (alpha_flags & IB_alphamode_premul) { + if (ibuf->rect) { + IMB_unpremultiply_alpha(ibuf); + } + else { + /* pass, floats are expected to be premul */ + } + } + else { + if (ibuf->rect_float) { + IMB_premultiply_alpha(ibuf); + } + else { + /* pass, bytes are expected to be straight */ + } + } + } + + /* OCIO_TODO: in some cases it's faster to do threaded conversion, + * but how to distinguish such cases */ + colormanage_imbuf_make_linear(ibuf, effective_colorspace); +} + ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; @@ -70,54 +117,36 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co if (colorspace) BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->load) { ibuf = type->load(mem, size, flags, effective_colorspace); if (ibuf) { - int alpha_flags; - - if (colorspace) { - if (ibuf->rect) { - /* byte buffer is never internally converted to some standard space, - * store pointer to it's color space descriptor instead - */ - ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace); - } - - BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE); - } - - if (flags & IB_alphamode_detect) - alpha_flags = ibuf->flags & IB_alphamode_premul; - else - alpha_flags = flags & IB_alphamode_premul; - - if (flags & IB_ignore_alpha) { - IMB_rectfill_alpha(ibuf, 1.0f); - } - else { - if (alpha_flags & IB_alphamode_premul) { - if (ibuf->rect) { - IMB_unpremultiply_alpha(ibuf); - } - else { - /* pass, floats are expected to be premul */ - } - } - else { - if (ibuf->rect_float) { - IMB_premultiply_alpha(ibuf); - } - else { - /* pass, bytes are expected to be straight */ - } - } - } - - /* OCIO_TODO: in some cases it's faster to do threaded conversion, - * but how to distinguish such cases */ - colormanage_imbuf_make_linear(ibuf, effective_colorspace); + imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace); + return ibuf; + } + } + } + + if ((flags & IB_test) == 0) + fprintf(stderr, "%s: unknown fileformat (%s)\n", __func__, descr); + + return NULL; +} + +static ImBuf *IMB_ibImageFromFile(const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr) +{ + ImBuf *ibuf; + ImFileType *type; + char effective_colorspace[IM_MAX_SPACE] = ""; + + if (colorspace) + BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace)); + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->load_filepath) { + ibuf = type->load_filepath(filepath, flags, effective_colorspace); + if (ibuf) { + imb_handle_alpha(ibuf, flags, colorspace, effective_colorspace); return ibuf; } } @@ -129,7 +158,13 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co return NULL; } -ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr) +static bool imb_is_filepath_format(const char *filepath) +{ + /* return true if this is one of the formats that can't be loaded from memory */ + return BLI_testextensie_array(filepath, imb_ext_image_filepath_only); +} + +ImBuf *IMB_loadifffile(int file, const char *filepath, int flags, char colorspace[IM_MAX_SPACE], const char *descr) { ImBuf *ibuf; unsigned char *mem; @@ -137,6 +172,9 @@ ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const if (file == -1) return NULL; + if (imb_is_filepath_format(filepath)) + return IMB_ibImageFromFile(filepath, flags, colorspace, descr); + size = BLI_file_descriptor_size(file); mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); @@ -179,7 +217,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_S file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); if (file < 0) return NULL; - ibuf = IMB_loadifffile(file, flags, colorspace, filepath_tx); + ibuf = IMB_loadifffile(file, filepath, flags, colorspace, filepath_tx); if (ibuf) { BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); @@ -206,7 +244,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags) file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0); if (file < 0) return NULL; - ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, colorspace, filepath_tx); + ibuf = IMB_loadifffile(file, filepath, flags | IB_test | IB_multilayer, colorspace, filepath_tx); if (ibuf) { BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name)); @@ -234,7 +272,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int return; } - for (type = IMB_FILE_TYPES; type->is_a; type++) + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) if (type->load_tile && type->ftype(type, ibuf)) type->load_tile(ibuf, mem, size, tx, ty, rect); diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index eaba04c9310..05e9a4fa134 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -315,7 +315,7 @@ int imb_is_a_tiff(unsigned char *mem) (memcmp(lil_endian, mem, IMB_TIFF_NCB) == 0) ); } -static void scanline_contig_16bit(float *rectf, unsigned short *sbuf, int scanline_w, int spp) +static void scanline_contig_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int spp) { int i; for (i = 0; i < scanline_w; i++) { @@ -326,7 +326,7 @@ static void scanline_contig_16bit(float *rectf, unsigned short *sbuf, int scanli } } -static void scanline_contig_32bit(float *rectf, float *fbuf, int scanline_w, int spp) +static void scanline_contig_32bit(float *rectf, const float *fbuf, int scanline_w, int spp) { int i; for (i = 0; i < scanline_w; i++) { @@ -337,14 +337,14 @@ static void scanline_contig_32bit(float *rectf, float *fbuf, int scanline_w, int } } -static void scanline_separate_16bit(float *rectf, unsigned short *sbuf, int scanline_w, int chan) +static void scanline_separate_16bit(float *rectf, const unsigned short *sbuf, int scanline_w, int chan) { int i; for (i = 0; i < scanline_w; i++) rectf[i * 4 + chan] = sbuf[i] / 65535.0; } -static void scanline_separate_32bit(float *rectf, float *fbuf, int scanline_w, int chan) +static void scanline_separate_32bit(float *rectf, const float *fbuf, int scanline_w, int chan) { int i; for (i = 0; i < scanline_w; i++) diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index a4b0e61d544..ecf6458ac57 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -98,6 +98,16 @@ const char *imb_ext_image[] = { #ifdef WITH_OPENEXR ".exr", #endif +#ifdef WITH_OPENIMAGEIO + ".psd", ".pdd", ".psb", +#endif + NULL +}; + +const char *imb_ext_image_filepath_only[] = { +#ifdef WITH_OPENIMAGEIO + ".psd", ".pdd", ".psb", +#endif NULL }; @@ -188,9 +198,16 @@ static int IMB_ispic_name(const char *name) if ((BIG_LONG(((int *)buf)[0]) & 0xfffffff0) == 0xffd8ffe0) return JPG; - for (type = IMB_FILE_TYPES; type->is_a; type++) { - if (type->is_a(buf)) { - return type->filetype; + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { + if (type->is_a) { + if (type->is_a(buf)) { + return type->filetype; + } + } + else if (type->is_a_filepath) { + if (type->is_a_filepath(name)) { + return type->filetype; + } } } diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 5d785e08212..1519fc1990d 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -67,7 +67,7 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags) if (ibuf == NULL) return (FALSE); ibuf->flags = flags; - for (type = IMB_FILE_TYPES; type->is_a; type++) { + for (type = IMB_FILE_TYPES; type < IMB_FILE_TYPES_LAST; type++) { if (type->save && type->ftype(type, ibuf)) { ImBuf *write_ibuf; short result = FALSE; diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index 4307ea57f15..a72e287c16f 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -178,6 +178,7 @@ enum { /* SpaceClip->mask_draw_flag */ #define MASK_DRAWFLAG_SMOOTH 1 +#define MASK_DRAWFLAG_OVERLAY 2 /* copy of eSpaceImage_UVDT */ /* SpaceClip->mask_draw_type */ @@ -188,6 +189,12 @@ enum { MASK_DT_WHITE = 3 }; +/* MaskSpaceInfo->overlay_mode */ +enum { + MASK_OVERLAY_ALPHACHANNEL = 0, + MASK_OVERLAY_COMBINED = 1 +}; + /* masklay->blend */ enum { MASK_BLEND_ADD = 0, diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5cfe3fd2082..75b9540f736 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -149,23 +149,16 @@ typedef enum eNodeSocketInOut { } eNodeSocketInOut; /* sock->flag, first bit is select */ - /* hidden is user defined, to hide unused */ -#define SOCK_HIDDEN 2 - /* for quick check if socket is linked */ -#define SOCK_IN_USE 4 - /* unavailable is for dynamic sockets */ -#define SOCK_UNAVAIL 8 - /* DEPRECATED dynamic socket (can be modified by user) */ -#define __SOCK_DYNAMIC 16 - /* DEPRECATED group socket should not be exposed */ -#define __SOCK_INTERNAL 32 - /* socket collapsed in UI */ -#define SOCK_COLLAPSED 64 - /* hide socket value, if it gets auto default */ -#define SOCK_HIDE_VALUE 128 - /* socket hidden automatically, to distinguish from manually hidden */ - /* DEPRECATED, only kept here to avoid reusing the flag */ -#define SOCK_AUTO_HIDDEN__DEPRECATED 256 +typedef enum eNodeSocketFlag { + SOCK_HIDDEN = 2, /* hidden is user defined, to hide unused */ + SOCK_IN_USE = 4, /* for quick check if socket is linked */ + SOCK_UNAVAIL = 8, /* unavailable is for dynamic sockets */ + __SOCK_DYNAMIC = 16, /* DEPRECATED dynamic socket (can be modified by user) */ + __SOCK_INTERNAL = 32, /* DEPRECATED group socket should not be exposed */ + SOCK_COLLAPSED = 64, /* socket collapsed in UI */ + SOCK_HIDE_VALUE = 128, /* hide socket value, if it gets auto default */ + SOCK_AUTO_HIDDEN__DEPRECATED = 256 /* socket hidden automatically, to distinguish from manually hidden */ +} eNodeSocketFlag; /* limit data in bNode to what we want to see saved? */ typedef struct bNode { @@ -976,7 +969,7 @@ typedef struct NodeShaderNormalMap { #define SHD_NORMAL_MAP_BLENDER_WORLD 4 /* subsurface */ -#define SHD_SUBSURFACE_COMPATIBLE 0 +#define SHD_SUBSURFACE_COMPATIBLE 0 // Deprecated #define SHD_SUBSURFACE_CUBIC 1 #define SHD_SUBSURFACE_GAUSSIAN 2 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 002d77fb0e6..232fe62df31 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -316,6 +316,7 @@ typedef struct ImageFormatData { #define R_IMF_IMTYPE_H264 31 #define R_IMF_IMTYPE_XVID 32 #define R_IMF_IMTYPE_THEORA 33 +#define R_IMF_IMTYPE_PSD 34 #define R_IMF_IMTYPE_INVALID 255 @@ -510,6 +511,7 @@ typedef struct RenderData { short bake_normal_space, bake_quad_split; float bake_maxdist, bake_biasdist; short bake_samples, bake_pad; + float bake_user_scale, bake_pad1; /* path to render output */ char pic[1024]; /* 1024 = FILE_MAX */ @@ -981,17 +983,6 @@ typedef struct ToolSettings { * paint */ float vgroup_weight; - /* Subdivide Settings */ - short cornertype; - short pad1; - /*Triangle to Quad conversion threshold*/ - float jointrilimit; - /* Editmode Tools */ - float degr; - short step; - short turn; - - float extr_offs; /* extrude offset */ float doublimit; /* remove doubles limit */ float normalsize; /* size of normals */ short automerge; @@ -999,30 +990,21 @@ typedef struct ToolSettings { /* Selection Mode for Mesh */ short selectmode; - /* Primitive Settings */ - /* UV Sphere */ - short segments; - short rings; - - /* Cylinder - Tube - Circle */ - short vertices; - /* UV Calculation */ - short unwrapper; - float uvcalc_radius; - float uvcalc_cubesize; + char unwrapper; + char uvcalc_flag; + char uv_flag; + char uv_selectmode; + float uvcalc_margin; - short uvcalc_mapdir; - short uvcalc_mapalign; - short uvcalc_flag; - short uv_flag, uv_selectmode; - short pad2; - - /* Grease Pencil */ - short gpencil_flags; - + /* Auto-IK */ - short autoik_chainlen; + short autoik_chainlen; /* runtime only */ + + /* Grease Pencil */ + char gpencil_flags; + + char pad[5]; /* Image Paint (8 byttse aligned please!) */ struct ImagePaintSettings imapaint; @@ -1035,16 +1017,13 @@ typedef struct ToolSettings { /* Select Group Threshold */ float select_thresh; - - /* Graph Editor */ - float clean_thresh; /* Auto-Keying Mode */ short autokey_mode, autokey_flag; /* defines in DNA_userdef_types.h */ /* Multires */ char multires_subdiv_type; - char pad3[5]; + char pad3[1]; /* Skeleton generation */ short skgen_resolution; @@ -1375,6 +1354,7 @@ typedef struct Scene { #define R_BAKE_MULTIRES 16 #define R_BAKE_LORES_MESH 32 #define R_BAKE_VCOL 64 +#define R_BAKE_USERSCALE 128 /* bake_normal_space */ #define R_BAKE_SPACE_CAMERA 0 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 0478ff567a0..5befaa87e7f 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -546,7 +546,8 @@ typedef struct MaskSpaceInfo /* draw options */ char draw_flag; char draw_type; - char pad3[6]; + char overlay_mode; + char pad3[5]; } MaskSpaceInfo; /* sseq->mainb */ diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index cae607949a9..317141b14e3 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -40,6 +40,8 @@ blender_include_dirs( set(SRC makesdna.c ../../../../intern/guardedalloc/intern/mallocn.c + ../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c + ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c ) if(WIN32 AND NOT UNIX) @@ -50,11 +52,6 @@ endif() # SRC_DNA_INC is defined in the parent dir -# for mallocn.c -if (WITH_GUARDEDALLOC) - add_definitions(-DWITH_GUARDEDALLOC) -endif() - add_executable(makesdna ${SRC} ${SRC_DNA_INC}) # Output dna.c diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript index 7c3af30ee83..35b4ff262ed 100644 --- a/source/blender/makesdna/intern/SConscript +++ b/source/blender/makesdna/intern/SConscript @@ -36,8 +36,6 @@ cflags = '' defines = [] root_build_dir=normpath(env['BF_BUILDDIR']) -defines.append('WITH_GUARDEDALLOC') - source_files = ['makesdna.c'] header_files = env.Glob('../*.h') diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 89ddb59aab5..2b1a5bc71ff 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -42,8 +42,8 @@ extern "C" { BlenderRNA *RNA_create(void); void RNA_define_free(BlenderRNA *brna); void RNA_free(BlenderRNA *brna); -void RNA_define_verify_sdna(int verify); -void RNA_define_animate_sdna(int animate); +void RNA_define_verify_sdna(bool verify); +void RNA_define_animate_sdna(bool animate); void RNA_init(void); void RNA_exit(void); @@ -225,6 +225,10 @@ const char *RNA_property_typename(PropertyType type); void RNA_identifier_sanitize(char *identifier, int property); +extern const int rna_matrix_dimsize_3x3[]; +extern const int rna_matrix_dimsize_4x4[]; +extern const int rna_matrix_dimsize_4x2[]; + /* max size for dynamic defined type descriptors, * this value is arbitrary */ #define RNA_DYN_DESCR_MAX 240 diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index dfe1ebb3385..5053c8082e9 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -66,6 +66,9 @@ if env['WITH_BF_BULLET']: defs.append('WITH_BULLET') incs += ' #/intern/rigidbody' +if env['WITH_BF_OIIO']: + defs.append('WITH_OPENIMAGEIO') + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index d901897cbc4..9b2fc2c3c4d 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -137,6 +137,8 @@ set(SRC ${DEFSRC} ${APISRC} ../../../../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 ) @@ -164,6 +166,10 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_OPENIMAGEIO) + add_definitions(-DWITH_OPENIMAGEIO) +endif() + if(WITH_IMAGE_TIFF) add_definitions(-DWITH_TIFF) endif() @@ -249,11 +255,6 @@ if(WITH_BULLET) add_definitions(-DWITH_BULLET) endif() -# for mallocn.c -if (WITH_GUARDEDALLOC) - add_definitions(-DWITH_GUARDEDALLOC) -endif() - # Build makesrna executable blender_include_dirs( . diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 10b6a8c8d10..fe6950e62dd 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -82,6 +82,9 @@ if env['WITH_BF_BULLET']: defs.append('WITH_BULLET') incs += ' #/intern/rigidbody' +if env['WITH_BF_OIIO']: + defs.append('WITH_OPENIMAGEIO') + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') @@ -150,8 +153,6 @@ if env['WITH_BF_INTERNATIONAL']: if not env['BF_DEBUG']: defs.append('NDEBUG') -defs.append('WITH_GUARDEDALLOC') - makesrna_tool.Append(CPPDEFINES=defs) makesrna_tool.Append (CPPPATH = Split(incs)) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index a908b403c03..8a4022de104 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -82,7 +82,7 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F fprintf(f, param); \ } (void)0 -static int replace_if_different(char *tmpfile, const char *dep_files[]) +static int replace_if_different(const char *tmpfile, const char *dep_files[]) { /* return 0; *//* use for testing had edited rna */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index b9cbbdb32f7..4b9f7ea32f6 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -471,9 +471,6 @@ static int rna_Armature_is_editmode_get(PointerRNA *ptr) #else -static int rna_matrix_dimsize_4x4[] = {4, 4}; -static int rna_matrix_dimsize_3x3[] = {3, 3}; - static void rna_def_bone_common(StructRNA *srna, int editbone) { PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index f8483d7b221..0c7c2ea1e49 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -505,7 +505,6 @@ static void rna_def_constrainttarget(BlenderRNA *brna) static void rna_def_constraint_childof(BlenderRNA *brna) { - static int rna_matrix_dimsize_4x4[] = {4, 4}; StructRNA *srna; PropertyRNA *prop; diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index b7cdc7a75b3..fe9e9573957 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -574,13 +574,13 @@ void RNA_define_free(BlenderRNA *UNUSED(brna)) DefRNA.error = 0; } -void RNA_define_verify_sdna(int verify) +void RNA_define_verify_sdna(bool verify) { DefRNA.verify = verify; } #ifndef RNA_RUNTIME -void RNA_define_animate_sdna(int animate) +void RNA_define_animate_sdna(bool animate) { DefRNA.animate = animate; } @@ -1253,6 +1253,11 @@ void RNA_def_property_array(PropertyRNA *prop, int length) } } +/* common args for length */ +const int rna_matrix_dimsize_3x3[] = {3, 3}; +const int rna_matrix_dimsize_4x4[] = {4, 4}; +const int rna_matrix_dimsize_4x2[] = {4, 2}; + void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int length[]) { StructRNA *srna = DefRNA.laststruct; diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 439bc51896f..6423763c49c 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -354,15 +354,15 @@ static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_srna(cprop, "GPencilStrokes"); srna = RNA_def_struct(brna, "GPencilStrokes", NULL); RNA_def_struct_sdna(srna, "bGPDframe"); - RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil frames"); + RNA_def_struct_ui_text(srna, "Grease Pencil Frames", "Collection of grease pencil stroke"); func = RNA_def_function(srna, "new", "rna_GPencil_stroke_new"); - RNA_def_function_ui_description(func, "Add a new grease pencil frame"); + RNA_def_function_ui_description(func, "Add a new grease pencil stroke"); parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "", "The newly created stroke"); RNA_def_function_return(func, parm); func = RNA_def_function(srna, "remove", "rna_GPencil_stroke_remove"); - RNA_def_function_ui_description(func, "Remove a grease pencil frame"); + RNA_def_function_ui_description(func, "Remove a grease pencil stroke"); RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to remove"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); @@ -390,7 +390,8 @@ static void rna_def_gpencil_frame(BlenderRNA *brna) /* Frame Number */ prop = RNA_def_property(srna, "frame_number", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "framenum"); - RNA_def_property_range(prop, MINFRAME, MAXFRAME); /* XXX note: this cannot occur on the same frame as another sketch */ + /* XXX note: this cannot occur on the same frame as another sketch */ + RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_ui_text(prop, "Frame Number", "The frame on which this sketch appears"); /* Flags */ @@ -421,7 +422,8 @@ static void rna_def_gpencil_frames_api(BlenderRNA *brna, PropertyRNA *cprop) func = RNA_def_function(srna, "new", "rna_GPencil_frame_new"); RNA_def_function_ui_description(func, "Add a new grease pencil frame"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - parm = RNA_def_int(func, "frame_number", 1, MINFRAME, MAXFRAME, "Frame Number", "The frame on which this sketch appears", MINFRAME, MAXFRAME); + parm = RNA_def_int(func, "frame_number", 1, MINAFRAME, MAXFRAME, "Frame Number", + "The frame on which this sketch appears", MINAFRAME, MAXFRAME); RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "frame", "GPencilFrame", "", "The newly created frame"); RNA_def_function_return(func, parm); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 3fa101a74e4..a25f56f2259 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -130,7 +130,7 @@ void RNA_api_mesh(StructRNA *srna) parm = RNA_def_float(func, "split_angle", M_PI, 0.0f, M_PI, "", "Angle between polys' normals above which an edge is always sharp (180° to disable)", 0.0f, M_PI); - RNA_def_property_subtype(parm, PROP_UNIT_ROTATION); + RNA_def_property_subtype(parm, (PropertySubType)PROP_UNIT_ROTATION); func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split"); RNA_def_function_ui_description(func, "Free split vertex normals"); diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index f01b5af7aaa..6bf7c8926e8 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -321,12 +321,14 @@ static void rna_def_metaball(BlenderRNA *brna) prop = RNA_def_property(srna, "resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "wiresize"); RNA_def_property_range(prop, 0.005f, 10000.0f); + RNA_def_property_ui_range(prop, 0.05f, 1000.0f, 2.5f, 3); RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); prop = RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "rendersize"); RNA_def_property_range(prop, 0.005f, 10000.0f); + RNA_def_property_ui_range(prop, 0.025f, 1000.0f, 2.5f, 3); RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 69addbae1e5..bb8e8d87252 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1377,8 +1377,8 @@ static bNodeType *rna_Node_register_base(Main *bmain, ReportList *reports, Struc nt->initfunc_api = (have_function[3]) ? rna_Node_init : NULL; nt->copyfunc_api = (have_function[4]) ? rna_Node_copy : NULL; nt->freefunc_api = (have_function[5]) ? rna_Node_free : NULL; - nt->uifunc = (have_function[6]) ? rna_Node_draw_buttons : NULL; - nt->uifuncbut = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL; + nt->draw_buttons = (have_function[6]) ? rna_Node_draw_buttons : NULL; + nt->draw_buttons_ex = (have_function[7]) ? rna_Node_draw_buttons_ext : NULL; /* sanitize size values in case not all have been registered */ if (nt->maxwidth < nt->minwidth) @@ -1889,6 +1889,12 @@ static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA ED_node_tag_update_nodetree(bmain, ntree); } +static int rna_NodeSocket_is_output_get(PointerRNA *ptr) +{ + bNodeSocket *sock = ptr->data; + return sock->in_out == SOCK_OUT; +} + static void rna_NodeSocket_link_limit_set(PointerRNA *ptr, int value) { bNodeSocket *sock = ptr->data; @@ -2336,24 +2342,24 @@ static void rna_NodeInternal_update(ID *id, bNode *node) static void rna_NodeInternal_draw_buttons(ID *id, bNode *node, struct bContext *C, struct uiLayout *layout) { - if (node->typeinfo->uifunc) { + if (node->typeinfo->draw_buttons) { PointerRNA ptr; RNA_pointer_create(id, &RNA_Node, node, &ptr); - node->typeinfo->uifunc(layout, C, &ptr); + node->typeinfo->draw_buttons(layout, C, &ptr); } } static void rna_NodeInternal_draw_buttons_ext(ID *id, bNode *node, struct bContext *C, struct uiLayout *layout) { - if (node->typeinfo->uifuncbut) { + if (node->typeinfo->draw_buttons_ex) { PointerRNA ptr; RNA_pointer_create(id, &RNA_Node, node, &ptr); - node->typeinfo->uifuncbut(layout, C, &ptr); + node->typeinfo->draw_buttons_ex(layout, C, &ptr); } - else if (node->typeinfo->uifunc) { + else if (node->typeinfo->draw_buttons) { PointerRNA ptr; RNA_pointer_create(id, &RNA_Node, node, &ptr); - node->typeinfo->uifunc(layout, C, &ptr); + node->typeinfo->draw_buttons(layout, C, &ptr); } } @@ -2847,6 +2853,15 @@ static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRN rna_Node_update(bmain, scene, ptr); } +static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + #else static EnumPropertyItem prop_image_layer_items[] = { @@ -3136,10 +3151,10 @@ static void def_sh_material(StructRNA *srna) static void def_sh_mapping(StructRNA *srna) { static EnumPropertyItem prop_vect_type_items[] = { - {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transforms a texture by inverse mapping the texture coordinate"}, - {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transforms a point"}, - {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transforms a direction vector"}, - {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transforms a normal vector with unit length"}, + {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"}, + {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, + {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"}, + {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"}, {0, NULL, 0, NULL, NULL} }; @@ -3147,7 +3162,7 @@ static void def_sh_mapping(StructRNA *srna) RNA_def_struct_sdna_from(srna, "TexMapping", "storage"); - prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_vect_type_items); RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms"); @@ -3536,9 +3551,9 @@ static void def_sh_tex_coord(StructRNA *srna) static void def_sh_vect_transform(StructRNA *srna) { static EnumPropertyItem prop_vect_type_items[] = { - {SHD_VECT_TRANSFORM_TYPE_POINT, "POINT", 0, "Point", "Transforms a point"}, - {SHD_VECT_TRANSFORM_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transforms a direction vector"}, - {SHD_VECT_TRANSFORM_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transforms a normal vector with unit length"}, + {SHD_VECT_TRANSFORM_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, + {SHD_VECT_TRANSFORM_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"}, + {SHD_VECT_TRANSFORM_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"}, {0, NULL, 0, NULL, NULL} }; @@ -3553,7 +3568,8 @@ static void def_sh_vect_transform(StructRNA *srna) RNA_def_struct_sdna_from(srna, "NodeShaderVectTransform", "storage"); - prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_vect_type_items); RNA_def_property_ui_text(prop, "Type", ""); RNA_def_property_update(prop, 0, "rna_Node_update"); @@ -3689,7 +3705,6 @@ static void def_sh_tangent(StructRNA *srna) static void def_sh_subsurface(StructRNA *srna) { static EnumPropertyItem prop_subsurface_falloff_items[] = { - {SHD_SUBSURFACE_COMPATIBLE, "COMPATIBLE", 0, "Compatible", "Subsurface scattering falloff compatible with previous versions"}, {SHD_SUBSURFACE_CUBIC, "CUBIC", 0, "Cubic", "Simple cubic falloff function"}, {SHD_SUBSURFACE_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", "Normal distribution, multiple can be combined to fit more complex profiles"}, {0, NULL, 0, NULL, NULL} @@ -4359,7 +4374,7 @@ static void def_cmp_scale(StructRNA *srna) RNA_def_property_enum_sdna(prop, NULL, "custom1"); RNA_def_property_enum_items(prop, space_items); RNA_def_property_ui_text(prop, "Space", "Coordinate space to scale relative to"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_CompositorNodeScale_update"); /* expose 2 flags as a enum of 3 items */ prop = RNA_def_property(srna, "frame_method", PROP_ENUM, PROP_NONE); @@ -6172,12 +6187,10 @@ static void rna_def_node_socket(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets"); - prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "in_out"); - RNA_def_property_enum_items(prop, node_socket_in_out_items); - RNA_def_property_enum_default(prop, SOCK_IN); + prop = RNA_def_property(srna, "is_output", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_NodeSocket_is_output_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type"); + RNA_def_property_ui_text(prop, "Is Output", "True if the socket is an output, otherwise input"); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDDEN); @@ -6299,12 +6312,10 @@ static void rna_def_node_socket_interface(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Identifier", "Unique identifier for mapping sockets"); - prop = RNA_def_property(srna, "in_out", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "in_out"); - RNA_def_property_enum_items(prop, node_socket_in_out_items); - RNA_def_property_enum_default(prop, SOCK_IN); + prop = RNA_def_property(srna, "is_output", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_NodeSocket_is_output_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Input or Output", "Input or Output type"); + RNA_def_property_ui_text(prop, "Is Output", "True if the socket is an output, otherwise input"); /* registration */ prop = RNA_def_property(srna, "bl_socket_idname", PROP_STRING, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 3589610214b..3f366dfbcfa 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -908,6 +908,15 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr) WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL); } +static char *rna_MaterialSlot_path(PointerRNA *ptr) +{ + Object *ob = (Object *)ptr->id.data; + int index = (Material **)ptr->data - ob->mat; + + /* from armature... */ + return BLI_sprintfN("material_slots[%d]", index); +} + /* why does this have to be so complicated?, can't all this crap be * moved to in BGE conversion function? - Campbell * * @@ -1451,8 +1460,6 @@ int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr) #else -static int rna_matrix_dimsize_4x4[] = {4, 4}; - static void rna_def_vertex_group(BlenderRNA *brna) { StructRNA *srna; @@ -1553,6 +1560,8 @@ static void rna_def_material_slot(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name", "Material slot name"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_struct_name_property(srna, prop); + + RNA_def_struct_path_func(srna, "rna_MaterialSlot_path"); } static void rna_def_object_game_settings(BlenderRNA *brna) @@ -2766,11 +2775,14 @@ static void rna_def_object_base(BlenderRNA *brna) void RNA_def_object(BlenderRNA *brna) { rna_def_object(brna); + + RNA_define_animate_sdna(false); rna_def_object_game_settings(brna); rna_def_object_base(brna); rna_def_vertex_group(brna); rna_def_material_slot(brna); rna_def_dupli_object(brna); + RNA_define_animate_sdna(true); } #endif diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 25ca231e58d..0f71e26b687 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -430,8 +430,6 @@ void RNA_api_object(StructRNA *srna) {0, NULL, 0, NULL, NULL} }; - static int rna_matrix_dimsize_4x4[] = {4, 4}; - #ifndef NDEBUG static EnumPropertyItem mesh_dm_info_items[] = { {0, "SOURCE", 0, "Source", "Source mesh"}, diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 146ba6e4b7d..33ae256c042 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -1540,8 +1540,6 @@ static void rna_def_softbody(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - const int matrix_dimsize[] = {3, 3}; - static EnumPropertyItem collision_type_items[] = { {SBC_MODE_MANUAL, "MANUAL", 0, "Manual", "Manual adjust"}, @@ -1784,12 +1782,12 @@ static void rna_def_softbody(BlenderRNA *brna) /* matrix */ prop = RNA_def_property(srna, "rotation_estimate", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "lrot"); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3); RNA_def_property_ui_text(prop, "Rot Matrix", "Estimated rotation matrix"); prop = RNA_def_property(srna, "scale_estimate", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "lscale"); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3); RNA_def_property_ui_text(prop, "Scale Matrix", "Estimated scale matrix"); /***********************************************************************************/ diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 58217206add..9c4e7f034cb 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -742,9 +742,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) static float default_quat[4] = {1, 0, 0, 0}; /* default quaternion values */ static float default_axisAngle[4] = {0, 0, 1, 0}; /* default axis-angle rotation values */ static float default_scale[3] = {1, 1, 1}; /* default scale values */ - - const int matrix_dimsize[] = {4, 4}; - + StructRNA *srna; PropertyRNA *prop; @@ -841,13 +839,13 @@ static void rna_def_pose_channel(BlenderRNA *brna) /* transform matrices - should be read-only since these are set directly by AnimSys evaluation */ prop = RNA_def_property(srna, "matrix_channel", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "chan_mat"); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Channel Matrix", "4x4 matrix, before constraints"); /* writable because it touches loc/scale/rot directly */ prop = RNA_def_property(srna, "matrix_basis", PROP_FLOAT, PROP_MATRIX); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_ui_text(prop, "Basis Matrix", "Alternative access to location/scale/rotation relative to the parent and own rest bone"); RNA_def_property_float_funcs(prop, "rna_PoseChannel_matrix_basis_get", "rna_PoseChannel_matrix_basis_set", NULL); @@ -857,7 +855,7 @@ static void rna_def_pose_channel(BlenderRNA *brna) /* final matrix */ prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "pose_mat"); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_float_funcs(prop, NULL, "rna_PoseChannel_matrix_set", NULL); RNA_def_property_ui_text(prop, "Pose Matrix", "Final 4x4 matrix after constraints and drivers are applied (object space)"); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 5b809a51705..7ebbcf7b39b 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -66,14 +66,14 @@ static void engine_tag_update(RenderEngine *engine) static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene) { - return IMB_colormanagement_support_glsl_draw(&scene->view_settings, true); + return IMB_colormanagement_support_glsl_draw(&scene->view_settings); } static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene) { IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, - false, true); + false); } static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine)) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index fcaabaa3e65..4d35acc84a0 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -219,6 +219,13 @@ EnumPropertyItem snap_uv_element_items[] = { # define R_IMF_ENUM_TIFF #endif +#ifdef WITH_OPENIMAGEIO +# define R_IMF_ENUM_PSD {R_IMF_IMTYPE_PSD, "PSD", ICON_FILE_IMAGE, "Photosp PSD", \ + "Output image in Photoshop PSD format"}, +#else +# define R_IMF_ENUM_PSD +#endif + #define IMAGE_TYPE_ITEMS_IMAGE_ONLY \ R_IMF_ENUM_BMP \ @@ -236,6 +243,7 @@ EnumPropertyItem snap_uv_element_items[] = { R_IMF_ENUM_EXR \ R_IMF_ENUM_HDR \ R_IMF_ENUM_TIFF \ + R_IMF_ENUM_PSD \ EnumPropertyItem image_only_type_items[] = { @@ -932,7 +940,7 @@ static void rna_RenderSettings_qtcodecsettings_codecType_set(PointerRNA *ptr, in settings->codecType = quicktime_videocodecType_from_rnatmpvalue(value); } -static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *C, PointerRNA *ptr, +static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_codecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) { EnumPropertyItem *item = NULL; @@ -971,7 +979,7 @@ static void rna_RenderSettings_qtcodecsettings_audiocodecType_set(PointerRNA *pt settings->audiocodecType = quicktime_audiocodecType_from_rnatmpvalue(value); } -static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *C, PointerRNA *ptr, +static EnumPropertyItem *rna_RenderSettings_qtcodecsettings_audiocodecType_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) { EnumPropertyItem *item = NULL; @@ -1541,7 +1549,8 @@ static void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value { FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data; - lineset->linestyle->id.us--; + if (lineset->linestyle) + lineset->linestyle->id.us--; lineset->linestyle = (FreestyleLineStyle *)value.data; lineset->linestyle->id.us++; } @@ -1580,14 +1589,12 @@ static void rna_def_transform_orientation(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - const int matrix_dimsize[] = {3, 3}; srna = RNA_def_struct(brna, "TransformOrientation", NULL); prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "mat"); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_3x3); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); @@ -2072,8 +2079,8 @@ static void rna_def_statvis(BlenderRNA *brna) {SCE_STATVIS_OVERHANG, "OVERHANG", 0, "Overhang", ""}, {SCE_STATVIS_THICKNESS, "THICKNESS", 0, "Thickness", ""}, {SCE_STATVIS_INTERSECT, "INTERSECT", 0, "Intersect", ""}, - {SCE_STATVIS_DISTORT, "DISTORT", 0, "Distort", ""}, - {SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""}, + {SCE_STATVIS_DISTORT, "DISTORT", 0, "Distortion", ""}, + {SCE_STATVIS_SHARP, "SHARP", 0, "Sharp", ""}, {0, NULL, 0, NULL, NULL}}; srna = RNA_def_struct(brna, "MeshStatVis", NULL); @@ -4079,6 +4086,8 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {RE_BAKE_NORMALS, "NORMALS", 0, "Normals", "Bake normals"}, {RE_BAKE_TEXTURE, "TEXTURE", 0, "Textures", "Bake textures"}, {RE_BAKE_DISPLACEMENT, "DISPLACEMENT", 0, "Displacement", "Bake displacement"}, + {RE_BAKE_DERIVATIVE, "DERIVATIVE", 0, "Derivative", "Bake derivative map"}, + {RE_BAKE_VERTEX_COLORS, "VERTEX_COLORS", 0, "Vertex Colors", "Bake vertex colors"}, {RE_BAKE_EMIT, "EMIT", 0, "Emission", "Bake Emit values (glow)"}, {RE_BAKE_ALPHA, "ALPHA", 0, "Alpha", "Bake Alpha values (transparency)"}, {RE_BAKE_MIRROR_INTENSITY, "MIRROR_INTENSITY", 0, "Mirror Intensity", "Bake Mirror values"}, @@ -4665,6 +4674,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna) "Bake to vertex colors instead of to a UV-mapped image"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + prop = RNA_def_property(srna, "use_bake_user_scale", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_USERSCALE); + RNA_def_property_ui_text(prop, "User scale", "Use a user scale for the derivative map"); + + prop = RNA_def_property(srna, "bake_user_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "bake_user_scale"); + RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_ui_text(prop, "Scale", + "Instead of automatically normalizing to 0..1, " + "apply a user scale to the derivative map"); + /* stamp */ prop = RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 375b31e0586..ae6c5e71e6e 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -142,12 +142,12 @@ static void rna_Scene_collada_export( int use_object_instantiation, int sort_by_name, int export_transformation_type, - int second_life) + int open_sim) { collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, include_shapekeys, deform_bones_only, active_uv_only, include_uv_textures, include_material_textures, - use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, second_life); + use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, open_sim); } #endif @@ -218,7 +218,7 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export"); parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data"); parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); - parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life"); + parm = RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds"); parm = RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, "Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 0f55da236c9..73f0d33257c 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -406,23 +406,12 @@ static void rna_SpaceView3D_layer_update(Main *bmain, Scene *UNUSED(scene), Poin DAG_on_visible_update(bmain, FALSE); } -static void rna_SpaceView3D_viewport_shade_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_SpaceView3D_viewport_shade_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { View3D *v3d = (View3D *)(ptr->data); ScrArea *sa = rna_area_from_space(ptr); - if (v3d->drawtype != OB_RENDER) { - ARegion *ar; - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d && rv3d->render_engine) { - RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; - } - } - } + ED_view3d_shade_update(bmain, v3d, sa); } static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -1347,6 +1336,12 @@ static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *m { PropertyRNA *prop; + static EnumPropertyItem overlay_mode_items[] = { + {MASK_OVERLAY_ALPHACHANNEL, "ALPHACHANNEL", ICON_NONE, "Alpha Channel", "Show alpha channel of the mask"}, + {MASK_OVERLAY_COMBINED, "COMBINED", ICON_NONE, "Combined", "Combine space background image with the mask"}, + {0, NULL, 0, NULL, NULL} + }; + prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "mask_info.mask"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -1365,6 +1360,17 @@ static void rna_def_space_mask_info(StructRNA *srna, int noteflag, const char *m RNA_def_property_boolean_sdna(prop, NULL, "mask_info.draw_flag", MASK_DRAWFLAG_SMOOTH); RNA_def_property_ui_text(prop, "Draw Smooth Splines", ""); RNA_def_property_update(prop, noteflag, NULL); + + prop = RNA_def_property(srna, "show_mask_overlay", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mask_info.draw_flag", MASK_DRAWFLAG_OVERLAY); + RNA_def_property_ui_text(prop, "Show Mask Overlay", ""); + RNA_def_property_update(prop, noteflag, NULL); + + prop = RNA_def_property(srna, "mask_overlay_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mask_info.overlay_mode"); + RNA_def_property_enum_items(prop, overlay_mode_items); + RNA_def_property_ui_text(prop, "Overlay Mode", "Overlay mode of rasterized mask"); + RNA_def_property_update(prop, noteflag, NULL); } static void rna_def_space_image_uv(BlenderRNA *brna) @@ -1695,7 +1701,6 @@ static void rna_def_space_view3d(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - const int matrix_dimsize[] = {4, 4}; static EnumPropertyItem pivot_items[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", @@ -2120,12 +2125,12 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop = RNA_def_property(srna, "perspective_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "persmat"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */ - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_ui_text(prop, "Perspective Matrix", "Current perspective matrix of the 3D region"); prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "viewmat"); - RNA_def_property_multi_array(prop, 2, matrix_dimsize); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_float_funcs(prop, NULL, "rna_RegionView3D_view_matrix_set", NULL); RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix of the 3D region"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 6aee4486cf5..a26272b34ce 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -496,10 +496,10 @@ static void rna_def_texmapping(BlenderRNA *brna) }; static EnumPropertyItem prop_vect_type_items[] = { - {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transforms a texture by inverse mapping the texture coordinate"}, - {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transforms a point"}, - {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transforms a direction vector"}, - {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transforms a normal vector with unit length"}, + {TEXMAP_TYPE_TEXTURE, "TEXTURE", 0, "Texture", "Transform a texture by inverse mapping the texture coordinate"}, + {TEXMAP_TYPE_POINT, "POINT", 0, "Point", "Transform a point"}, + {TEXMAP_TYPE_VECTOR, "VECTOR", 0, "Vector", "Transform a direction vector"}, + {TEXMAP_TYPE_NORMAL, "NORMAL", 0, "Normal", "Transform a normal vector with unit length"}, {0, NULL, 0, NULL, NULL} }; @@ -517,7 +517,7 @@ static void rna_def_texmapping(BlenderRNA *brna) srna = RNA_def_struct(brna, "TexMapping", NULL); RNA_def_struct_ui_text(srna, "Texture Mapping", "Texture coordinate mapping settings"); - prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "vector_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_vect_type_items); RNA_def_property_ui_text(prop, "Type", "Type of vector that the mapping transforms"); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 2b3cf58d452..97f5c24dc56 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -711,9 +711,6 @@ static EnumPropertyItem pattern_match_items[] = { {0, NULL, 0, NULL, NULL} }; -static int rna_matrix_dimsize_4x4[] = {4, 4}; -static int rna_matrix_dimsize_4x2[] = {4, 2}; - static void rna_def_trackingSettings(BlenderRNA *brna) { StructRNA *srna; diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c index 134402c00e1..8041a2e56e9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_scale.c +++ b/source/blender/nodes/composite/nodes/node_composite_scale.c @@ -45,12 +45,31 @@ static bNodeSocketTemplate cmp_node_scale_out[] = { { -1, 0, "" } }; +static void node_composite_update_scale(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock; + bool use_xy_scale = ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_ABSOLUTE); + + /* Only show X/Y scale factor inputs for modes using them! */ + for (sock = node->inputs.first; sock; sock = sock->next) { + if (STREQ(sock->name, "X") || STREQ(sock->name, "Y")) { + if (use_xy_scale) { + sock->flag &= ~SOCK_UNAVAIL; + } + else { + sock->flag |= SOCK_UNAVAIL; + } + } + } +} + void register_node_type_cmp_scale(void) { static bNodeType ntype; cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, 0); node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out); + node_type_update(&ntype, node_composite_update_scale, NULL); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c index fad1a69d364..9956fd712c8 100644 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.c +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c @@ -41,6 +41,11 @@ static bNodeSocketTemplate sh_node_gamma_out[] = { { -1, 0, "" } }; +static int node_shader_gpu_gamma(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_gamma", in, out); +} + void register_node_type_sh_gamma(void) { static bNodeType ntype; @@ -50,6 +55,7 @@ void register_node_type_sh_gamma(void) node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_gamma); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c index 82444caadb8..cff4a039602 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mapping.c +++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c @@ -71,7 +71,7 @@ static void node_shader_exec_mapping(void *UNUSED(data), int UNUSED(thread), bNo static void node_shader_init_mapping(bNodeTree *UNUSED(ntree), bNode *node) { - node->storage = add_tex_mapping(TEXMAP_TYPE_TEXTURE); + node->storage = add_tex_mapping(TEXMAP_TYPE_POINT); } static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c index 480d285af6c..12da301d090 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c @@ -51,7 +51,7 @@ static bNodeSocketTemplate sh_node_tex_brick_out[] = { static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexBrick *tex = MEM_callocN(sizeof(NodeTexBrick), "NodeTexBrick"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->offset = 0.5f; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c index 82125f3ea02..725b5654523 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_checker.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_checker.c @@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_checker_out[] = { static void node_shader_init_tex_checker(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexChecker *tex = MEM_callocN(sizeof(NodeTexChecker), "NodeTexChecker"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); node->storage = tex; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index 923684304bf..5e6471eab77 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_environment_out[] = { static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->color_space = SHD_COLORSPACE_COLOR; tex->projection = SHD_PROJ_EQUIRECTANGULAR; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c index 00dd45df7b0..c3ef897b1ad 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_gradient.c @@ -43,7 +43,7 @@ static bNodeSocketTemplate sh_node_tex_gradient_out[] = { static void node_shader_init_tex_gradient(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexGradient *tex = MEM_callocN(sizeof(NodeTexGradient), "NodeTexGradient"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->gradient_type = SHD_BLEND_LINEAR; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 935c0c618c7..1b705e12daf 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_tex_image_out[] = { static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->color_space = SHD_COLORSPACE_COLOR; tex->iuser.frames = 1; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c index c043484d550..b9339bc483f 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_magic.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_magic.c @@ -45,7 +45,7 @@ static bNodeSocketTemplate sh_node_tex_magic_out[] = { static void node_shader_init_tex_magic(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexMagic *tex = MEM_callocN(sizeof(NodeTexMagic), "NodeTexMagic"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->depth = 2; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index 33ae2dbc8c2..2b5d5e12420 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -49,7 +49,7 @@ static bNodeSocketTemplate sh_node_tex_musgrave_out[] = { static void node_shader_init_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexMusgrave *tex = MEM_callocN(sizeof(NodeTexMusgrave), "NodeTexMusgrave"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->musgrave_type = SHD_MUSGRAVE_FBM; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c index 9e63e0278e6..36e26925501 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c @@ -46,7 +46,7 @@ static bNodeSocketTemplate sh_node_tex_noise_out[] = { static void node_shader_init_tex_noise(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexNoise *tex = MEM_callocN(sizeof(NodeTexNoise), "NodeTexNoise"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); node->storage = tex; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index 0c842207c05..22061979b12 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -42,7 +42,7 @@ static bNodeSocketTemplate sh_node_tex_sky_out[] = { static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexSky *tex = MEM_callocN(sizeof(NodeTexSky), "NodeTexSky"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->sun_direction[0] = 0.0f; tex->sun_direction[1] = 0.0f; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c index 5ace85506a6..f75c05601aa 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.c @@ -44,7 +44,7 @@ static bNodeSocketTemplate sh_node_tex_voronoi_out[] = { static void node_shader_init_tex_voronoi(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexVoronoi *tex = MEM_callocN(sizeof(NodeTexVoronoi), "NodeTexVoronoi"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->coloring = SHD_VORONOI_INTENSITY; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c index a189d927673..be7df85fbee 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_wave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_wave.c @@ -47,7 +47,7 @@ static bNodeSocketTemplate sh_node_tex_wave_out[] = { static void node_shader_init_tex_wave(bNodeTree *UNUSED(ntree), bNode *node) { NodeTexWave *tex = MEM_callocN(sizeof(NodeTexWave), "NodeTexWave"); - default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_TEXTURE); + default_tex_mapping(&tex->base.tex_mapping, TEXMAP_TYPE_POINT); default_color_mapping(&tex->base.color_mapping); tex->wave_type = SHD_WAVE_BANDS; diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index aae0f926e81..ef5d26dccdc 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -174,6 +174,10 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +if(WITH_OPENIMAGEIO) + add_definitions(-DWITH_OPENIMAGEIO) +endif() + if(WITH_IMAGE_OPENJPEG) add_definitions(-DWITH_OPENJPEG) endif() diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 65b7bf62032..efee9b13d58 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -177,14 +177,17 @@ PyObject *PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args) } /* identifiers */ - srna = srna_from_self(macro, "Macro Define:"); - macroname = RNA_struct_identifier(srna); + srna = pyrna_struct_as_srna((PyObject *)macro, false, "Macro Define:"); + if (srna == NULL) { + return NULL; + } + macroname = RNA_struct_identifier(srna); ot = WM_operatortype_find(macroname, true); if (!ot) { PyErr_Format(PyExc_ValueError, - "Macro Define: '%s' is not a valid macro or hasn't been registered yet", + "Macro Define: '%s' is not a valid macro", macroname); return NULL; } diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 6bb3031f0a3..2a874f51fd4 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -707,7 +707,7 @@ PyTypeObject euler_Type = { * (i.e. it was allocated elsewhere by MEM_mallocN()) * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON * (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *Euler_CreatePyObject(float *eul, const short order, int type, PyTypeObject *base_type) +PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type) { EulerObject *self; diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h index 355d0ed1810..62fb83ef234 100644 --- a/source/blender/python/mathutils/mathutils_Euler.h +++ b/source/blender/python/mathutils/mathutils_Euler.h @@ -43,7 +43,7 @@ typedef struct { * blender (stored in blend_data). This is an either/or struct not both */ /* prototypes */ -PyObject *Euler_CreatePyObject(float *eul, const short order, int type, PyTypeObject *base_type); +PyObject *Euler_CreatePyObject(float eul[3], const short order, int type, PyTypeObject *base_type); PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order, unsigned char cb_type, unsigned char cb_subtype); diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index b0b818faaa0..e13136057c8 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -1246,7 +1246,7 @@ PyTypeObject quaternion_Type = { * (i.e. it was allocated elsewhere by MEM_mallocN()) * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON * (i.e. it must be created here with PyMEM_malloc())*/ -PyObject *Quaternion_CreatePyObject(float *quat, int type, PyTypeObject *base_type) +PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type) { QuaternionObject *self; diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h index be3566934a4..36036c6d3fa 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.h +++ b/source/blender/python/mathutils/mathutils_Quaternion.h @@ -40,7 +40,7 @@ typedef struct { * blender (stored in blend_data). This is an either/or struct not both */ /* prototypes */ -PyObject *Quaternion_CreatePyObject(float *quat, int type, PyTypeObject *base_type); +PyObject *Quaternion_CreatePyObject(float quat[4], int type, PyTypeObject *base_type); PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user, unsigned char cb_type, unsigned char cb_subtype); diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 8a5a8446ac6..6b2da9ca593 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1853,7 +1853,7 @@ static PyObject *Vector_neg(VectorObject *self) } /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */ -static double vec_magnitude_nosqrt(float *data, int size) +static double vec_magnitude_nosqrt(const float *data, int size) { /* return (double)sqrt(dot);*/ /* warning, line above removed because we are not using the length, @@ -2940,10 +2940,10 @@ PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, int size, unsigned char cb return (PyObject *)self; } -PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type) +PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type) { VectorObject *vect_ob; - vect_ob = (VectorObject *)Vector_CreatePyObject(vec, size, Py_WRAP, base_type); + vect_ob = (VectorObject *)Vector_CreatePyObject((float *)vec, size, Py_WRAP, base_type); vect_ob->wrapped = Py_NEW; return (PyObject *)vect_ob; diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h index 18d89e73734..2074270670a 100644 --- a/source/blender/python/mathutils/mathutils_Vector.h +++ b/source/blender/python/mathutils/mathutils_Vector.h @@ -41,6 +41,6 @@ typedef struct { PyObject *Vector_CreatePyObject(float *vec, const int size, const int type, PyTypeObject *base_type); PyObject *Vector_CreatePyObject_cb(PyObject *user, int size, unsigned char cb_type, unsigned char subtype); -PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type); +PyObject *Vector_CreatePyObject_alloc(const float *vec, const int size, PyTypeObject *base_type); -#endif /* __MATHUTILS_VECTOR_H__ */ +#endif /* __MATHUTILS_VECTOR_H__ */ diff --git a/source/blender/render/extern/include/RE_multires_bake.h b/source/blender/render/extern/include/RE_multires_bake.h index 04cfe55e3a3..c1c5fc4a04d 100644 --- a/source/blender/render/extern/include/RE_multires_bake.h +++ b/source/blender/render/extern/include/RE_multires_bake.h @@ -37,21 +37,26 @@ struct MultiresBakeRender; typedef struct MultiresBakeRender { DerivedMesh *lores_dm, *hires_dm; - int simple, lvl, tot_lvl, bake_filter; - short mode, use_lores_mesh; + bool simple; + int bake_filter; /* Bake-filter, aka margin */ + int lvl, tot_lvl; + short mode; + bool use_lores_mesh; /* Use low-resolution mesh when baking displacement maps */ - int number_of_rays; - float bias; + int number_of_rays; /* Number of rays to be cast when doing AO baking */ + float bias; /* Bias between object and start ray point when doing AO baking */ int tot_obj, tot_image; ListBase image; int baked_objects, baked_faces; - int raytrace_structure; - int octree_resolution; - int threads; - + int raytrace_structure; /* Optimization structure to be used for AO baking */ + int octree_resolution; /* Reslution of octotree when using octotree optimization structure */ + int threads; /* Number of threads to be used for baking */ + + float user_scale; /* User scale used to scale displacement when baking derivative map. */ + short *stop; short *do_update; float *progress; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 73a89ad884f..79826a63690 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -249,7 +249,7 @@ void RE_MergeFullSample(struct Render *re, struct Main *bmain, struct Scene *sce /* ancient stars function... go away! */ void RE_make_stars(struct Render *re, struct Scene *scenev3d, void (*initfunc)(void), - void (*vertexfunc)(float *), void (*termfunc)(void)); + void (*vertexfunc)(const float *), void (*termfunc)(void)); /* display and event callbacks */ void RE_display_init_cb (struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)); @@ -281,6 +281,8 @@ int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); #define RE_BAKE_MIRROR_INTENSITY 10 #define RE_BAKE_ALPHA 11 #define RE_BAKE_EMIT 12 +#define RE_BAKE_DERIVATIVE 13 +#define RE_BAKE_VERTEX_COLORS 14 void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, const int type, struct Object *actob); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 19ddfb7a13d..baec1a74721 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -213,6 +213,9 @@ int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob struct Image *RE_bake_shade_get_image(void); void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter); void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max); +float RE_bake_make_derivative(struct ImBuf *ibuf, float *heights_buffer, const char *mask, + const float height_min, const float height_max, + const float fmult); #define BAKE_RESULT_OK 0 #define BAKE_RESULT_NO_OBJECTS 1 diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 42dc9bcdfb2..3d97eda50d9 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -236,7 +236,6 @@ struct Render struct Object *excludeob; ListBase render_volumes_inside; ListBase volumes; - ListBase volume_precache_parts; #ifdef WITH_FREESTYLE struct Main freestyle_bmain; @@ -621,6 +620,7 @@ typedef struct LampRen { #define R_BAKE_TRACE 32 #define R_BAKING 64 #define R_ANIMATION 128 +#define R_NEED_VCOL 256 /* vlakren->flag (vlak = face in dutch) char!!! */ #define R_SMOOTH 1 diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c index 6e70e670ff8..72e47f89bb2 100644 --- a/source/blender/render/intern/source/bake.c +++ b/source/blender/render/intern/source/bake.c @@ -168,7 +168,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua else { if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ shi->r = shi->g = shi->b = 1.0f; - + shade_input_set_shade_texco(shi); /* only do AO for a full bake (and obviously AO bakes) @@ -260,12 +260,16 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua copy_v3_fl(shr.combined, shi->emit); shr.alpha = 1.0f; } + else if (bs->type == RE_BAKE_VERTEX_COLORS) { + copy_v3_v3(shr.combined, shi->vcol); + shr.alpha = shi->vcol[3]; + } } if (bs->rect_float && !bs->vcol) { float *col = bs->rect_float + 4 * (bs->rectx * y + x); copy_v3_v3(col, shr.combined); - if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE) { + if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE || bs->type == RE_BAKE_VERTEX_COLORS) { col[3] = shr.alpha; } else { @@ -294,7 +298,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua rgb_float_to_uchar(col, shr.combined); } - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { + if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE, RE_BAKE_VERTEX_COLORS)) { col[3] = FTOCHAR(shr.alpha); } else { @@ -553,7 +557,7 @@ static void do_bake_shade(void *handle, int x, int y, float u, float v) } } - if (bs->type == RE_BAKE_DISPLACEMENT) { + if (ELEM(bs->type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { if (hit) bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y); else @@ -688,7 +692,7 @@ static int get_next_bake_face(BakeShade *bs) if (R.r.bake_flag & R_BAKE_CLEAR) { if (R.r.bake_mode == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? nor_alpha : nor_solid); - else if (R.r.bake_mode == RE_BAKE_DISPLACEMENT) + else if (ELEM(R.r.bake_mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? disp_alpha : disp_solid); else IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); @@ -984,8 +988,10 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up use_mask = true; /* do we need buffer to store displacements */ - if (type == RE_BAKE_DISPLACEMENT) { - if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) { + if (ELEM(type, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE)) { + if (((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) || + (type == RE_BAKE_DERIVATIVE)) + { use_displacement_buffer = true; use_mask = true; } @@ -1089,8 +1095,15 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up userdata = (BakeImBufuserData *)ibuf->userdata; if (userdata) { if (use_displacement_buffer) { - RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - displacement_min, displacement_max); + if (type == RE_BAKE_DERIVATIVE) { + float user_scale = (R.r.bake_flag & R_BAKE_USERSCALE) ? R.r.bake_user_scale : -1.0f; + RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + displacement_min, displacement_max, user_scale); + } + else { + RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + displacement_min, displacement_max); + } } RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter); @@ -1124,3 +1137,176 @@ struct Image *RE_bake_shade_get_image(void) return R.bakebuf; } +/* **************** Derivative Maps Baker **************** */ + +static void add_single_heights_margin(const ImBuf *ibuf, const char *mask, float *heights_buffer) +{ + int x ,y; + + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + int index = ibuf->x * y + x; + + /* If unassigned pixel, look for neighbors. */ + if (mask[index] != FILTER_MASK_USED) { + float height_acc = 0; + int denom = 0; + int i, j; + + for (j = -1; j <= 1; j++) + for (i = -1; i <= 1; i++) { + int w = (i == 0 ? 1 : 0) + (j == 0 ? 1 : 0) + 1; + + if (i != 0 || j != 0) { + int index2 = 0; + int x0 = x + i; + int y0 = y + j; + + CLAMP(x0, 0, ibuf->x - 1); + CLAMP(y0, 0, ibuf->y - 1); + + index2 = ibuf->x * y0 + x0; + + if (mask[index2] == FILTER_MASK_USED) { + height_acc += w * heights_buffer[index2]; + denom += w; + } + } + } + + /* Insert final value. */ + if (denom > 0) { + heights_buffer[index] = height_acc / denom; + } + } + } + } +} + +/* returns user-scale */ +float RE_bake_make_derivative(ImBuf *ibuf, float *heights_buffer, const char *mask, + const float height_min, const float height_max, + const float fmult) +{ + const float delta_height = height_max - height_min; + const float denom = delta_height > 0.0f ? (8 * delta_height) : 1.0f; + bool auto_range_fit = fmult <= 0.0f; + float max_num_deriv = -1.0f; + int x, y, index; + + /* Need a single margin to calculate good derivatives. */ + add_single_heights_margin(ibuf, mask, heights_buffer); + + if (auto_range_fit) { + /* If automatic range fitting is enabled. */ + for (y = 0; y < ibuf->y; y++) { + const int Yu = y == (ibuf->y - 1) ? (ibuf->y - 1) : (y+1); + const int Yc = y; + const int Yd = y == 0 ? 0 : (y - 1); + + for (x= 0; x < ibuf->x; x++) { + const int Xl = x == 0 ? 0 : (x - 1); + const int Xc = x; + const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1); + + const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl]; + const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl]; + const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl]; + + const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl]; + const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc]; + const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr]; + + /* This corresponds to using the sobel kernel on the heights buffer + * to obtain the derivative multiplied by 8. + */ + const float deriv_x = Hu + 2 * Hcy + Hd; + const float deriv_y = Hr + 2 * Hcx + Hl; + + /* early out */ + index = ibuf->x * y + x; + if (mask[index] != FILTER_MASK_USED) { + continue; + } + + /* Widen bound. */ + if (fabsf(deriv_x) > max_num_deriv) { + max_num_deriv = fabsf(deriv_x); + } + + if (fabsf(deriv_y) > max_num_deriv) { + max_num_deriv = fabsf(deriv_y); + } + } + } + } + + /* Output derivatives. */ + auto_range_fit &= (max_num_deriv > 0); + for (y = 0; y < ibuf->y; y++) { + const int Yu= y==(ibuf->y-1) ? (ibuf->y-1) : (y+1); + const int Yc= y; + const int Yd= y==0 ? 0 : (y-1); + + for(x= 0; x<ibuf->x; x++) { + const int Xl = x == 0 ? 0 : (x - 1); + const int Xc = x; + const int Xr = x == (ibuf->x - 1) ? (ibuf->x - 1) : (x + 1); + + const float Hcy = heights_buffer[Yc * ibuf->x + Xr] - heights_buffer[Yc * ibuf->x + Xl]; + const float Hu = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yu * ibuf->x + Xl]; + const float Hd = heights_buffer[Yd * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xl]; + + const float Hl = heights_buffer[Yu * ibuf->x + Xl] - heights_buffer[Yd * ibuf->x + Xl]; + const float Hcx = heights_buffer[Yu * ibuf->x + Xc] - heights_buffer[Yd * ibuf->x + Xc]; + const float Hr = heights_buffer[Yu * ibuf->x + Xr] - heights_buffer[Yd * ibuf->x + Xr]; + + /* This corresponds to using the sobel kernel on the heights buffer + * to obtain the derivative multiplied by 8. + */ + float deriv_x = Hu + 2 * Hcy + Hd; + float deriv_y = Hr + 2 * Hcx + Hl; + + /* Early out. */ + index = ibuf->x * y + x; + if (mask[index] != FILTER_MASK_USED){ + continue; + } + + if (auto_range_fit) { + deriv_x /= max_num_deriv; + deriv_y /= max_num_deriv; + } else { + deriv_x *= (fmult / denom); + deriv_y *= (fmult / denom); + } + + deriv_x = deriv_x * 0.5f + 0.5f; + deriv_y = deriv_y * 0.5f + 0.5f; + + /* Clamp. */ + CLAMP(deriv_x, 0.0f, 1.0f); + CLAMP(deriv_y, 0.0f, 1.0f); + + /* Write out derivatives. */ + if (ibuf->rect_float) { + float *rrgbf = ibuf->rect_float + index * 4; + + rrgbf[0] = deriv_x; + rrgbf[1] = deriv_y; + rrgbf[2] = 0.0f; + rrgbf[3] = 1.0f; + } else { + char *rrgb = (char*)ibuf->rect + index * 4; + + rrgb[0] = FTOCHAR(deriv_x); + rrgb[1] = FTOCHAR(deriv_y); + rrgb[2] = 0; + rrgb[3] = 255; + } + } + } + + /* Eeturn user-scale (for rendering). */ + return auto_range_fit ? (max_num_deriv / denom) : (fmult > 0.0f ? (1.0f / fmult) : 0.0f); +} diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index a0104a30d0e..18f658fb169 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -167,7 +167,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h */ void RE_make_stars(Render *re, Scene *scenev3d, void (*initfunc)(void), - void (*vertexfunc)(float *), void (*termfunc)(void)) + void (*vertexfunc)(const float *), void (*termfunc)(void)) { extern unsigned char hash[512]; ObjectRen *obr= NULL; @@ -5982,7 +5982,9 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned * RE_BAKE_NORMALS:for baking, no lamps and only selected objects * RE_BAKE_AO: for baking, no lamps, but all objects * RE_BAKE_TEXTURE:for baking, no lamps, only selected objects + * RE_BAKE_VERTEX_COLORS:for baking, no lamps, only selected objects * RE_BAKE_DISPLACEMENT:for baking, no lamps, only selected objects + * RE_BAKE_DERIVATIVE:for baking, no lamps, only selected objects * RE_BAKE_SHADOW: for baking, only shadows, but all objects */ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, const int type, Object *actob) @@ -5990,8 +5992,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, Object *camera; float mat[4][4]; float amb[3]; - const short onlyselected= !ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO); - const short nolamps= ELEM3(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT); + const short onlyselected= !ELEM5(type, RE_BAKE_LIGHT, RE_BAKE_ALL, RE_BAKE_SHADOW, RE_BAKE_AO, RE_BAKE_VERTEX_COLORS); + const short nolamps= ELEM5(type, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS); re->main= bmain; re->scene= scene; @@ -6009,8 +6011,11 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, if (type==RE_BAKE_NORMALS && re->r.bake_normal_space==R_BAKE_SPACE_TANGENT) re->flag |= R_NEED_TANGENT; - - if (!actob && ELEM4(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT)) { + + if (type==RE_BAKE_VERTEX_COLORS) + re->flag |= R_NEED_VCOL; + + if (!actob && ELEM6(type, RE_BAKE_LIGHT, RE_BAKE_NORMALS, RE_BAKE_TEXTURE, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE, RE_BAKE_VERTEX_COLORS)) { re->r.mode &= ~R_SHADOW; re->r.mode &= ~R_RAYTRACE; } diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index c5e4f97c6bc..bfc13bf6151 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -799,7 +799,7 @@ static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, afdata /* table of (exp(ar) - exp(a)) / (1 - exp(a)) for r in range [0, 1] and a = -2 * used instead of actual gaussian, otherwise at high texture magnifications circular artifacts are visible */ #define EWA_MAXIDX 255 -static float EWA_WTS[EWA_MAXIDX + 1] = { +static const float EWA_WTS[EWA_MAXIDX + 1] = { 1.f, 0.990965f, 0.982f, 0.973105f, 0.96428f, 0.955524f, 0.946836f, 0.938216f, 0.929664f, 0.921178f, 0.912759f, 0.904405f, 0.896117f, 0.887893f, 0.879734f, 0.871638f, 0.863605f, 0.855636f, 0.847728f, 0.839883f, 0.832098f, 0.824375f, 0.816712f, 0.809108f, 0.801564f, diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index a2fa37fd7ea..3259608c18f 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -124,7 +124,7 @@ typedef struct { const int *orig_index_mp_to_orig; } MAOBakeData; -static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index) +static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index) { unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2, data->mface[face_num].v3, data->mface[face_num].v4}; @@ -1231,6 +1231,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result); break; case RE_BAKE_DISPLACEMENT: + case RE_BAKE_DERIVATIVE: do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result); break; case RE_BAKE_AO: @@ -1248,7 +1249,7 @@ static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; - int use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT; + bool use_displacement_buffer = ELEM(bkr->mode, RE_BAKE_DISPLACEMENT, RE_BAKE_DERIVATIVE); for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; @@ -1259,8 +1260,14 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) continue; if (use_displacement_buffer) { - RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, - result->height_min, result->height_max); + if (bkr->mode == RE_BAKE_DERIVATIVE) { + RE_bake_make_derivative(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + result->height_min, result->height_max, bkr->user_scale); + } + else { + RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + result->height_min, result->height_max); + } } RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 6118d479cab..fa05f8dd18d 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1309,6 +1309,10 @@ static void do_render_blur_3d(Render *re) re->mblur_offs = 0.0f; re->i.curblur = 0; /* stats */ + /* make sure motion blur changes get reset to current frame */ + if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) + BKE_scene_update_for_newframe(re->main, re->scene, re->lay); + /* weak... the display callback wants an active renderlayer pointer... */ re->result->renlay = render_get_active_layer(re, re->result); re->display_draw(re->ddh, re->result, NULL); diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index 8a023a2c009..43e052a6efc 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -73,7 +73,7 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -extern float hashvectf[]; +extern const float hashvectf[]; static void render_lighting_halo(HaloRen *har, float col_r[3]) { @@ -341,7 +341,8 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz, if (flarec) har->pixels+= (int)(har->rad-radist); if (har->ringc) { - float *rc, fac; + const float *rc; + float fac; int ofs; /* per ring an antialised circle */ @@ -393,7 +394,8 @@ int shadeHaloFloat(HaloRen *har, float col[4], int zz, dist= 0.0f; if (har->linec) { - float *rc, fac; + const float *rc; + float fac; int ofs; /* per starpoint an antialiased line */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 982e9b1a410..89d8345a0d7 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1875,10 +1875,11 @@ static void renderhalo_post(RenderResult *rr, float *rectf, HaloRen *har) /* pos static void renderflare(RenderResult *rr, float *rectf, HaloRen *har) { - extern float hashvectf[]; + extern const float hashvectf[]; HaloRen fla; Material *ma; - float *rc, rad, alfa, visifac, vec[3]; + const float *rc; + float rad, alfa, visifac, vec[3]; int b, type; fla= *har; diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 0d85cfe78b7..0c3bf85cd24 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -1373,7 +1373,7 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]) /* printf("start %x %x \n", (int)(0x7FFFFFFF*zf1), (int)(0x7FFFFFFF*zf2)); */ - while (1) { + do { lambda_o= lambda; if (lambda_x==lambda_y) { @@ -1394,7 +1394,13 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]) } lambda = min_ff(lambda_x, lambda_y); - + + /* not making any progress? */ + if (lambda==lambda_o) break; + + /* clip to end of volume */ + lambda = min_ff(lambda, 1.0f); + zf= zf1 + lambda*(zf2-zf1); count+= (float)shb->totbuf; @@ -1409,10 +1415,9 @@ float shadow_halo(LampRen *lar, const float p1[3], const float p2[3]) lightcount+= readshadowbuf_halo(shb, shsample, x, y, z); } - /* break after sample, so it takes at least one */ - if (lambda==lambda_o || lambda>=1.0f) break; } - + while (lambda < 1.0f); + if (count!=0.0f) return (lightcount/count); return 0.0f; diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 2dcb55f1f5d..bc9ba348c62 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -1002,7 +1002,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) } /* pass option forces UV calc */ - if (shi->passflag & SCE_PASS_UV) + if ((shi->passflag & SCE_PASS_UV) || (R.flag & R_NEED_VCOL)) texco |= (NEED_UV | TEXCO_UV); /* texture coordinates. shi->dxuv shi->dyuv have been set */ @@ -1056,7 +1056,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) } } - if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE))) { + if ((texco & TEXCO_UV) || (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) { VlakRen *vlr = shi->vlr; MTFace *tface; MCol *mcol; @@ -1071,7 +1071,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->actuv = obr->actmtface; shi->actcol = obr->actmcol; - if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) { + if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) || (R.flag & R_NEED_VCOL)) { for (i = 0; (mcol = RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) { ShadeInputCol *scol = &shi->col[i]; char *cp1, *cp2, *cp3; @@ -1213,7 +1213,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) } if ((mode & MA_FACETEXTURE) && i == obr->actmtface) { - if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) { + if (((mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) == 0) && ((R.flag & R_NEED_VCOL) == 0)) { shi->vcol[0] = 1.0f; shi->vcol[1] = 1.0f; shi->vcol[2] = 1.0f; @@ -1299,7 +1299,7 @@ void shade_input_set_shade_texco(ShadeInput *shi) * else un-initialized values are used */ if (shi->do_manage) { - if (mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) { + if ((mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) || (R.flag & R_NEED_VCOL)) { srgb_to_linearrgb_v3_v3(shi->vcol, shi->vcol); } } diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index f86942f7918..732892ed357 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -309,7 +309,7 @@ ScatterSettings *scatter_settings_new(float refl, float radius, float ior, float ss->Fdr= -1.440f/ior*ior + 0.710f/ior + 0.668f + 0.0636f*ior; ss->A= (1.0f + ss->Fdr)/(1.0f - ss->Fdr); ss->ld= radius; - ss->ro= min_ff(refl, 0.999f); + ss->ro= min_ff(refl, 0.99f); ss->color= ss->ro*reflfac + (1.0f-reflfac); ss->alpha_= compute_reduced_albedo(ss); diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index 028217b8609..6912f998e7a 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -39,6 +39,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLI_voxel.h" #include "BLI_utildefines.h" @@ -483,82 +484,96 @@ static void *vol_precache_part_test(void *data) } #endif -typedef struct VolPrecacheQueue { - ThreadQueue *work; - ThreadQueue *done; -} VolPrecacheQueue; - /* Iterate over the 3d voxel grid, and fill the voxels with scattering information * * It's stored in memory as 3 big float grids next to each other, one for each RGB channel. * I'm guessing the memory alignment may work out better this way for the purposes * of doing linear interpolation, but I haven't actually tested this theory! :) */ -static void *vol_precache_part(void *data) +typedef struct VolPrecacheState { + double lasttime; + int totparts; +} VolPrecacheState; + +static void vol_precache_part(TaskPool *pool, void *taskdata, int threadid) { - VolPrecacheQueue *queue = (VolPrecacheQueue *)data; - VolPrecachePart *pa; - - while ((pa = BLI_thread_queue_pop(queue->work))) { - ObjectInstanceRen *obi = pa->obi; - RayObject *tree = pa->tree; - ShadeInput *shi = pa->shi; - float scatter_col[3] = {0.f, 0.f, 0.f}; - float co[3], cco[3], view[3]; - int x, y, z, i; - int res[3]; - - if (pa->re->test_break && pa->re->test_break(pa->re->tbh)) - break; - - res[0]= pa->res[0]; - res[1]= pa->res[1]; - res[2]= pa->res[2]; - - for (z= pa->minz; z < pa->maxz; z++) { - co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f)); + VolPrecacheState *state = (VolPrecacheState *)BLI_task_pool_userdata(pool); + VolPrecachePart *pa = (VolPrecachePart *)taskdata; + Render *re = pa->re; + + ObjectInstanceRen *obi = pa->obi; + RayObject *tree = pa->tree; + ShadeInput *shi = pa->shi; + float scatter_col[3] = {0.f, 0.f, 0.f}; + float co[3], cco[3], view[3]; + int x, y, z, i; + int res[3]; + double time; + + if (re->test_break && re->test_break(re->tbh)) + return; + + printf("thread id %d\n", threadid); + + res[0]= pa->res[0]; + res[1]= pa->res[1]; + res[2]= pa->res[2]; + + for (z= pa->minz; z < pa->maxz; z++) { + co[2] = pa->bbmin[2] + (pa->voxel[2] * (z + 0.5f)); + + for (y= pa->miny; y < pa->maxy; y++) { + co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f)); - for (y= pa->miny; y < pa->maxy; y++) { - co[1] = pa->bbmin[1] + (pa->voxel[1] * (y + 0.5f)); + for (x=pa->minx; x < pa->maxx; x++) { + co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f)); - for (x=pa->minx; x < pa->maxx; x++) { - co[0] = pa->bbmin[0] + (pa->voxel[0] * (x + 0.5f)); - - if (pa->re->test_break && pa->re->test_break(pa->re->tbh)) - break; - - /* convert from world->camera space for shading */ - mul_v3_m4v3(cco, pa->viewmat, co); + if (re->test_break && re->test_break(re->tbh)) + break; + + /* convert from world->camera space for shading */ + mul_v3_m4v3(cco, pa->viewmat, co); - i = BLI_VOXEL_INDEX(x, y, z, res); + i = BLI_VOXEL_INDEX(x, y, z, res); - /* don't bother if the point is not inside the volume mesh */ - if (!point_inside_obi(tree, obi, cco)) { - obi->volume_precache->data_r[i] = -1.0f; - obi->volume_precache->data_g[i] = -1.0f; - obi->volume_precache->data_b[i] = -1.0f; - continue; - } - - copy_v3_v3(view, cco); - normalize_v3(view); - vol_get_scattering(shi, scatter_col, cco, view); - - obi->volume_precache->data_r[i] = scatter_col[0]; - obi->volume_precache->data_g[i] = scatter_col[1]; - obi->volume_precache->data_b[i] = scatter_col[2]; - + /* don't bother if the point is not inside the volume mesh */ + if (!point_inside_obi(tree, obi, cco)) { + obi->volume_precache->data_r[i] = -1.0f; + obi->volume_precache->data_g[i] = -1.0f; + obi->volume_precache->data_b[i] = -1.0f; + continue; } + + copy_v3_v3(view, cco); + normalize_v3(view); + vol_get_scattering(shi, scatter_col, cco, view); + + obi->volume_precache->data_r[i] = scatter_col[0]; + obi->volume_precache->data_g[i] = scatter_col[1]; + obi->volume_precache->data_b[i] = scatter_col[2]; + } } + } + + time = PIL_check_seconds_timer(); + if (time - state->lasttime > 1.0) { + ThreadMutex *mutex = BLI_task_pool_user_mutex(pool); - BLI_thread_queue_push(queue->done, pa); + if (BLI_mutex_trylock(mutex)) { + char str[64]; + float ratio = (float)BLI_task_pool_tasks_done(pool)/(float)state->totparts; + BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"), (int)(100.0f * ratio)); + re->i.infostr = str; + re->stats_draw(re->sdh, &re->i); + re->i.infostr = NULL; + state->lasttime = time; + + BLI_mutex_unlock(mutex); + } } - - return NULL; } - static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Material *ma, ShadeInput *shi) { memset(shi, 0, sizeof(ShadeInput)); @@ -573,9 +588,12 @@ static void precache_setup_shadeinput(Render *re, ObjectInstanceRen *obi, Materi shi->lay = re->lay; } -static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, ObjectInstanceRen *obi, int totthread, int *parts) +static void precache_launch_parts(Render *re, RayObject *tree, ShadeInput *shi, ObjectInstanceRen *obi) { + TaskScheduler *task_scheduler; + TaskPool *task_pool; VolumePrecache *vp = obi->volume_precache; + VolPrecacheState state; int i=0, x, y, z; float voxel[3]; int sizex, sizey, sizez; @@ -584,15 +602,23 @@ static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob int minx, maxx; int miny, maxy; int minz, maxz; + int totthread = re->r.threads; + int parts[3]; if (!vp) return; - BLI_freelistN(&re->volume_precache_parts); - /* currently we just subdivide the box, number of threads per side */ parts[0] = parts[1] = parts[2] = totthread; res = vp->res; + /* setup task scheduler */ + memset(&state, 0, sizeof(state)); + state.totparts = parts[0]*parts[1]*parts[2]; + state.lasttime = PIL_check_seconds_timer(); + + task_scheduler = BLI_task_scheduler_create(totthread); + task_pool = BLI_task_pool_create(task_scheduler, &state); + /* using boundbox in worldspace */ global_bounds_obi(re, obi, bbmin, bbmax); sub_v3_v3v3(voxel, bbmax, bbmin); @@ -636,13 +662,19 @@ static void precache_init_parts(Render *re, RayObject *tree, ShadeInput *shi, Ob pa->miny = miny; pa->maxy = maxy; pa->minz = minz; pa->maxz = maxz; - - BLI_addtail(&re->volume_precache_parts, pa); + BLI_task_pool_push(task_pool, vol_precache_part, pa, true, TASK_PRIORITY_HIGH); i++; } } } + + /* work and wait until tasks are done */ + BLI_task_pool_work_and_wait(task_pool); + + /* free */ + BLI_task_pool_free(task_pool); + BLI_task_scheduler_free(task_scheduler); } /* calculate resolution from bounding box in world space */ @@ -678,17 +710,8 @@ static int precache_resolution(Render *re, VolumePrecache *vp, ObjectInstanceRen static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *obi, Material *ma) { VolumePrecache *vp; - VolPrecachePart *pa; RayObject *tree; ShadeInput shi; - ListBase threads; - VolPrecacheQueue queue; - int parts[3] = {1, 1, 1}, totparts; - - int counter=0; - int totthread = re->r.threads, thread; - - double time, lasttime= PIL_check_seconds_timer(); R = *re; @@ -717,49 +740,8 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o /* Need a shadeinput to calculate scattering */ precache_setup_shadeinput(re, obi, ma, &shi); - precache_init_parts(re, tree, &shi, obi, totthread, parts); - totparts = parts[0] * parts[1] * parts[2]; - - /* setup work and done queues */ - queue.work = BLI_thread_queue_init(); - queue.done = BLI_thread_queue_init(); - BLI_thread_queue_nowait(queue.work); + precache_launch_parts(re, tree, &shi, obi); - for (pa= re->volume_precache_parts.first; pa; pa= pa->next) - BLI_thread_queue_push(queue.work, pa); - - /* launch threads */ - BLI_init_threads(&threads, vol_precache_part, totthread); - - for (thread= 0; thread<totthread; thread++) - BLI_insert_thread(&threads, &queue); - - /* loop waiting for work to be done */ - while (counter < totparts) { - if (re->test_break && re->test_break(re->tbh)) - break; - - if (BLI_thread_queue_pop_timeout(queue.done, 50)) - counter++; - - time= PIL_check_seconds_timer(); - if (time-lasttime>1.0) { - char str[64]; - BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"), - (int)(100.0f * ((float)counter / (float)totparts))); - re->i.infostr = str; - re->stats_draw(re->sdh, &re->i); - re->i.infostr = NULL; - lasttime = time; - } - } - - /* free */ - BLI_end_threads(&threads); - BLI_thread_queue_free(queue.work); - BLI_thread_queue_free(queue.done); - BLI_freelistN(&re->volume_precache_parts); - if (tree) { /* TODO: makeraytree_object creates a tree and saves it on OBI, * if we free this tree we should also clear other pointers to it */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 84b376edcd8..c338d49fe17 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -198,6 +198,7 @@ bool WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct I /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ +int WM_operator_props_popup_confirm(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_operator_props_dialog_popup(struct bContext *C, struct wmOperator *op, int width, int height); diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 121e5e401fa..eab27286709 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -98,6 +98,8 @@ const char *WM_key_event_string(short type); int WM_key_event_operator_id(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, int hotkey, struct wmKeyMap **keymap_r); char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, const bool strict, char *str, int len); +const char *WM_bool_as_string(bool test); + #ifdef __cplusplus } #endif diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 3e2d01d6e80..4c58089f4e7 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -226,13 +226,13 @@ static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event) /* check buttons (XXX todo rna and value) */ if (UI_but_active_drop_name(C) ) { - strcpy(drag->opname, IFACE_("Paste name")); + BLI_strncpy(drag->opname, IFACE_("Paste name"), sizeof(drag->opname)); } else { const char *opname = wm_dropbox_active(C, drag, event); if (opname) { - BLI_strncpy(drag->opname, opname, FILE_MAX); + BLI_strncpy(drag->opname, opname, sizeof(drag->opname)); // WM_cursor_modal_set(win, CURSOR_COPY); } // else diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 37bcfa4f591..825c1ca9252 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2171,7 +2171,7 @@ void wm_event_do_handlers(bContext *C) while ( (event = win->queue.first) ) { int action = WM_HANDLER_CONTINUE; -#ifdef DEBUG +#ifndef NDEBUG if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { printf("\n%s: Handling event\n", __func__); WM_event_print(event); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index cc4d422331d..f7bbb84facc 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -865,9 +865,10 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList * /* first time saving */ /* XXX temp solution to solve bug, real fix coming (ton) */ - if (G.main->name[0] == 0) + if ((G.main->name[0] == '\0') && !(fileflags & G_FILE_SAVE_COPY)) { BLI_strncpy(G.main->name, filepath, sizeof(G.main->name)); - + } + /* XXX temp solution to solve bug, real fix coming (ton) */ G.main->recovered = 0; diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index adf159bcfee..05ee23e2361 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -40,6 +40,7 @@ #include "BLI_math.h" #include "BLI_scanfill.h" /* lasso tessellation */ #include "BLI_utildefines.h" +#include "BLI_lasso.h" #include "BKE_context.h" @@ -231,56 +232,73 @@ static void wm_gesture_draw_circle(wmGesture *gt) } -static void draw_filled_lasso(wmGesture *gt) +struct LassoFillData { + unsigned int *px; + int width; +}; + +static void draw_filled_lasso_px_cb(int x, int y, void *user_data) +{ + struct LassoFillData *data = user_data; + unsigned char *col = (unsigned char *)&(data->px[(y * data->width) + x]); + col[0] = col[1] = col[2] = 0xff; + col[3] = 0x10; +} + +static void draw_filled_lasso(wmWindow *win, wmGesture *gt) { - ScanFillContext sf_ctx; - ScanFillVert *sf_vert = NULL, *sf_vert_last = NULL, *sf_vert_first = NULL; - ScanFillFace *sf_tri; short *lasso = (short *)gt->customdata; + const int tot = gt->points; + int (*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__); int i; - - BLI_scanfill_begin(&sf_ctx); - for (i = 0; i < gt->points; i++, lasso += 2) { - float co[3]; - - co[0] = (float)lasso[0]; - co[1] = (float)lasso[1]; - co[2] = 0.0f; - - sf_vert = BLI_scanfill_vert_add(&sf_ctx, co); - if (sf_vert_last) - /* e = */ /* UNUSED */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert); - sf_vert_last = sf_vert; - if (sf_vert_first == NULL) sf_vert_first = sf_vert; + rcti rect; + rcti rect_win; + + for (i = 0; i < tot; i++, lasso += 2) { + moves[i][0] = lasso[0]; + moves[i][1] = lasso[1]; } - - /* highly unlikely this will fail, but could crash if (gt->points == 0) */ - if (sf_vert_first) { - const float zvec[3] = {0.0f, 0.0f, 1.0f}; - BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); - BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_HOLES, zvec); - + + BLI_lasso_boundbox(&rect, (const int (*)[2])moves, tot); + + wm_subwindow_getrect(win, gt->swinid, &rect_win); + BLI_rcti_translate(&rect, rect_win.xmin, rect_win.ymin); + BLI_rcti_isect(&rect_win, &rect, &rect); + BLI_rcti_translate(&rect, -rect_win.xmin, -rect_win.ymin); + + /* highly unlikely this will fail, but could crash if (tot == 0) */ + if (BLI_rcti_is_empty(&rect) == false) { + const int w = BLI_rcti_size_x(&rect); + const int h = BLI_rcti_size_y(&rect); + unsigned int *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__); + struct LassoFillData lasso_fill_data = {pixel_buf, w}; + + fill_poly_v2i_n( + rect.xmin, rect.ymin, rect.xmax, rect.ymax, + (const int (*)[2])moves, tot, + draw_filled_lasso_px_cb, &lasso_fill_data); + glEnable(GL_BLEND); - glColor4f(1.0, 1.0, 1.0, 0.05); - glBegin(GL_TRIANGLES); - for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { - glVertex2fv(sf_tri->v1->co); - glVertex2fv(sf_tri->v2->co); - glVertex2fv(sf_tri->v3->co); - } - glEnd(); + // glColor4f(1.0, 1.0, 1.0, 0.05); + + glRasterPos2f(rect.xmin, rect.ymin); + + glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_buf); + glDisable(GL_BLEND); - - BLI_scanfill_end(&sf_ctx); + MEM_freeN(pixel_buf); } + + MEM_freeN(moves); } -static void wm_gesture_draw_lasso(wmGesture *gt) + +static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt) { short *lasso = (short *)gt->customdata; int i; - draw_filled_lasso(gt); + draw_filled_lasso(win, gt); glEnable(GL_LINE_STIPPLE); glColor3ub(96, 96, 96); @@ -347,9 +365,9 @@ void wm_gesture_draw(wmWindow *win) wm_gesture_draw_cross(win, gt); } else if (gt->type == WM_GESTURE_LINES) - wm_gesture_draw_lasso(gt); + wm_gesture_draw_lasso(win, gt); else if (gt->type == WM_GESTURE_LASSO) - wm_gesture_draw_lasso(gt); + wm_gesture_draw_lasso(win, gt); else if (gt->type == WM_GESTURE_STRAIGHTLINE) wm_gesture_draw_line(gt); } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 43a98a4600b..f6ba3a29344 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -50,6 +50,7 @@ #include "BKE_main.h" #include "BKE_screen.h" +#include "BLF_translation.h" #include "RNA_access.h" #include "RNA_enum_types.h" @@ -1479,3 +1480,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) return km; } +const char *WM_bool_as_string(bool test) +{ + return test ? IFACE_("ON") : IFACE_("OFF"); +} diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5e1e5890c6b..6091ec4a371 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1433,7 +1433,8 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) * For use by #WM_operator_props_popup_call, #WM_operator_props_popup only. * * \note operator menu needs undo flag enabled , for redo callback */ -static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_call) +static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, + const bool do_call, const bool do_redo) { if ((op->type->flag & OPTYPE_REGISTER) == 0) { BKE_reportf(op->reports, RPT_ERROR, @@ -1443,7 +1444,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_ /* if we don't have global undo, we can't do undo push for automatic redo, * so we require manual OK clicking in this popup */ - if (!(U.uiflag & USER_GLOBALUNDO)) + if (!do_redo || !(U.uiflag & USER_GLOBALUNDO)) return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y); uiPupBlockEx(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op); @@ -1454,18 +1455,26 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_ return OPERATOR_RUNNING_MODAL; } +/* Same as WM_operator_props_popup but don't use operator redo. + * just wraps WM_operator_props_dialog_popup. + */ +int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, false, false); +} + /* Same as WM_operator_props_popup but call the operator first, * This way - the button values correspond to the result of the operator. * Without this, first access to a button will make the result jump, * see [#32452] */ int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return wm_operator_props_popup_ex(C, op, TRUE); + return wm_operator_props_popup_ex(C, op, true, true); } int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return wm_operator_props_popup_ex(C, op, FALSE); + return wm_operator_props_popup_ex(C, op, false, true); } int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height) @@ -2531,6 +2540,8 @@ static bool blend_save_check(bContext *UNUSED(C), wmOperator *op) static void WM_OT_save_as_mainfile(wmOperatorType *ot) { + PropertyRNA *prop; + ot->name = "Save As Blender File"; ot->idname = "WM_OT_save_as_mainfile"; ot->description = "Save the current file in the desired location"; @@ -2545,8 +2556,9 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file"); RNA_def_boolean(ot->srna, "relative_remap", 1, "Remap Relative", "Remap relative paths when saving in a different directory"); - RNA_def_boolean(ot->srna, "copy", 0, "Save Copy", + prop = RNA_def_boolean(ot->srna, "copy", 0, "Save Copy", "Save a copy of the actual working state but does not make saved file active"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); #ifdef USE_BMESH_SAVE_AS_COMPAT RNA_def_boolean(ot->srna, "use_mesh_compat", 0, "Legacy Mesh Format", "Save using legacy mesh format (no ngons) - WARNING: only saves tris and quads, other ngons will " diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 4ad4286b657..ae535ed45e8 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -148,6 +148,15 @@ void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[4][4]) } } +void wm_subwindow_getrect(wmWindow *win, int swinid, rcti *r_rect) +{ + wmSubWindow *swin = swin_from_swinid(win, swinid); + + if (swin) { + *r_rect = swin->winrct; + } +} + /* always sets pixel-precise 2D window/view matrices */ /* coords is in whole pixels. xmin = 15, xmax = 16: means window is 2 pix big */ int wm_subwindow_open(wmWindow *win, rcti *winrct) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 78a2ed9b05d..9e89c17e024 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -131,7 +131,7 @@ static void wm_window_check_position(rcti *rect) { int width, height, d; - wm_get_desktopsize(&width, &height); + wm_get_screensize(&width, &height); #if defined(__APPLE__) && !defined(GHOST_COCOA) height -= 70; @@ -359,7 +359,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) if (multisamples == -1) multisamples = U.ogl_multisamples; - wm_get_desktopsize(&scr_w, &scr_h); + wm_get_screensize(&scr_w, &scr_h); posy = (scr_h - win->posy - win->sizey); ghostwin = GHOST_CreateWindow(g_system, title, @@ -378,12 +378,12 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) win->ghostwin = ghostwin; GHOST_SetWindowUserData(ghostwin, win); /* pointer back */ - /* set the state*/ - GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate); - if (win->eventstate == NULL) win->eventstate = MEM_callocN(sizeof(wmEvent), "window event state"); + /* set the state */ + GHOST_SetWindowState(ghostwin, (GHOST_TWindowState)win->windowstate); + /* until screens get drawn, make it nice gray */ glClearColor(0.55, 0.55, 0.55, 0.0); /* Crash on OSS ATI: bugs.launchpad.net/ubuntu/+source/mesa/+bug/656100 */ diff --git a/source/blender/windowmanager/wm_subwindow.h b/source/blender/windowmanager/wm_subwindow.h index 064d00b0723..a70e7765ecf 100644 --- a/source/blender/windowmanager/wm_subwindow.h +++ b/source/blender/windowmanager/wm_subwindow.h @@ -45,6 +45,7 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct); void wm_subwindow_getsize(wmWindow *win, int swinid, int *x, int *y); void wm_subwindow_getorigin(wmWindow *win, int swinid, int *x, int *y); void wm_subwindow_getmatrix(wmWindow *win, int swinid, float mat[4][4]); +void wm_subwindow_getrect(wmWindow *win, int swinid, struct rcti *r_rect); unsigned int index_to_framebuffer(int index); diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 1123e6e6ea6..529e2017989 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -130,6 +130,7 @@ endif() bf_intern_utfconv bf_imbuf_cineon bf_imbuf_openexr + bf_imbuf_openimageio extern_openjpeg extern_redcode bf_imbuf_dds diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 9e267d45424..f55f307e095 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -335,6 +335,7 @@ void ED_view3D_background_image_remove(struct View3D *v3d, struct BGpic *bgpic) void ED_view3D_background_image_clear(struct View3D *v3d) {STUB_ASSERT(0);} void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]) {STUB_ASSERT(0);} float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit) {STUB_ASSERT(0); return 0.0f;} +void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrArea *sa) {STUB_ASSERT(0);} void view3d_apply_mat4(float mat[4][4], float *ofs, float *quat, float *dist) {STUB_ASSERT(0);} int text_file_modified(struct Text *text) {STUB_ASSERT(0); return 0;} void ED_node_shader_default(struct bContext *C, struct ID *id) {STUB_ASSERT(0);} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 397da79a493..921443d9ab9 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -912,6 +912,7 @@ endif() bf_avi bf_imbuf_cineon bf_imbuf_openexr + bf_imbuf_openimageio bf_imbuf_dds bf_collada bf_intern_bsp diff --git a/source/creator/creator.c b/source/creator/creator.c index b442194bd7d..1596fe5359c 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -76,13 +76,13 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLI_callbacks.h" +#include "BLI_blenlib.h" +#include "BLI_mempool.h" #include "DNA_ID.h" #include "DNA_scene_types.h" #include "DNA_userdef_types.h" -#include "BLI_blenlib.h" - #include "BKE_blender.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -300,6 +300,7 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data) #ifdef WITH_LIBMV BLI_argsPrintArgDoc(ba, "--debug-libmv"); #endif + BLI_argsPrintArgDoc(ba, "--debug-memory"); BLI_argsPrintArgDoc(ba, "--debug-jobs"); BLI_argsPrintArgDoc(ba, "--debug-python"); @@ -412,10 +413,13 @@ static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data) G.debug |= G_DEBUG; /* std output printf's */ printf(BLEND_VERSION_STRING_FMT); MEM_set_memory_debug(); +#ifdef DEBUG + BLI_mempool_set_memory_debug(); +#endif #ifdef WITH_BUILDINFO printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type); -#endif // WITH_BUILDINFO +#endif BLI_argsPrint(data); return 0; @@ -436,6 +440,12 @@ static int debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *U } #endif +static int debug_mode_memory(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) +{ + MEM_set_memory_debug(); + return 0; +} + static int set_debug_value(int argc, const char **argv, void *UNUSED(data)) { if (argc > 1) { @@ -1381,6 +1391,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) #ifdef WITH_LIBMV BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL); #endif + BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL); BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL); BLI_argsAdd(ba, 1, NULL, "--debug-jobs", "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS); @@ -1451,23 +1462,50 @@ int main(int argc, const char **UNUSED(argv_c)) /* Do not mess with const */ int main(int argc, const char **argv) #endif { - bContext *C = CTX_create(); + bContext *C; SYS_SystemHandle syshandle; #ifndef WITH_PYTHON_MODULE bArgs *ba; #endif -#ifdef WIN32 +#ifdef WIN32 /* Win32 Unicode Args */ + /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialised + * (it depends on the args passed in, which is what we're getting here!) + */ wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc); + char **argv = malloc(argc * sizeof(char *)); int argci = 0; - char **argv = MEM_mallocN(argc * sizeof(char *), "argv array"); + for (argci = 0; argci < argc; argci++) { argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0); } + LocalFree(argv_16); #endif + /* NOTE: Special exception for guarded allocator type switch: + * we need to perform switch from lock-free to fully + * guarded allocator before any allocation happened. + */ + { + int i; + for (i = 0; i < argc; i++) { + if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") || + STREQ(argv[i], "--debug-memory")) + { + printf("Switching to fully guarded memory allocator.\n"); + MEM_use_guarded_allocator(); + break; + } + else if (STREQ(argv[i], "--")) { + break; + } + } + } + + C = CTX_create(); + #ifdef WITH_PYTHON_MODULE #ifdef __APPLE__ environ = *_NSGetEnviron(); @@ -1638,7 +1676,7 @@ int main(int argc, const char **argv) while (argci) { free(argv[--argci]); } - MEM_freeN(argv); + free(argv); argv = NULL; #endif diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index a6b71e0bc43..bcc62a341f8 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -211,7 +211,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat MT_Vector3 dir = (campos - objpos).safe_normalized(); MT_Vector3 up(0,0,1.0); - KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; + KX_GameObject* gameobj = (KX_GameObject *)this->m_clientobject; // get scaling of halo object MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling(); @@ -225,7 +225,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat } MT_Vector3 left = dir.normalized(); - dir = (up.cross(left)).normalized(); + dir = (left.cross(up)).normalized(); // we have calculated the row vectors, now we keep // local scaling into account: @@ -241,14 +241,13 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat glTranslated(objpos[0],objpos[1],objpos[2]); glMultMatrixd(maat); - } else { if (objectdrawmode & RAS_IPolyMaterial::SHADOW) { // shadow must be cast to the ground, physics system needed here! MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; + KX_GameObject *gameobj = (KX_GameObject *)this->m_clientobject; MT_Vector3 direction = MT_Vector3(0,0,-1); direction.normalize(); @@ -328,7 +327,7 @@ void KX_BlenderRenderTools::RenderText( RAS_IPolyMaterial* polymat, float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { - const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); + const STR_String &mytext = ((CValue *)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); struct MTFace* tface = 0; @@ -408,3 +407,4 @@ void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) } } } + diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index dd9609968b0..b0555abbea4 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2665,7 +2665,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, case PARBONE: { // parent this to a bone - Bone *parent_bone = BKE_armature_find_bone_name( (bArmature *)(blenderchild->parent)->data, blenderchild->parsubstr); + Bone *parent_bone = BKE_armature_find_bone_name(BKE_armature_from_object(blenderchild->parent), + blenderchild->parsubstr); if (parent_bone) { KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index e8c29d5aa4f..0d851c4f10d 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -66,9 +66,7 @@ unsigned int GPC_RenderTools::m_numgllights; GPC_RenderTools::GPC_RenderTools() { -// XXX m_font = BMF_GetFont(BMF_kHelvetica10); - - glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); + glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights); if (m_numgllights < 8) m_numgllights = 8; } @@ -220,7 +218,7 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in MT_Vector3 dir = (campos - objpos).safe_normalized(); MT_Vector3 up(0,0,1.0); - KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; + KX_GameObject* gameobj = (KX_GameObject *)this->m_clientobject; // get scaling of halo object MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling(); @@ -256,7 +254,7 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in { // shadow must be cast to the ground, physics system needed here! MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; + KX_GameObject *gameobj = (KX_GameObject *)this->m_clientobject; MT_Vector3 direction = MT_Vector3(0,0,-1); direction.normalize(); @@ -280,6 +278,12 @@ void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,in // couldn't find something to cast the shadow on... glMultMatrixd(oglmatrix); } + else + { // we found the "ground", but the cast matrix doesn't take + // scaling in consideration, so we must apply the object scale + MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); + glScalef(size[0], size[1], size[2]); + } } else { @@ -490,7 +494,7 @@ void GPC_RenderTools::RenderText( RAS_IPolyMaterial* polymat, float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { - STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); + const STR_String &mytext = ((CValue *)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); struct MTFace* tface = 0; @@ -562,8 +566,7 @@ void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) glAccum(GL_LOAD, 1.0); rasterizer->SetMotionBlurState(2); } - else if (motionblurvalue>=0.0 && motionblurvalue<=1.0) - { + else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) { glAccum(GL_MULT, motionblurvalue); glAccum(GL_ACCUM, 1-motionblurvalue); glAccum(GL_RETURN, 1.0); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 0b1fbf977dd..5bed4fa40b6 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -58,11 +58,15 @@ extern "C" #endif // __cplusplus #include "MEM_guardedalloc.h" #include "BLI_threads.h" +#include "BLI_mempool.h" #include "BLI_blenlib.h" + #include "DNA_scene_types.h" #include "DNA_userdef_types.h" + #include "BLO_readfile.h" #include "BLO_runtime.h" + #include "BKE_blender.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -74,6 +78,7 @@ extern "C" #include "BKE_modifier.h" #include "BKE_text.h" #include "BKE_sound.h" + #include "IMB_imbuf.h" int GHOST_HACK_getFirstFile(char buf[]); @@ -580,8 +585,11 @@ int main(int argc, char** argv) case 'd': i++; - G.debug |= G_DEBUG; /* std output printf's */ + G.debug |= G_DEBUG; MEM_set_memory_debug(); +#ifdef DEBUG + BLI_mempool_set_memory_debug(); +#endif break; case 'f': diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index b3a38cb4f98..e5b8159753b 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -968,7 +968,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)") return NULL; } -static unsigned int GL_array[11] = { +static const unsigned int GL_array[11] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, |