diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
30 files changed, 673 insertions, 956 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b329a502c42..db8fb288d87 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2166,6 +2166,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, /* weight paint and face select need original indices because of selection buffer drawing */ int needMapping = (ob == obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT))); + BLI_assert(ob->type == OB_MESH); + clear_mesh_caches(ob); mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform, diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e95451252d0..dd27cc70ba3 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -512,7 +512,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) { if (pose) { switch (pose->iksolver) { - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: return NULL; case IKSOLVER_ITASC: return "bItasc"; @@ -587,7 +587,7 @@ void BKE_pose_ikparam_init(bPose *pose) BKE_pose_itasc_init(itasc); pose->ikparam = itasc; break; - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: default: pose->ikparam = NULL; break; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index b3cbc1f2b16..1970df54339 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1822,8 +1822,15 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos */ /* only happens on reload file, but violates depsgraph still... fix! */ - if ((cu->path == NULL) || (cu->path->data == NULL)) + if (ELEM(NULL, cu->path, cu->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); + + /* path building may fail in EditMode after removing verts [#33268]*/ + if (ELEM(NULL, cu->path, cu->path->data)) { + /* BLI_assert(cu->path != NULL); */ + return; + } + } } /* find the root bone and the chain of bones from the root to the tip diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e1e868b234e..40cd5b3d403 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -70,6 +70,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_library.h" #include "BKE_main.h" @@ -113,6 +114,7 @@ void free_blender(void) BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); + BKE_images_exit(); BLI_callback_global_finalize(); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 98b206712d6..f310895f590 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1287,8 +1287,6 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); - BKE_image_get_ibuf(mtex->tex->ima, NULL); - /*do normalized cannonical view coords for texture*/ for (y = -1.0, iy = 0; iy < side; iy++, y += step) { for (x = -1.0, ix = 0; ix < side; ix++, x += step) { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index b7ad135fa72..7ac046c092f 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2408,6 +2408,11 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) * this is a really horribly written function. ger. - joeedh * * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + * + * Note: This function is currently only used by the Mirror modifier, so it + * skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices). If used elsewhere, it may + * be necessary to make this functionality optional. */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { @@ -2451,14 +2456,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = newv[vtargetmap[i]]; } } - - /* find-replace merged vertices with target vertices */ - ml = cddm->mloop; - for (i = 0; i < totloop; i++, ml++) { - if (vtargetmap[ml->v] != -1) { - ml->v = vtargetmap[ml->v]; - } - } + + /* Don't remap vertices in cddm->mloop, because we need to know the original + * indices in order to skip faces with all vertices merged. + * The "update loop indices..." section further down remaps vertices in mloop. + */ /* now go through and fix edges and faces */ med = cddm->medge; @@ -2492,6 +2494,24 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) ml = cddm->mloop + mp->loopstart; + /* skip faces with all vertices merged */ + { + int all_vertices_merged = TRUE; + + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = FALSE; + break; + } + } + + if (UNLIKELY(all_vertices_merged)) { + continue; + } + } + + ml = cddm->mloop + mp->loopstart; + c = 0; for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; @@ -2650,7 +2670,7 @@ void CDDM_calc_edges(DerivedMesh *dm) EdgeHashIterator *ehi; MPoly *mp = cddm->mpoly; MLoop *ml; - MEdge *med; + MEdge *med, *origmed; EdgeHash *eh = BLI_edgehash_new(); int v1, v2; int *eindex; @@ -2683,6 +2703,7 @@ void CDDM_calc_edges(DerivedMesh *dm) CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + origmed = cddm->medge; med = CustomData_get_layer(&edgeData, CD_MEDGE); index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); @@ -2693,8 +2714,14 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - *index = j == 0 ? ORIGINDEX_NONE : eindex[j - 1]; + if (j == 0) { + med->flag = ME_EDGEDRAW | ME_EDGERENDER; + *index = ORIGINDEX_NONE; + } + else { + med->flag = ME_EDGEDRAW | ME_EDGERENDER | origmed[j - 1].flag; + *index = eindex[j - 1]; + } BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b488e683947..4641a02265a 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -198,8 +198,10 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3 w3[0] = 1.0f - w1[0] - w2[0]; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 ) { @@ -371,7 +373,9 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM return result; } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 75276adf518..529fe07cab3 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1008,8 +1008,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * const ColorManagedDisplaySettings *display_settings) { int x, y, c; - unsigned int n, nl; - double div, divl; + unsigned int nl, na, nr, ng, nb; + double divl, diva, divr, divg, divb; float *rf = NULL; unsigned char *rc = NULL; unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; @@ -1149,24 +1149,37 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * savedlines += 1; } + /* test for nicer distribution even - non standard, leave it out for a while */ +#if 0 + for (x = 0; x < 256; x++) { + bin_lum[x] = sqrt (bin_lum[x]); + bin_r[x] = sqrt(bin_r[x]); + bin_g[x] = sqrt(bin_g[x]); + bin_b[x] = sqrt(bin_b[x]); + bin_a[x] = sqrt(bin_a[x]); + } +#endif + /* convert hist data to float (proportional to max count) */ - n = 0; - nl = 0; + nl = na = nr = nb = ng = 0; for (x = 0; x < 256; x++) { if (bin_lum[x] > nl) nl = bin_lum[x]; - if (bin_r[x] > n) n = bin_r[x]; - if (bin_g[x] > n) n = bin_g[x]; - if (bin_b[x] > n) n = bin_b[x]; - if (bin_a[x] > n) n = bin_a[x]; + if (bin_r[x] > nr) nr = bin_r[x]; + if (bin_g[x] > ng) ng = bin_g[x]; + if (bin_b[x] > nb) nb = bin_b[x]; + if (bin_a[x] > na) na = bin_a[x]; } - div = 1.0 / (double)n; divl = 1.0 / (double)nl; + diva = 1.0 / (double)na; + divr = 1.0 / (double)nr; + divg = 1.0 / (double)ng; + divb = 1.0 / (double)nb; for (x = 0; x < 256; x++) { scopes->hist.data_luma[x] = bin_lum[x] * divl; - scopes->hist.data_r[x] = bin_r[x] * div; - scopes->hist.data_g[x] = bin_g[x] * div; - scopes->hist.data_b[x] = bin_b[x] * div; - scopes->hist.data_a[x] = bin_a[x] * div; + scopes->hist.data_r[x] = bin_r[x] * divr; + scopes->hist.data_g[x] = bin_g[x] * divg; + scopes->hist.data_b[x] = bin_b[x] * divb; + scopes->hist.data_a[x] = bin_a[x] * diva; } MEM_freeN(bin_lum); MEM_freeN(bin_r); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 719ae7357b4..ffb93139358 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -245,6 +246,10 @@ static void *ctx_wm_python_context_get(const bContext *C, const char *member, vo (void)C, (void)member; #endif + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return NULL; + return fall_through; } @@ -264,6 +269,11 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res // return 1; } #endif + + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return done; + /* we check recursion to ensure that we do not get infinite * loops requesting data from ourselfs in a context callback */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index f2cd695d64a..754a4fbc0c8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1116,7 +1116,7 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * *fp = basisu[i] * bp->vec[3]; sumdiv += *fp; } - if (sumdiv != 0.0f) if (sumdiv < 0.999f || sumdiv > 1.001f) { + if ((sumdiv != 0.0f) && (sumdiv < 0.999f || sumdiv > 1.001f)) { /* is normalizing needed? */ fp = sum; for (i = istart; i <= iend; i++, fp++) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 93c776ae30e..b2f8db0dcce 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -761,7 +761,7 @@ static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) { MLoopUV *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloopuv(void *data1, void *data2) @@ -833,7 +833,7 @@ static void layerDoMinMax_mloop_origspace(void *data, void *vmin, void *vmax) { OrigSpaceLoop *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloop_origspace(void *data1, void *data2) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 9d3a7ec57cf..d23a608d31f 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -671,8 +671,9 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } } - else if(ob->type == OB_LAMP) + else if (ob->type == OB_LAMP) { dag_add_lamp_driver_relations(dag, node, ob->data); + } /* particles */ psys = ob->particlesystem.first; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 89d728c0419..bb3836e3c08 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -86,11 +86,13 @@ #include "RE_shader_ext.h" #ifdef _OPENMP -#include <omp.h> +# include <omp.h> #endif /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* precalculated gaussian factors for 5x super sampling */ static float gaussianFactors[5] = {0.996849f, diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 30427a81c4b..c3008d17bd1 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -47,39 +47,40 @@ typedef struct { } IDType; /* plural need to match rna_main.c's MainCollectionDef */ +/* WARNING! Keep it in sync with i18n contexts in BLF_translation.h */ static IDType idtypes[] = { - { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE}, - { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE}, - { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE}, /* rename gpencil */ - { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ID, "ID", "ids", 0}, /* plural is fake */ - { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE}, - { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE}, /* deprecated */ - { ID_KE, "Key", "shape_keys", 0}, - { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE}, - { ID_LI, "Library", "libraries", 0}, - { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE}, - { ID_PA, "ParticleSettings", "particles", 0}, - { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SCR, "Screen", "screens", 0}, - { ID_SEQ, "Sequence", "sequences", 0}, /* not actually ID data */ - { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WM, "WindowManager", "window_managers", 0}, - { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, + { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE }, + { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE }, + { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */ + { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ID, "ID", "ids", 0 }, /* plural is fake */ + { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE }, + { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */ + { ID_KE, "Key", "shape_keys", 0 }, + { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE }, + { ID_LI, "Library", "libraries", 0 }, + { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE }, + { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE }, + { ID_PA, "ParticleSettings", "particles", 0 }, + { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SCR, "Screen", "screens", 0 }, + { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */ + { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WM, "WindowManager", "window_managers", 0 }, }; static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 55d37c91859..e4b9edacc7e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -100,6 +100,8 @@ #include "WM_api.h" +static SpinLock image_spin; + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -108,6 +110,16 @@ #define IMA_INDEX_FRAME(index) (index >> 10) #define IMA_INDEX_PASS(index) (index & ~1023) +void BKE_images_init(void) +{ + BLI_spin_init(&image_spin); +} + +void BKE_images_exit(void) +{ + BLI_spin_end(&image_spin); +} + /* ******** IMAGE PROCESSING ************* */ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ @@ -168,13 +180,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ void BKE_image_de_interlace(Image *ima, int odd) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { if (odd) de_interlace_st(ibuf); else de_interlace_ng(ibuf); } + BKE_image_release_ibuf(ima, ibuf, NULL); } /* ***************** ALLOC & FREE, DATA MANAGING *************** */ @@ -260,8 +273,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) /* this function is intended to be thread safe. with IMA_NO_INDEX this * should be OK, but when iterating over the list this is more tricky * */ - if (index == IMA_NO_INDEX) + if (index == IMA_NO_INDEX) { return ima->ibufs.first; + } else { ImBuf *ibuf; @@ -269,9 +283,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) for (ibuf = ima->ibufs.first; ibuf; ibuf = ibuf->next) if (ibuf->index == index) return ibuf; - - return NULL; } + + return NULL; } /* no ima->ibuf anymore, but listbase */ @@ -534,7 +548,7 @@ int BKE_image_scale(Image *image, int width, int height) ibuf->userflags |= IB_BITMAPDIRTY; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); return (ibuf != NULL); } @@ -2081,6 +2095,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (ima == NULL) return; + BLI_spin_lock(&image_spin); + switch (signal) { case IMA_SIGNAL_FREE: image_free_buffers(ima); @@ -2157,6 +2173,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) break; } + BLI_spin_unlock(&image_spin); + /* don't use notifiers because they are not 100% sure to succeeded * this also makes sure all scenes are accounted for. */ { @@ -2320,7 +2338,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) if (ibuf) { #ifdef WITH_OPENEXR - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, frame); ima->type = IMA_TYPE_MULTILAYER; @@ -2482,7 +2500,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) } if (ibuf) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, cfra); ima->type = IMA_TYPE_MULTILAYER; @@ -2751,38 +2769,32 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame * a big bottleneck */ } - *frame_r = frame; - *index_r = index; + if (frame_r) + *frame_r = frame; + + if (index_r) + *index_r = index; return ibuf; } -/* Checks optional ImageUser and verifies/creates ImBuf. */ -/* use this one if you want to get a render result in progress, - * if not, use BKE_image_get_ibuf which doesn't require a release */ -ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +/* Checks optional ImageUser and verifies/creates ImBuf. + * + * not thread-safe, so callee should worry about thread locks + */ +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf = NULL; float color[] = {0, 0, 0, 1}; int frame = 0, index = 0; - /* This function is intended to be thread-safe. It postpones the mutex lock - * until it needs to load the image, if the image is already there it - * should just get the pointer and return. The reason is that a lot of mutex - * locks appears to be very slow on certain multicore macs, causing a render - * with image textures to actually slow down as more threads are used. - * - * Note that all the image loading functions should also make sure they do - * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. - * That means, the last two steps must be, 1) add the ibuf to the list and - * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ - if (lock_r) *lock_r = NULL; /* quick reject tests */ if (ima == NULL) return NULL; + if (iuser) { if (iuser->ok == 0) return NULL; @@ -2790,95 +2802,71 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) else if (ima->ok == 0) return NULL; - /* try to get the ibuf without locking */ ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); if (ibuf == NULL) { - /* couldn't get ibuf and image is not ok, so let's lock and try to - * load the image */ - BLI_lock_thread(LOCK_IMAGE); - - /* need to check ok flag and loading ibuf again, because the situation - * might have changed in the meantime */ - if (iuser) { - if (iuser->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; - } - } - else if (ima->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; - } - - ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); - - if (ibuf == NULL) { - /* we are sure we have to load the ibuf, using source and type */ - if (ima->source == IMA_SRC_MOVIE) { - /* source is from single file, use flipbook to store ibuf */ - ibuf = image_load_movie_file(ima, iuser, frame); - } - else if (ima->source == IMA_SRC_SEQUENCE) { - if (ima->type == IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ - ibuf = image_load_sequence_file(ima, iuser, frame); - } - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) { - /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ - ibuf = image_load_sequence_multilayer(ima, iuser, frame); - } + /* we are sure we have to load the ibuf, using source and type */ + if (ima->source == IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + ibuf = image_load_movie_file(ima, iuser, frame); + } + else if (ima->source == IMA_SRC_SEQUENCE) { + if (ima->type == IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + ibuf = image_load_sequence_file(ima, iuser, frame); } - else if (ima->source == IMA_SRC_FILE) { - - if (ima->type == IMA_TYPE_IMAGE) - ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) - /* keeps render result, stores ibufs in listbase, allows saving */ - ibuf = image_get_ibuf_multilayer(ima, iuser); - + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) { + /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + ibuf = image_load_sequence_multilayer(ima, iuser, frame); } - else if (ima->source == IMA_SRC_GENERATED) { - /* generated is: ibuf is allocated dynamically */ - /* UV testgrid or black or solid etc */ - if (ima->gen_x == 0) ima->gen_x = 1024; - if (ima->gen_y == 0) ima->gen_y = 1024; - ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, - color, &ima->colorspace_settings); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - ima->ok = IMA_OK_LOADED; + } + else if (ima->source == IMA_SRC_FILE) { + + if (ima->type == IMA_TYPE_IMAGE) + ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) + /* keeps render result, stores ibufs in listbase, allows saving */ + ibuf = image_get_ibuf_multilayer(ima, iuser); + + } + else if (ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + /* UV testgrid or black or solid etc */ + if (ima->gen_x == 0) ima->gen_x = 1024; + if (ima->gen_y == 0) ima->gen_y = 1024; + ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, + color, &ima->colorspace_settings); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + ima->ok = IMA_OK_LOADED; + } + else if (ima->source == IMA_SRC_VIEWER) { + if (ima->type == IMA_TYPE_R_RESULT) { + /* always verify entirely, and potentially + * returns pointer to release later */ + ibuf = image_get_render_result(ima, iuser, lock_r); } - else if (ima->source == IMA_SRC_VIEWER) { - if (ima->type == IMA_TYPE_R_RESULT) { - /* always verify entirely, and potentially - * returns pointer to release later */ - ibuf = image_get_render_result(ima, iuser, lock_r); - } - else if (ima->type == IMA_TYPE_COMPOSITE) { - /* requires lock/unlock, otherwise don't return image */ - if (lock_r) { - /* unlock in BKE_image_release_ibuf */ - BLI_lock_thread(LOCK_VIEWER); - *lock_r = ima; - - /* XXX anim play for viewer nodes not yet supported */ - frame = 0; // XXX iuser?iuser->framenr:0; - ibuf = image_get_ibuf(ima, 0, frame); - - if (!ibuf) { - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); - image_assign_ibuf(ima, ibuf, 0, frame); - } + else if (ima->type == IMA_TYPE_COMPOSITE) { + /* requires lock/unlock, otherwise don't return image */ + if (lock_r) { + /* unlock in BKE_image_release_ibuf */ + BLI_lock_thread(LOCK_VIEWER); + *lock_r = ima; + + /* XXX anim play for viewer nodes not yet supported */ + frame = 0; // XXX iuser?iuser->framenr:0; + ibuf = image_get_ibuf(ima, 0, frame); + + if (!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); + image_assign_ibuf(ima, ibuf, 0, frame); } } } } - - BLI_unlock_thread(LOCK_IMAGE); } BKE_image_tag_time(ima); @@ -2886,23 +2874,79 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) return ibuf; } -void BKE_image_release_ibuf(Image *ima, void *lock) +/* return image buffer for given image and user + * + * - will lock render result if image type is render result and lock is not NULL + * - will return NULL if image type if render or composite result and lock is NULL + * + * references the result, BKE_image_release_ibuf should be used to de-reference + */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +{ + ImBuf *ibuf; + + BLI_spin_lock(&image_spin); + + ibuf = image_acquire_ibuf(ima, iuser, lock_r); + + if (ibuf) + IMB_refImBuf(ibuf); + + BLI_spin_unlock(&image_spin); + + return ibuf; +} + +void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) { - /* for getting image during threaded render / compositing, need to release */ - if (lock == ima) { - BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + if (lock) { + /* for getting image during threaded render / compositing, need to release */ + if (lock == ima) { + BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + } + else if (lock) { + RE_ReleaseResultImage(lock); /* render result */ + BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + } } - else if (lock) { - RE_ReleaseResultImage(lock); /* render result */ - BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + + if (ibuf) { + BLI_spin_lock(&image_spin); + IMB_freeImBuf(ibuf); + BLI_spin_unlock(&image_spin); } } -/* warning, this can allocate generated images */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) { - /* here (+fie_ima/2-1) makes sure that division happens correctly */ - return BKE_image_acquire_ibuf(ima, iuser, NULL); + ImBuf *ibuf; + + /* quick reject tests */ + if (ima == NULL) + return FALSE; + + if (iuser) { + if (iuser->ok == 0) + return FALSE; + } + else if (ima->ok == 0) + return FALSE; + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) { + BLI_spin_lock(&image_spin); + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) + ibuf = image_acquire_ibuf(ima, iuser, NULL); + + BLI_spin_unlock(&image_spin); + } + + return ibuf != NULL; } int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range) @@ -3020,7 +3064,7 @@ int BKE_image_has_alpha(struct Image *image) ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); planes = (ibuf ? ibuf->planes : 0); - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); if (planes == 32) return 1; @@ -3044,7 +3088,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 9deff12f124..eb0612a75bd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1520,7 +1520,9 @@ void test_idbutton(char *name) /* search for id */ idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2); - if (idtest) if (new_id(lb, idtest, name) == 0) id_sort_by_name(lb, idtest); + if (idtest && (new_id(lb, idtest, name) == 0)) { + id_sort_by_name(lb, idtest); + } } void text_idbutton(struct ID *id, char *text) diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 7d89678d36f..a2f6b3c1929 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -289,10 +289,10 @@ static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_f /* collapse loop with smaller AABB */ for (k = 0; k < tot_feather_point; k++) { if (k >= check_b && k <= cur_a) { - DO_MINMAX2(feather_points[k], min_a, max_a); + minmax_v2v2_v2(min_a, max_a, feather_points[k]); } else { - DO_MINMAX2(feather_points[k], min_b, max_b); + minmax_v2v2_v2(min_b, max_b, feather_points[k]); } } @@ -379,7 +379,7 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*fe int next = i + 1; float delta; - DO_MINMAX2(feather_points[i], min, max); + minmax_v2v2_v2(min, max, feather_points[i]); if (next == tot_feather_point) { if (spline->flag & MASK_SPLINE_CYCLIC) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 068059dc29a..fd5af6a20bb 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -3011,7 +3011,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, MLoop *l_iter = loopstart; float area, polynorm_local[3], (*vertexcos)[3]; const float *no = polynormal ? polynormal : polynorm_local; - BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); + BLI_array_fixedstack_declare(vertexcos, BM_DEFAULT_NGON_STACK_SIZE, mpoly->totloop, __func__); /* pack vertex cos into an array for area_poly_v3 */ for (i = 0; i < mpoly->totloop; i++, l_iter++) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9c7cbc42bdd..25b70ce1793 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -249,13 +249,13 @@ int modifier_couldBeCage(struct Scene *scene, ModifierData *md) modifier_supportsMapping(md)); } -int modifier_sameTopology(ModifierData *md) +int modifier_isSameTopology(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } -int modifier_nonGeometrical(ModifierData *md) +int modifier_isNonGeometrical(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type == eModifierTypeType_NonGeometrical); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 2d76484b60a..06b846a6df9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2184,6 +2184,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_normal(ttype); register_node_type_cmp_curve_vec(ttype); register_node_type_cmp_map_value(ttype); + register_node_type_cmp_map_range(ttype); register_node_type_cmp_normalize(ttype); register_node_type_cmp_filter(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6ec173a5908..47ca502d247 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -196,18 +196,18 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type) return TRUE; } -void BKE_object_link_modifiers(struct Object *ob, struct Object *from) +void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) { ModifierData *md; - BKE_object_free_modifiers(ob); + BKE_object_free_modifiers(ob_dst); - if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { /* only objects listed above can have modifiers and linking them to objects * which doesn't have modifiers stack is quite silly */ return; } - for (md = from->modifiers.first; md; md = md->next) { + for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = NULL; if (ELEM4(md->type, @@ -219,16 +219,18 @@ void BKE_object_link_modifiers(struct Object *ob, struct Object *from) continue; } - if (!BKE_object_support_modifier_type_check(ob, md->type)) + if (!BKE_object_support_modifier_type_check(ob_dst, md->type)) continue; nmd = modifier_new(md->type); + BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); modifier_copyData(md, nmd); - BLI_addtail(&ob->modifiers, nmd); + BLI_addtail(&ob_dst->modifiers, nmd); + modifier_unique_name(&ob_dst->modifiers, nmd); } - BKE_object_copy_particlesystems(ob, from); - BKE_object_copy_softbody(ob, from); + BKE_object_copy_particlesystems(ob_dst, ob_src); + BKE_object_copy_softbody(ob_dst, ob_src); /* TODO: smoke?, cloth? */ } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d645204d29c..93bf5a5c0b4 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3786,14 +3786,22 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co return 1; } -#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ - if ((event & mtex->mapto) & type) { pvalue = texture_value_blend(def, pvalue, value, texfac, blend); } (void)0 - -#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ - if (event & type) { if (pvalue < 0.0f) pvalue = 1.0f + pvalue; CLAMP(pvalue, 0.0f, 1.0f); } (void)0 - -#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ - if (event & type) { CLAMP(pvalue, -1.0f, 1.0f); } (void)0 +#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ + if ((event & mtex->mapto) & type) { \ + pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \ + } (void)0 + +#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ + if (event & type) { \ + if (pvalue < 0.0f) \ + pvalue = 1.0f + pvalue; \ + CLAMP(pvalue, 0.0f, 1.0f); \ + } (void)0 + +#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ + if (event & type) { \ + CLAMP(pvalue, -1.0f, 1.0f); \ + } (void)0 static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra) { @@ -3802,8 +3810,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti float value, rgba[4], texvec[3]; ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = - ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = - ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f; ptex->length = 1.0f - part->randlength * PSYS_FRAND(child_index + 26); ptex->length *= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f195b3d71b0..3f2eb32f61c 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2568,10 +2568,12 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) sbFreeSimulation(pid->calldata); else if (pid->type == PTCACHE_TYPE_PARTICLES) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); - /*else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) +#if 0 + else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) smokeModifier_reset(pid->calldata); else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) - smokeModifier_reset_turbulence(pid->calldata);*/ + smokeModifier_reset_turbulence(pid->calldata); +#endif else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 4f62732f5e6..9b1425584a7 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1045,7 +1045,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen /* always update layer, so that animating layers works (joshua july 2010) */ /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes - (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ + * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ // base->lay = ob->lay; } diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 469881020c1..0b7fdaa7c1d 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -139,6 +139,9 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * IMB_rect_from_float(ibuf3); } + if (out->rect_float) + IMB_colormanagement_assign_float_colorspace(out, context.scene->sequencer_colorspace_settings.name); + return out; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a947a48938e..e023a3e20ae 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2338,11 +2338,13 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float */ const short is_rendering = G.is_rendering; + const short is_background = G.background; const int do_seq_gl = G.is_rendering ? 0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ : (context.scene->r.seq_flag & R_SEQ_GL_PREV); int do_seq; int have_seq = FALSE; + int have_comp = FALSE; Scene *scene; int is_thread_main = BLI_thread_is_main(); @@ -2355,6 +2357,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float frame = scene->r.sfra + nr + seq->anim_startofs; have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first; + have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree; oldcfra = scene->r.cfra; scene->r.cfra = frame; @@ -2367,7 +2370,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float camera = scene->camera; } - if (have_seq == FALSE && camera == NULL) { + if (have_comp == FALSE && camera == NULL) { scene->r.cfra = oldcfra; return NULL; } @@ -2384,8 +2387,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float (void)oldmarkers; #endif - if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) - { + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2408,11 +2410,15 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float * * disable rendered preview for sequencer while rendering -- it's very much possible * that preview render will went into conflict with final render + * + * When rendering from command line renderer is called from main thread, in this + * case it's always safe to render scene here */ - if (!is_thread_main || is_rendering == FALSE) { + if (!is_thread_main || is_rendering == FALSE || is_background) { if (re == NULL) re = RE_NewRender(scene->id.name); + BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index 99e33594a3e..ff9774f85af 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -47,6 +47,7 @@ static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; static char *documentation = NULL; //static int doc_lines = 0; +/* TODO, replace with BLI_strncasecmp() */ static int txttl_cmp(const char *first, const char *second, int len) { int cmp, i; @@ -113,19 +114,18 @@ short texttool_text_is_active(Text *text) void texttool_suggest_add(const char *name, char type) { + const int len = strlen(name); + int cmp; SuggItem *newitem, *item; - int len, cmp; - newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + newitem = MEM_mallocN(sizeof(SuggItem) + len + 1, "SuggItem"); if (!newitem) { printf("Failed to allocate memory for suggestion.\n"); return; } newitem->name = (char *) (newitem + 1); - len = strlen(name); - strncpy(newitem->name, name, len); - newitem->name[len] = '\0'; + memcpy(newitem->name, name, len + 1); newitem->type = type; newitem->prev = newitem->next = NULL; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index d230cf8f1fe..e6339d07e66 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -96,17 +96,6 @@ * If the user moves the cursor the st containing that cursor should * be popped ... other st's retain their own top location. * - * Markers - * -- - * The mrk->flags define the behavior and relationships between markers. The - * upper two bytes are used to hold a group ID, the lower two are normal flags. If - * TMARK_EDITALL is set the group ID defines which other markers should be edited. - * - * The mrk->clr field is used to visually group markers where the flags may not - * match. A template system, for example, may allow editing of repeating tokens - * (in one group) but include other marked positions (in another group) all in the - * same template with the same color. - * * Undo * -- * Undo/Redo works by storing @@ -136,8 +125,7 @@ static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); -static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, const char *buf); +static void txt_undo_add_blockop(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); static void txt_delete_sel(Text *text); static void txt_make_dirty(Text *text); @@ -175,7 +163,6 @@ void BKE_text_free(Text *text) } BLI_freelistN(&text->lines); - BLI_freelistN(&text->markers); if (text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -203,7 +190,6 @@ Text *BKE_text_add(const char *name) ta->flags |= TXT_TABSTOSPACES; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line = (char *) MEM_mallocN(1, "textline_string"); @@ -399,7 +385,6 @@ Text *BKE_text_load(const char *file, const char *relpath) ta->id.us = 1; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; ta->curl = ta->sell = NULL; if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0) @@ -496,7 +481,6 @@ Text *BKE_text_copy(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY; tan->lines.first = tan->lines.last = NULL; - tan->markers.first = tan->markers.last = NULL; tan->curl = tan->sell = NULL; tan->nlines = ta->nlines; @@ -785,23 +769,6 @@ static void txt_curs_sel(Text *text, TextLine ***linep, int **charp) *linep = &text->sell; *charp = &text->selc; } -static void txt_curs_first(Text *text, TextLine **linep, int *charp) -{ - if (text->curl == text->sell) { - *linep = text->curl; - if (text->curc < text->selc) *charp = text->curc; - else *charp = text->selc; - } - else if (txt_get_span(text->lines.first, text->curl) < txt_get_span(text->lines.first, text->sell)) { - *linep = text->curl; - *charp = text->curc; - } - else { - *linep = text->sell; - *charp = text->selc; - } -} - /*****************************/ /* Cursor movement functions */ /*****************************/ @@ -843,13 +810,11 @@ void txt_move_up(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->prev) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); @@ -857,8 +822,6 @@ void txt_move_up(Text *text, short sel) if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SUP : UNDO_CUP); } else { txt_move_bol(text, sel); @@ -871,22 +834,17 @@ void txt_move_down(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->next) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); *linep = (*linep)->next; if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SDOWN : UNDO_CDOWN); } else { txt_move_eol(text, sel); @@ -898,7 +856,7 @@ void txt_move_down(Text *text, short sel) void txt_move_left(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing; + int *charp; int tabsize = 0, i = 0; if (!text) return; @@ -906,8 +864,6 @@ void txt_move_left(Text *text, short sel) else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == 0) { if ((*linep)->prev) { txt_move_up(text, sel); @@ -939,24 +895,19 @@ void txt_move_left(Text *text, short sel) } } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SLEFT : UNDO_CLEFT); - if (!sel) txt_pop_sel(text); } void txt_move_right(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing, do_tab = FALSE, i; + int *charp, do_tab = FALSE, i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == (*linep)->len) { if ((*linep)->next) { txt_move_down(text, sel); @@ -984,124 +935,103 @@ void txt_move_right(Text *text, short sel) else (*charp) += BLI_str_utf8_size((*linep)->line + *charp); } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SRIGHT : UNDO_CRIGHT); - if (!sel) txt_pop_sel(text); } void txt_jump_left(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_jump_right(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_move_bol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; - + *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_bof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.first; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.last; *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_toline(Text *text, unsigned int line, short sel) @@ -1112,16 +1042,14 @@ void txt_move_toline(Text *text, unsigned int line, short sel) /* Moves to a certain byte in a line, not a certain utf8-character! */ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) { - TextLine **linep, *oldl; - int *charp, oldc; + TextLine **linep; + int *charp; unsigned int i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - oldc = *charp; - oldl = *linep; *linep = text->lines.first; for (i = 0; i < line; i++) { @@ -1133,7 +1061,6 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) *charp = ch; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -1152,8 +1079,6 @@ static void txt_curs_swap(Text *text) tmpc = text->curc; text->curc = text->selc; text->selc = tmpc; - - if (!undoing) txt_undo_add_op(text, UNDO_SWAP); } static void txt_pop_first(Text *text) @@ -1164,12 +1089,6 @@ static void txt_pop_first(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1181,12 +1100,6 @@ static void txt_pop_last(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1222,9 +1135,7 @@ int txt_has_sel(Text *text) static void txt_delete_sel(Text *text) { TextLine *tmpl; - TextMarker *mrk; char *buf; - int move, lineno; if (!text) return; if (!text->curl) return; @@ -1236,33 +1147,11 @@ static void txt_delete_sel(Text *text) if (!undoing) { buf = txt_sel_to_buf(text); - txt_undo_add_block(text, UNDO_DBLOCK, buf); + txt_undo_add_blockop(text, UNDO_DBLOCK, buf); MEM_freeN(buf); } buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string"); - - if (text->curl != text->sell) { - txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); - move = txt_get_span(text->curl, text->sell); - } - else { - mrk = txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) - txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - move = 0; - } - - mrk = txt_find_marker_region(text, text->sell, text->selc - 1, text->sell->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno -= move; - if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; - mrk->end -= text->selc - text->curc; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } strncpy(buf, text->curl->line, text->curc); strcpy(buf + text->curc, text->sell->line + text->selc); @@ -1491,19 +1380,9 @@ char *txt_sel_to_buf(Text *text) return buf; } -static void txt_shift_markers(Text *text, int lineno, int count) -{ - TextMarker *marker; - - for (marker = text->markers.first; marker; marker = marker->next) - if (marker->lineno >= lineno) { - marker->lineno += count; - } -} - void txt_insert_buf(Text *text, const char *in_buffer) { - int l = 0, u, len, lineno = -1, count = 0; + int l = 0, u, len; size_t i = 0, j; TextLine *add; char *buffer; @@ -1517,7 +1396,7 @@ void txt_insert_buf(Text *text, const char *in_buffer) buffer = BLI_strdupn(in_buffer, len); len += txt_extended_ascii_as_utf8(&buffer); - if (!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer); + if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer); u = undoing; undoing = 1; @@ -1530,9 +1409,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) else { undoing = u; MEM_freeN(buffer); return; } i++; - /* Read as many full lines as we can */ - lineno = txt_get_span(text->lines.first, text->curl); - while (i < len) { l = 0; @@ -1544,14 +1420,8 @@ void txt_insert_buf(Text *text, const char *in_buffer) add = txt_new_linen(buffer + (i - l), l); BLI_insertlinkbefore(&text->lines, text->curl, add); i++; - count++; } else { - if (count) { - txt_shift_markers(text, lineno, count); - count = 0; - } - for (j = i - l; j < i && j < len; ) txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j)); break; @@ -1560,10 +1430,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) MEM_freeN(buffer); - if (count) { - txt_shift_markers(text, lineno, count); - } - undoing = u; } @@ -1599,6 +1465,7 @@ static void dump_buffer(Text *text) while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]); } +/* Note: this function is outdated and must be updated if needed for future use */ void txt_print_undo(Text *text) { int i = 0; @@ -1615,37 +1482,7 @@ void txt_print_undo(Text *text) while (i <= text->undo_pos) { op = text->undo_buf[i]; - if (op == UNDO_CLEFT) { - ops = "Cursor left"; - } - else if (op == UNDO_CRIGHT) { - ops = "Cursor right"; - } - else if (op == UNDO_CUP) { - ops = "Cursor up"; - } - else if (op == UNDO_CDOWN) { - ops = "Cursor down"; - } - else if (op == UNDO_SLEFT) { - ops = "Selection left"; - } - else if (op == UNDO_SRIGHT) { - ops = "Selection right"; - } - else if (op == UNDO_SUP) { - ops = "Selection up"; - } - else if (op == UNDO_SDOWN) { - ops = "Selection down"; - } - else if (op == UNDO_STO) { - ops = "Selection "; - } - else if (op == UNDO_CTO) { - ops = "Cursor "; - } - else if (op == UNDO_INSERT_1) { + if (op == UNDO_INSERT_1) { ops = "Insert ascii "; } else if (op == UNDO_INSERT_2) { @@ -1681,9 +1518,6 @@ void txt_print_undo(Text *text) else if (op == UNDO_DEL_4) { ops = "Delete unicode "; } - else if (op == UNDO_SWAP) { - ops = "Cursor swap"; - } else if (op == UNDO_DBLOCK) { ops = "Delete text block"; } @@ -1738,29 +1572,6 @@ void txt_print_undo(Text *text) } } } - else if (op == UNDO_STO || op == UNDO_CTO) { - i++; - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("to <%d, %d> ", linep, charp); - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("from <%d, %d>", linep, charp); - } else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) { i++; @@ -1811,16 +1622,6 @@ void txt_print_undo(Text *text) } } -static void txt_undo_add_op(Text *text, int op) -{ - if (!max_undo_test(text, 2)) - return; - - text->undo_pos++; - text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; -} - static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value) { undo_buf[*undo_pos] = (value) & 0xff; @@ -1841,17 +1642,41 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va (*undo_pos)++; } -static void txt_undo_add_block(Text *text, int op, const char *buf) +/* store the cur cursor to the undo buffer */ +static void txt_undo_store_cur(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl)); +} + +/* store the sel cursor to the undo buffer */ +static void txt_undo_store_sel(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell)); +} + +/* store both cursors to the undo buffer */ +static void txt_undo_store_cursors(Text *text) +{ + txt_undo_store_cur(text); + txt_undo_store_sel(text); +} + +/* store an operator along with a block of data */ +static void txt_undo_add_blockop(Text *text, int op, const char *buf) { unsigned int length = strlen(buf); - if (!max_undo_test(text, length + 11)) + if (!max_undo_test(text, length + 11 + 12)) return; text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length); strncpy(text->undo_buf + text->undo_pos, buf, length); @@ -1863,34 +1688,30 @@ static void txt_undo_add_block(Text *text, int op, const char *buf) text->undo_buf[text->undo_pos + 1] = 0; } -void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc) +/* store a regular operator */ +void txt_undo_add_op(Text *text, int op) { if (!max_undo_test(text, 15)) return; - if (froml == tol && fromc == toc) return; - text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml); - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol); + txt_undo_store_cursors(text); text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; } +/* store an operator for a single character */ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) { char utf8[BLI_UTF8_MAX]; size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8); - if (!max_undo_test(text, 3 + utf8_size)) + if (!max_undo_test(text, 3 + utf8_size + 12)) return; text->undo_pos++; @@ -1899,6 +1720,8 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) text->undo_buf[text->undo_pos] = op_start + utf8_size - 1; text->undo_pos++; + txt_undo_store_cur(text); + for (i = 0; i < utf8_size; i++) { text->undo_buf[text->undo_pos] = utf8[i]; text->undo_pos++; @@ -1909,6 +1732,9 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) else { text->undo_buf[text->undo_pos] = op_start + 3; text->undo_pos++; + + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c); text->undo_buf[text->undo_pos] = op_start + 3; } @@ -1934,6 +1760,29 @@ static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* read the cur cursor from the undo buffer */ +static void txt_undo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curln = txt_undo_read_uint32(undo_buf, undo_pos); + *curc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read the sel cursor from the undo buffer */ +static void txt_undo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selln = txt_undo_read_uint32(undo_buf, undo_pos); + *selc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read both cursors from the undo buffer */ +static void txt_undo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_undo_read_sel(undo_buf, undo_pos, selln, selc); + txt_undo_read_cur(undo_buf, undo_pos, curln, curc); +} + static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -1986,6 +1835,29 @@ static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* redo read cur cursor from the undo buffer */ +static void txt_redo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curc = txt_redo_read_uint16(undo_buf, undo_pos); + *curln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read sel cursor from the undo buffer */ +static void txt_redo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selc = txt_redo_read_uint16(undo_buf, undo_pos); + *selln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read both cursors from the undo buffer */ +static void txt_redo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_redo_read_cur(undo_buf, undo_pos, curln, curc); + txt_redo_read_sel(undo_buf, undo_pos, selln, selc); +} + static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -2024,9 +1896,10 @@ void txt_do_undo(Text *text) { int op = text->undo_buf[text->undo_pos]; unsigned int linep, i; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; unsigned short charp; - TextLine *holdl; - int holdc, holdln; char *buf; if (text->undo_pos < 0) { @@ -2038,88 +1911,60 @@ void txt_do_undo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_right(text, 0); - break; + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: + text->undo_pos -= op - UNDO_INSERT_1 + 1; - case UNDO_CRIGHT: - txt_move_left(text, 0); - break; + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - case UNDO_CUP: - txt_move_down(text, 0); - break; + txt_delete_char(text); - case UNDO_CDOWN: - txt_move_up(text, 0); - break; - - case UNDO_SLEFT: - txt_move_right(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_left(text, 1); - break; - - case UNDO_SUP: - txt_move_down(text, 1); + text->undo_pos--; break; - case UNDO_SDOWN: - txt_move_up(text, 1); - break; - - case UNDO_CTO: - case UNDO_STO: - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - - text->undo_pos--; - text->undo_pos--; - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: + charp = op - UNDO_BS_1 + 1; + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); - text->undo_pos--; - break; + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: - txt_backspace_char(text); - text->undo_pos -= op - UNDO_INSERT_1 + 1; - text->undo_pos--; - break; + txt_add_char(text, uchar); - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: - charp = op - UNDO_BS_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); text->undo_pos--; break; - - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: charp = op - UNDO_DEL_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_add_char(text, uchar); + txt_move_left(text, 0); - text->undo_pos--; - break; - case UNDO_SWAP: - txt_curs_swap(text); + text->undo_pos--; break; case UNDO_DBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "dblock buffer"); @@ -2128,34 +1973,33 @@ void txt_do_undo(Text *text) text->undo_pos--; } buf[i] = 0; - - txt_curs_first(text, &holdl, &holdc); - holdln = txt_get_span(text->lines.first, holdl); - - txt_insert_buf(text, buf); - MEM_freeN(buf); - - text->curl = text->lines.first; - while (holdln > 0) { - if (text->curl->next) - text->curl = text->curl->next; - - holdln--; - } - text->curc = holdc; + /* skip over the length that was stored again */ text->undo_pos--; text->undo_pos--; text->undo_pos--; text->undo_pos--; + /* Get the cursor positions */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + + /* move cur to location that needs buff inserted */ + txt_move_to(text, curln, curc, 0); + + txt_insert_buf(text, buf); + MEM_freeN(buf); + + /* restore the cursors */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + text->undo_pos--; break; case UNDO_IBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); /* txt_backspace_char removes utf8-characters, not bytes */ buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2167,47 +2011,32 @@ void txt_do_undo(Text *text) linep = txt_utf8_len(buf); MEM_freeN(buf); - while (linep > 0) { - txt_backspace_char(text); - linep--; - } - + /* skip over the length that was stored again */ text->undo_pos--; text->undo_pos--; - text->undo_pos--; text->undo_pos--; - text->undo_pos--; + + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc + linep, 1); + + txt_delete_selected(text); + text->undo_pos--; break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the end line of the selection - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the last char selected or text->line->len - - //set the selection for this now - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //first line to be selected - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //first postion to be selected - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_unindent(text); @@ -2221,37 +2050,24 @@ void txt_do_undo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_comment(text); } + else if (op == UNDO_DUPLICATE) { + txt_delete_line(text, text->curl->next); + } + else if (op == UNDO_MOVE_LINES_UP) { + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + txt_move_lines(text, TXT_MOVE_LINE_UP); + } text->undo_pos--; break; - case UNDO_DUPLICATE: - txt_delete_line(text, text->curl->next); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; break; } - - /* next undo step may need evaluating */ - if (text->undo_pos >= 0) { - switch (text->undo_buf[text->undo_pos]) { - case UNDO_STO: - txt_do_undo(text); - txt_do_redo(text); /* selections need restoring */ - break; - case UNDO_SWAP: - txt_do_undo(text); /* swaps should appear transparent */ - break; - } - } undoing = 0; } @@ -2259,9 +2075,12 @@ void txt_do_undo(Text *text) void txt_do_redo(Text *text) { char op; - unsigned int linep, i; - unsigned short charp; char *buf; + unsigned int linep; + unsigned short charp; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; text->undo_pos++; op = text->undo_buf[text->undo_pos]; @@ -2274,104 +2093,91 @@ void txt_do_redo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_left(text, 0); - break; - - case UNDO_CRIGHT: - txt_move_right(text, 0); - break; + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: + text->undo_pos++; - case UNDO_CUP: - txt_move_up(text, 0); - break; + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - case UNDO_CDOWN: - txt_move_down(text, 0); - break; - - case UNDO_SLEFT: - txt_move_left(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_right(text, 1); - break; - - case UNDO_SUP: - txt_move_up(text, 1); - break; - - case UNDO_SDOWN: - txt_move_down(text, 1); - break; - - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: - text->undo_pos++; charp = op - UNDO_INSERT_1 + 1; - txt_add_char(text, txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp)); - break; + uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: - text->undo_pos++; - txt_backspace_char(text); - text->undo_pos += op - UNDO_BS_1 + 1; + txt_add_char(text, uchar); break; - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: text->undo_pos++; - txt_delete_char(text); - text->undo_pos += op - UNDO_DEL_1 + 1; - break; - case UNDO_SWAP: - txt_curs_swap(text); - txt_do_redo(text); /* swaps should appear transparent a*/ - break; + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + text->undo_pos += op - UNDO_BS_1 + 1; - case UNDO_CTO: - case UNDO_STO: - text->undo_pos++; - text->undo_pos++; + /* move right so we backspace the correct char */ + txt_move_right(text, 0); + txt_backspace_char(text); - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; + break; + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: text->undo_pos++; - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } + text->undo_pos += op - UNDO_DEL_1 + 1; + + txt_delete_char(text); break; case UNDO_DBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); text->undo_pos += linep; + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + txt_delete_sel(text); + break; case UNDO_IBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2382,40 +2188,27 @@ void txt_do_redo(Text *text) txt_insert_buf(text, buf); MEM_freeN(buf); + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: text->undo_pos++; - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the first char selected or 0 - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the first line of the selection - //set the selcetion for this now - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //last postion to be selected - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //Last line to be selected - - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_indent(text); @@ -2429,15 +2222,28 @@ void txt_do_redo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_uncomment(text); } - break; - case UNDO_DUPLICATE: - txt_duplicate_line(text); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); + else if (op == UNDO_DUPLICATE) { + txt_duplicate_line(text); + } + else if (op == UNDO_MOVE_LINES_UP) { + /* offset the cursor by + 1 */ + txt_move_to(text, curln + 1, curc, 0); + txt_move_to(text, selln + 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_UP); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + /* offset the cursor by - 1 */ + txt_move_to(text, curln - 1, curc, 0); + txt_move_to(text, selln - 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + + /* re-restore the cursors since they got moved when redoing */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + break; default: //XXX error("Undo buffer error - resetting"); @@ -2456,31 +2262,13 @@ void txt_do_redo(Text *text) void txt_split_curline(Text *text) { TextLine *ins; - TextMarker *mrk; char *left, *right; - int lineno = -1; if (!text) return; if (!text->curl) return; txt_delete_sel(text); - /* Move markers */ - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (mrk->lineno == lineno && mrk->start > text->curc) { - mrk->lineno++; - mrk->start -= text->curc; - mrk->end -= text->curc; - } - else if (mrk->lineno > lineno) { - mrk->lineno++; - } - mrk = mrk->next; - } - /* Make the two half strings */ left = MEM_mallocN(text->curc + 1, "textline_string"); @@ -2517,23 +2305,9 @@ void txt_split_curline(Text *text) static void txt_delete_line(Text *text, TextLine *line) { - TextMarker *mrk = NULL, *nxt; - int lineno = -1; - if (!text) return; if (!text->curl) return; - lineno = txt_get_span(text->lines.first, line); - mrk = text->markers.first; - while (mrk) { - nxt = mrk->next; - if (mrk->lineno == lineno) - BLI_freelinkN(&text->markers, mrk); - else if (mrk->lineno > lineno) - mrk->lineno--; - mrk = nxt; - } - BLI_remlink(&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2548,25 +2322,12 @@ static void txt_delete_line(Text *text, TextLine *line) static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb) { char *tmp; - TextMarker *mrk = NULL; - int lineno = -1; - + if (!text) return; if (!linea || !lineb) return; - mrk = txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno--; - mrk->start += linea->len; - mrk->end += linea->len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } - if (lineno == -1) lineno = txt_get_span(text->lines.first, lineb); - + tmp = MEM_mallocN(linea->len + lineb->len + 1, "textline_string"); strcpy(tmp, linea->line); @@ -2619,27 +2380,7 @@ void txt_delete_char(Text *text) } else { /* Just deleting a char */ size_t c_len = 0; - TextMarker *mrk; c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->end == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } memmove(text->curl->line + text->curc, text->curl->line + text->curc + c_len, text->curl->len - text->curc - c_len + 1); @@ -2683,28 +2424,8 @@ void txt_backspace_char(Text *text) } else { /* Just backspacing a char */ size_t c_len = 0; - TextMarker *mrk; char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc); c = BLI_str_utf8_as_unicode_and_size(prev, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->start == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc - c_len) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } /* source and destination overlap, don't use memcpy() */ memmove(text->curl->line + text->curc - c_len, @@ -2746,9 +2467,7 @@ static void txt_convert_tab_to_spaces(Text *text) static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) { - int lineno; char *tmp, ch[BLI_UTF8_MAX]; - TextMarker *mrk; size_t add_len; if (!text) return 0; @@ -2767,16 +2486,9 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_delete_sel(text); + if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); + add_len = BLI_str_utf8_from_unicode(add, ch); - mrk = txt_find_marker_region(text, text->curl, text->curc - 1, text->curl->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - if (mrk->start > text->curc) mrk->start += add_len; - mrk->end += add_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } tmp = MEM_mallocN(text->curl->len + add_len + 1, "textline_string"); @@ -2793,7 +2505,6 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_make_dirty(text); txt_clean_text(text); - if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); return 1; } @@ -2824,10 +2535,7 @@ int txt_replace_char(Text *text, unsigned int add) /* If text is selected or we're at the end of the line just use txt_add_char */ if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') { - int i = txt_add_char(text, add); - TextMarker *mrk = txt_find_marker(text, text->curl, text->curc, 0, 0); - if (mrk) BLI_freelinkN(&text->markers, mrk); - return i; + return txt_add_char(text, add); } del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size); @@ -2854,8 +2562,8 @@ int txt_replace_char(Text *text, unsigned int add) /* Should probably create a new op for this */ if (!undoing) { - txt_undo_add_charop(text, UNDO_DEL_1, del); txt_undo_add_charop(text, UNDO_INSERT_1, add); + txt_undo_add_charop(text, UNDO_DEL_1, del); } return 1; } @@ -2924,7 +2632,7 @@ void txt_indent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_INDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_INDENT); } } @@ -2982,7 +2690,7 @@ void txt_unindent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNINDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNINDENT); } } @@ -3031,7 +2739,7 @@ void txt_comment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_COMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_COMMENT); } } @@ -3076,7 +2784,7 @@ void txt_uncomment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNCOMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNCOMMENT); } } @@ -3165,157 +2873,6 @@ int setcurr_tab_spaces(Text *text, int space) return i; } -/*********************************/ -/* Text marker utility functions */ -/*********************************/ - -/* Creates and adds a marker to the list maintaining sorted order */ -void txt_add_marker(Text *text, TextLine *line, int start, int end, const unsigned char color[4], int group, int flags) -{ - TextMarker *tmp, *marker; - - marker = MEM_mallocN(sizeof(TextMarker), "text_marker"); - - marker->lineno = txt_get_span(text->lines.first, line); - marker->start = MIN2(start, end); - marker->end = MAX2(start, end); - marker->group = group; - marker->flags = flags; - - marker->color[0] = color[0]; - marker->color[1] = color[1]; - marker->color[2] = color[2]; - marker->color[3] = color[3]; - - for (tmp = text->markers.last; tmp; tmp = tmp->prev) - if (tmp->lineno < marker->lineno || (tmp->lineno == marker->lineno && tmp->start < marker->start)) - break; - - if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); - else BLI_addhead(&text->markers, marker); -} - -/* Returns the first matching marker on the specified line between two points. - * If the group or flags fields are non-zero the returned flag must be in the - * specified group and have at least the specified flags set. */ -TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - return marker; - } - } - return NULL; -} - -/* Clears all markers on the specified line between two points. If the group or - * flags fields are non-zero the returned flag must be in the specified group - * and have at least the specified flags set. */ -short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Clears all markers in the specified group (if given) with at least the - * specified flags set. Useful for clearing temporary markers (group = 0, - * flags = TMARK_TEMP) */ -short txt_clear_markers(Text *text, int group, int flags) -{ - TextMarker *marker, *next; - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if ((!group || marker->group == group) && - (marker->flags & flags) == flags) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Finds the marker at the specified line and cursor position with at least the - * specified flags set in the given group (if non-zero). */ -TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) -{ - TextMarker *marker; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = marker->next) { - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if (marker->start <= curs && curs <= marker->end) - return marker; - } - return NULL; -} - -/* Finds the previous marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_prev_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->prev) tmp = tmp->prev; - else tmp = text->markers.last; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - -/* Finds the next marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_next_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->next) tmp = tmp->next; - else tmp = text->markers.first; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - - /*******************************/ /* Character utility functions */ /*******************************/ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index b174f27b7e1..30b48401046 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1124,10 +1124,10 @@ void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float { INIT_MINMAX2(min, max); - DO_MINMAX2(marker->pattern_corners[0], min, max); - DO_MINMAX2(marker->pattern_corners[1], min, max); - DO_MINMAX2(marker->pattern_corners[2], min, max); - DO_MINMAX2(marker->pattern_corners[3], min, max); + minmax_v2v2_v2(min, max, marker->pattern_corners[0]); + minmax_v2v2_v2(min, max, marker->pattern_corners[1]); + minmax_v2v2_v2(min, max, marker->pattern_corners[2]); + minmax_v2v2_v2(min, max, marker->pattern_corners[3]); } void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2]) @@ -3161,7 +3161,7 @@ static int stabilization_median_point_get(MovieTracking *tracking, int framenr, if (track->flag & TRACK_USE_2D_STAB) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - DO_MINMAX2(marker->pos, min, max); + minmax_v2v2_v2(min, max, marker->pos); ok = TRUE; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index da9c919c109..0f861a7ed37 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -111,6 +111,11 @@ static void delete_picture(AVFrame *f) } } +static int use_float_audio_buffer(int codec_id) +{ + return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS; +} + #ifdef WITH_AUDASPACE static int write_audio_frame(void) { @@ -599,12 +604,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex /* Prepare an audio stream for the output file */ -static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of) +static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) { AVStream *st; AVCodecContext *c; AVCodec *codec; + error[0] = '\0'; + st = av_new_stream(of, 1); if (!st) return NULL; @@ -616,6 +623,10 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->bit_rate = ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; c->channels = rd->ffcodecdata.audio_channels; + if (use_float_audio_buffer(codec_id)) { + c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + c->sample_fmt = AV_SAMPLE_FMT_FLT; + } codec = avcodec_find_encoder(c->codec_id); if (!codec) { //XXX error("Couldn't find a valid audio codec"); @@ -626,6 +637,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex if (avcodec_open(c, codec) < 0) { //XXX error("Couldn't initialize audio codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -646,7 +658,12 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + if (use_float_audio_buffer(codec_id)) { + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float)); + } + else { + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + } audio_time = 0.0f; @@ -801,9 +818,12 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (ffmpeg_audio_codec != CODEC_ID_NONE) { - audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); + audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error)); if (!audio_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); + if (error[0]) + BKE_report(reports, RPT_ERROR, error); + else + BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); av_dict_free(&opts); return 0; } @@ -943,7 +963,12 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, AVCodecContext *c = audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; - specs.format = AUD_FORMAT_S16; + if (use_float_audio_buffer(c->codec_id)) { + specs.format = AUD_FORMAT_FLOAT32; + } + else { + specs.format = AUD_FORMAT_S16; + } specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE |