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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2016-06-16 10:18:40 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-06-16 10:18:40 +0300
commite197ce618b2c8b063776e79d8f9304a7e65aec02 (patch)
tree61e3da1abfb5b1c80ab9cf478cf561983ddc28c7 /source/blender
parent926819d82f7ab63d03c65197fd59f14259fc08fa (diff)
parent57cff46cec9599e5897de72f45ce735da79db0ff (diff)
Merge branch 'master' into object_nodes
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c1
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c20
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c16
-rw-r--r--source/blender/blenkernel/intern/library_idmap.c6
-rw-r--r--source/blender/blenkernel/intern/movieclip.c6
-rw-r--r--source/blender/blenkernel/intern/node.c19
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c23
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c3
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c2
-rw-r--r--source/blender/blenlib/BLI_array_store_utils.h50
-rw-r--r--source/blender/blenlib/BLI_math_vector.h18
-rw-r--r--source/blender/blenlib/BLI_rand.h1
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c2
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c2
-rw-r--r--source/blender/blenlib/intern/array_store.c8
-rw-r--r--source/blender/blenlib/intern/array_store_utils.c103
-rw-r--r--source/blender/blenlib/intern/math_color_inline.c4
-rw-r--r--source/blender/blenlib/intern/math_vector.c117
-rw-r--r--source/blender/blenlib/intern/rand.c40
-rw-r--r--source/blender/blenloader/intern/writefile.c235
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c242
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.h9
-rw-r--r--source/blender/bmesh/operators/bmo_connect_concave.c11
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c21
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c224
-rw-r--r--source/blender/collada/MeshImporter.cpp25
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc5
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc100
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc1
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h9
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/curve/CMakeLists.txt1
-rw-r--r--source/blender/editors/curve/editcurve_paint.c2
-rw-r--r--source/blender/editors/curve/editfont.c58
-rw-r--r--source/blender/editors/curve/editfont_undo.c311
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c1
-rw-r--r--source/blender/editors/include/BIF_glutil.h1
-rw-r--r--source/blender/editors/include/ED_anim_api.h2
-rw-r--r--source/blender/editors/include/ED_curve.h6
-rw-r--r--source/blender/editors/include/ED_fileselect.h3
-rw-r--r--source/blender/editors/interface/interface_draw.c21
-rw-r--r--source/blender/editors/interface/interface_handlers.c50
-rw-r--r--source/blender/editors/interface/interface_icons.c6
-rw-r--r--source/blender/editors/interface/interface_panel.c6
-rw-r--r--source/blender/editors/interface/interface_templates.c5
-rw-r--r--source/blender/editors/interface/interface_widgets.c12
-rw-r--r--source/blender/editors/io/io_collada.c2
-rw-r--r--source/blender/editors/mask/mask_draw.c18
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c245
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c85
-rw-r--r--source/blender/editors/screen/glutil.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c4
-rw-r--r--source/blender/editors/space_clip/clip_draw.c52
-rw-r--r--source/blender/editors/space_file/filelist.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c18
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c20
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c108
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c6
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c2
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c25
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c31
-rw-r--r--source/blender/editors/space_view3d/drawobject.c43
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c2
-rw-r--r--source/blender/editors/transform/transform.c7
-rw-r--r--source/blender/editors/transform/transform_conversions.c60
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c4
-rw-r--r--source/blender/editors/transform/transform_snap_object.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c9
-rw-r--r--source/blender/gpu/GPU_basic_shader.h11
-rw-r--r--source/blender/gpu/GPU_draw.h19
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c34
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c29
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c6
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c5
-rw-r--r--source/blender/gpu/intern/gpu_draw.c28
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c4
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c2
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c3
-rw-r--r--source/blender/gpu/intern/gpu_material.c6
-rw-r--r--source/blender/gpu/intern/gpu_shader.c1
-rw-r--r--source/blender/gpu/intern/gpu_texture.c1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_vert.glsl10
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c7
-rw-r--r--source/blender/makesrna/intern/rna_pose.c4
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c144
-rw-r--r--source/blender/physics/intern/implicit_blender.c7
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c80
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c34
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c8
97 files changed, 2059 insertions, 1003 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index e928ab04fc2..2cbf98a2366 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -351,6 +351,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree);
struct bNodeTree *ntreeFromID(struct ID *id);
void ntreeMakeLocal(struct bNodeTree *ntree, bool id_in_mainlist);
+struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 09f4c286f48..db56c8d2aea 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -3945,7 +3945,6 @@ static void navmesh_drawColored(DerivedMesh *dm)
/* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */
{
DEBUG_VBO("Using legacy code. drawNavMeshColored\n");
- //glShadeModel(GL_SMOOTH);
glBegin(glmode = GL_QUADS);
for (a = 0; a < dm->numTessFaceData; a++, mface++) {
int new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 392a38773e7..267f7a65e00 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -464,7 +464,6 @@ static void cdDM_drawFacesSolid(
BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors,
setMaterial, false, false);
- glShadeModel(GL_FLAT);
return;
}
}
@@ -472,7 +471,6 @@ static void cdDM_drawFacesSolid(
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
GPU_triangle_setup(dm);
- glShadeModel(GL_SMOOTH);
for (a = 0; a < dm->drawObject->totmaterial; a++) {
if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
GPU_buffer_draw_elements(
@@ -481,8 +479,6 @@ static void cdDM_drawFacesSolid(
}
}
GPU_buffers_unbind();
-
- glShadeModel(GL_FLAT);
}
static void cdDM_drawFacesTex_common(
@@ -553,8 +549,7 @@ static void cdDM_drawFacesTex_common(
if (mloopcol) {
GPU_color_setup(dm, colType);
}
-
- glShadeModel(GL_SMOOTH);
+
/* lastFlag = 0; */ /* UNUSED */
for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
@@ -633,7 +628,6 @@ static void cdDM_drawFacesTex_common(
}
GPU_buffers_unbind();
- glShadeModel(GL_FLAT);
}
@@ -742,9 +736,6 @@ static void cdDM_drawMappedFaces(
}
}
}
-
-
- glShadeModel(GL_SMOOTH);
tot_tri_elem = dm->drawObject->tot_triangle_point;
@@ -841,7 +832,6 @@ static void cdDM_drawMappedFaces(
}
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glShadeModel(GL_FLAT);
GPU_buffers_unbind();
@@ -929,8 +919,6 @@ static void cdDM_drawMappedFacesGLSL(
matnr = -1;
do_draw = false;
- glShadeModel(GL_SMOOTH);
-
if (setDrawOptions != NULL) {
DMVertexAttribs attribs;
DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n");
@@ -1153,8 +1141,6 @@ static void cdDM_drawMappedFacesGLSL(
MEM_freeN(mat_orig_to_new);
MEM_freeN(matconv);
}
-
- glShadeModel(GL_FLAT);
}
static void cdDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial)
@@ -1203,8 +1189,6 @@ static void cdDM_drawMappedFacesMat(
matnr = -1;
- glShadeModel(GL_SMOOTH);
-
memset(&attribs, 0, sizeof(attribs));
glBegin(GL_TRIANGLES);
@@ -1260,8 +1244,6 @@ static void cdDM_drawMappedFacesMat(
cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal);
}
glEnd();
-
- glShadeModel(GL_FLAT);
}
static void cdDM_drawMappedEdges(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, void *userData)
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index ffd000eed88..c1013342bd9 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -1181,6 +1181,14 @@ static void emDM_drawMappedFaces(
/* if non zero we know a face was rendered */
if (poly_prev != GL_ZERO) glEnd();
+
+ if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) {
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ }
+
+ if (shade_prev == GL_FLAT) {
+ glShadeModel(GL_SMOOTH);
+ }
}
static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
@@ -1236,8 +1244,6 @@ static void emDM_drawFacesTex_common(
// dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */
/* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- glShadeModel(GL_SMOOTH);
-
BM_mesh_elem_index_ensure(bm, BM_FACE);
/* call again below is ok */
@@ -1384,8 +1390,6 @@ static void emDM_drawFacesTex_common(
}
}
}
-
- glShadeModel(GL_FLAT);
}
static void emDM_drawFacesTex(
@@ -1524,8 +1528,6 @@ static void emDM_drawMappedFacesGLSL(
vertexNos = bmdm->vertexNos;
polyNos = bmdm->polyNos;
- /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- glShadeModel(GL_SMOOTH);
BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
for (i = 0; i < em->tottri; i++) {
@@ -1636,8 +1638,6 @@ static void emDM_drawMappedFacesMat(
vertexNos = bmdm->vertexNos;
polyNos = bmdm->polyNos;
- /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- glShadeModel(GL_SMOOTH);
BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0));
for (i = 0; i < em->tottri; i++) {
diff --git a/source/blender/blenkernel/intern/library_idmap.c b/source/blender/blenkernel/intern/library_idmap.c
index fd78d9b23ce..66025c04332 100644
--- a/source/blender/blenkernel/intern/library_idmap.c
+++ b/source/blender/blenkernel/intern/library_idmap.c
@@ -88,8 +88,10 @@ struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain)
int index = 0;
while (index < MAX_LIBARRAY) {
- id_map->type_maps[index].map = NULL;
- id_map->type_maps[index].id_type = BKE_idcode_iter_step(&index);
+ struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index];
+ type_map->map = NULL;
+ type_map->id_type = BKE_idcode_iter_step(&index);
+ BLI_assert(type_map->id_type != 0);
}
BLI_assert(index == MAX_LIBARRAY);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index a8d3c600817..d2bfcfb0887 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -608,7 +608,7 @@ static MovieClip *movieclip_alloc(Main *bmain, const char *name)
return clip;
}
-static void movieclip_load_get_szie(MovieClip *clip)
+static void movieclip_load_get_size(MovieClip *clip)
{
int width, height;
MovieClipUser user = {0};
@@ -670,7 +670,7 @@ MovieClip *BKE_movieclip_file_add(Main *bmain, const char *name)
detect_clip_source(clip);
- movieclip_load_get_szie(clip);
+ movieclip_load_get_size(clip);
if (clip->lastsize[0]) {
int width = clip->lastsize[0];
@@ -1276,7 +1276,7 @@ void BKE_movieclip_reload(MovieClip *clip)
detect_clip_source(clip);
clip->lastsize[0] = clip->lastsize[1] = 0;
- movieclip_load_get_szie(clip);
+ movieclip_load_get_size(clip);
movieclip_calc_length(clip);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 27f8fb85527..3e446469b1c 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2428,15 +2428,20 @@ void ntreeInterfaceTypeUpdate(bNodeTree *ntree)
/* ************ find stuff *************** */
+bNode *ntreeFindType(const bNodeTree *ntree, int type) {
+ if (ntree) {
+ for (bNode * node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == type) {
+ return node;
+ }
+ }
+ }
+ return NULL;
+}
+
bool ntreeHasType(const bNodeTree *ntree, int type)
{
- bNode *node;
-
- if (ntree)
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->type == type)
- return true;
- return false;
+ return ntreeFindType(ntree, type) != NULL;
}
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index f6bddfa6f99..0d7fe04a1e4 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -392,22 +392,25 @@ static int distribute_binary_search(float *sum, int n, float value)
{
int mid, low = 0, high = n - 1;
+ if (high == low)
+ return low;
+
if (sum[low] >= value)
return low;
- if (sum[high] < value)
+ if (sum[high - 1] < value)
return high;
while (low < high) {
mid = (low + high) / 2;
- if ((sum[mid] < value) && (sum[mid + 1] >= value))
+ if ((sum[mid] >= value) && (sum[mid - 1] < value))
return mid;
- if (sum[mid] >= value) {
+ if (sum[mid] > value) {
high = mid - 1;
}
- else if (sum[mid] < value) {
+ else {
low = mid + 1;
}
}
@@ -1024,7 +1027,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* Calculate cumulative weights.
* We remove all null-weighted elements from element_sum, and create a new mapping
* 'activ'_elem_index -> orig_elem_index.
- * This simplifies greatly the filtering of zero-weighted items - and can be much mor efficient
+ * This simplifies greatly the filtering of zero-weighted items - and can be much more efficient
* especially in random case (reducing a lot the size of binary-searched array)...
*/
float *element_sum = MEM_mallocN(sizeof(*element_sum) * totmapped, __func__);
@@ -1047,13 +1050,13 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* Finally assign elements to particles */
if ((part->flag & PART_TRAND) || (part->simplify_flag & PART_SIMPLIFY_ENABLE)) {
- float pos;
-
for (p = 0; p < totpart; p++) {
- /* In theory element_sum[totelem - 1] should be 1.0,
+ /* In theory element_sum[totmapped - 1] should be 1.0,
* but due to float errors this is not necessarily always true, so scale pos accordingly. */
- pos = BLI_frand() * element_sum[totmapped - 1];
- particle_element[p] = element_map[distribute_binary_search(element_sum, totmapped, pos)];
+ const float pos = BLI_frand() * element_sum[totmapped - 1];
+ const int eidx = distribute_binary_search(element_sum, totmapped, pos);
+ particle_element[p] = element_map[eidx];
+ BLI_assert(pos <= element_sum[eidx] && pos > (eidx ? element_sum[eidx - 1] : 0.0f));
jitter_offset[particle_element[p]] = pos;
}
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 88bc3fb9854..b0d19320230 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2619,7 +2619,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
if (BKE_pbvh_has_faces(ccgdm->pbvh)) {
BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL,
setMaterial, false, fast);
- glShadeModel(GL_FLAT);
}
return;
@@ -3164,7 +3163,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
MEM_freeN(matconv);
}
- glShadeModel(GL_FLAT);
+ glShadeModel(GL_SMOOTH);
}
static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial)
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index 3c2444b0ef1..a40e4f72636 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -529,7 +529,7 @@ typedef struct AccessCacheKey {
static unsigned int accesscache_hashhash(const void *key_v)
{
const AccessCacheKey *key = (const AccessCacheKey *) key_v;
- /* TODP(sergey): Need better hasing here for faster frame access. */
+ /* TODP(sergey): Need better hashing here for faster frame access. */
return key->clip_index << 16 | key->frame;
}
diff --git a/source/blender/blenlib/BLI_array_store_utils.h b/source/blender/blenlib/BLI_array_store_utils.h
new file mode 100644
index 00000000000..6b2a28846f4
--- /dev/null
+++ b/source/blender/blenlib/BLI_array_store_utils.h
@@ -0,0 +1,50 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ARRAY_STORE_UTILS_H__
+#define __BLI_ARRAY_STORE_UTILS_H__
+
+/** \file BLI_array_store_utils.h
+ * \ingroup bli
+ */
+
+struct BArrayStore;
+
+struct BArrayStore_AtSize {
+ struct BArrayStore **stride_table;
+ int stride_table_len;
+};
+
+BArrayStore *BLI_array_store_at_size_ensure(
+ struct BArrayStore_AtSize *bs_stride,
+ const int stride, const int chunk_size);
+
+BArrayStore *BLI_array_store_at_size_get(
+ struct BArrayStore_AtSize *bs_stride,
+ const int stride);
+
+void BLI_array_store_at_size_clear(
+ struct BArrayStore_AtSize *bs_stride);
+
+void BLI_array_store_at_size_calc_memory_usage(
+ struct BArrayStore_AtSize *bs_stride,
+ size_t *r_size_expanded, size_t *r_size_compacted);
+
+#endif /* __BLI_ARRAY_STORE_UTILS_H__ */
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 5f76b79b298..25f485a25aa 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -282,18 +282,18 @@ void angle_poly_v3(float *angles, const float *verts[3], int len);
/********************************* Geometry **********************************/
-void project_v2_v2v2(float c[2], const float v1[2], const float v2[2]);
-void project_v3_v3v3(float r[3], const float p[3], const float n[3]);
-void project_plane_v3_v3v3(float c[3], const float v[3], const float v_plane[3]);
-void project_plane_v2_v2v2(float c[2], const float v[2], const float v_plane[2]);
-void project_v3_plane(float v[3], const float n[3], const float p[3]);
-void reflect_v3_v3v3(float r[3], const float v[3], const float n[3]);
+void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2]);
+void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3]);
+void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3]);
+void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2]);
+void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3]);
+void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3]);
void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3]);
-void ortho_v3_v3(float p[3], const float v[3]);
-void ortho_v2_v2(float p[2], const float v[2]);
+void ortho_v3_v3(float out[3], const float v[3]);
+void ortho_v2_v2(float out[2], const float v[2]);
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
-void rotate_normalized_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
+void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle);
/*********************************** Other ***********************************/
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index c86c9ae84d7..4b535706ef6 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -49,6 +49,7 @@ void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1);
void BLI_rng_seed(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1);
void BLI_rng_srandom(struct RNG *rng, unsigned int seed) ATTR_NONNULL(1);
+void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len) ATTR_NONNULL(1, 2);
int BLI_rng_get_int(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
unsigned int BLI_rng_get_uint(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 9c0731ce612..90aa45b13af 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -53,6 +53,7 @@ set(SRC
intern/BLI_mempool.c
intern/DLRB_tree.c
intern/array_store.c
+ intern/array_store_utils.c
intern/array_utils.c
intern/astar.c
intern/boxpack2d.c
@@ -123,6 +124,7 @@ set(SRC
BLI_args.h
BLI_array.h
BLI_array_store.h
+ BLI_array_store_utils.h
BLI_array_utils.h
BLI_astar.h
BLI_bitmap.h
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 06946e520a8..f943a8119c4 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -69,7 +69,7 @@ const unsigned int hashsizes[] = {
/**
* \note Max load #GHASH_LIMIT_GROW used to be 3. (pre 2.74).
- * Python uses 0.6666, tommyhaslib even goes down to 0.5.
+ * Python uses 0.6666, tommyhashlib even goes down to 0.5.
* Reducing our from 3 to 0.75 gives huge speedup (about twice quicker pure GHash insertions/lookup,
* about 25% - 30% quicker 'dynamic-topology' stroke drawing e.g.).
* Min load #GHASH_LIMIT_SHRINK is a quarter of max load, to avoid resizing to quickly.
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index b7a51f2c48e..783dba5510c 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -622,7 +622,7 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
iter->curindex = 0;
iter->curchunk = iter->curchunk->next;
if (iter->curchunk == NULL) {
- return NULL;
+ return (ret->freeword == FREEWORD) ? NULL : ret;
}
curnode = CHUNK_DATA(iter->curchunk);
}
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 9baccf38fa3..33565596c1f 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -36,7 +36,7 @@
*
* This diagram is an overview of the structure of a single array-store.
*
- * \note The only 2 structues here which are referenced externally are the.
+ * \note The only 2 structures here which are referenced externally are the.
*
* - BArrayStore: The whole array store.
* - BArrayState: Represents a single state (array) of data.
@@ -92,7 +92,7 @@
* First matches at either end of the array are detected.
* For identical arrays this is all thats needed.
*
- * De-duplication is performed on any remaining chunks, by hasing the first few bytes of the chunk
+ * De-duplication is performed on any remaining chunks, by hashing the first few bytes of the chunk
* (see: BCHUNK_HASH_TABLE_ACCUMULATE_STEPS).
*
* \note This is cached for reuse since the referenced data never changes.
@@ -650,7 +650,7 @@ static void bchunk_list_append_data(
* Use for adding arrays of arbitrary sized memory at once.
*
* \note This function takes care not to perform redundant chunk-merging checks,
- * so we can write succesive fixed size chunks quickly.
+ * so we can write successive fixed size chunks quickly.
*/
static void bchunk_list_append_data_n(
const BArrayInfo *info, BArrayMemory *bs_mem,
@@ -1680,7 +1680,7 @@ void *BLI_array_store_state_data_get_alloc(
/** \} */
-/** \name Debigging API (for testing).
+/** \name Debugging API (for testing).
* \{ */
/* only for test validation */
diff --git a/source/blender/blenlib/intern/array_store_utils.c b/source/blender/blenlib/intern/array_store_utils.c
new file mode 100644
index 00000000000..83cd28ddf11
--- /dev/null
+++ b/source/blender/blenlib/intern/array_store_utils.c
@@ -0,0 +1,103 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/array_store_utils.c
+ * \ingroup bli
+ * \brief Helper functions for BLI_array_store API.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_array_store.h"
+#include "BLI_array_store_utils.h" /* own include */
+
+#include "BLI_math_base.h"
+
+BArrayStore *BLI_array_store_at_size_ensure(
+ struct BArrayStore_AtSize *bs_stride,
+ const int stride, const int chunk_size)
+{
+ if (bs_stride->stride_table_len < stride) {
+ bs_stride->stride_table_len = stride;
+ bs_stride->stride_table = MEM_recallocN(bs_stride->stride_table, sizeof(*bs_stride->stride_table) * stride);
+ }
+ BArrayStore **bs_p = &bs_stride->stride_table[stride - 1];
+
+ if ((*bs_p) == NULL) {
+#if 0
+ unsigned int chunk_count = chunk_size;
+#else
+ /* calculate best chunk-count to fit a power of two */
+ unsigned int chunk_count = chunk_size;
+ {
+ unsigned int size = chunk_count * stride;
+ size = power_of_2_max_u(size);
+ size = MEM_SIZE_OPTIMAL(size);
+ chunk_count = size / stride;
+ }
+#endif
+
+ (*bs_p) = BLI_array_store_create(stride, chunk_count);
+ }
+ return *bs_p;
+}
+
+BArrayStore *BLI_array_store_at_size_get(
+ struct BArrayStore_AtSize *bs_stride,
+ const int stride)
+{
+ BLI_assert(stride > 0 && stride <= bs_stride->stride_table_len);
+ return bs_stride->stride_table[stride - 1];
+}
+
+void BLI_array_store_at_size_clear(
+ struct BArrayStore_AtSize *bs_stride)
+{
+ for (int i = 0; i < bs_stride->stride_table_len; i += 1) {
+ if (bs_stride->stride_table[i]) {
+ BLI_array_store_destroy(bs_stride->stride_table[i]);
+ }
+ }
+
+ MEM_freeN(bs_stride->stride_table);
+ bs_stride->stride_table = NULL;
+ bs_stride->stride_table_len = 0;
+}
+
+
+void BLI_array_store_at_size_calc_memory_usage(
+ struct BArrayStore_AtSize *bs_stride,
+ size_t *r_size_expanded, size_t *r_size_compacted)
+{
+ size_t size_compacted = 0;
+ size_t size_expanded = 0;
+ for (int i = 0; i < bs_stride->stride_table_len; i++) {
+ BArrayStore *bs = bs_stride->stride_table[i];
+ if (bs) {
+ size_compacted += BLI_array_store_calc_size_compacted_get(bs);
+ size_expanded += BLI_array_store_calc_size_expanded_get(bs);
+ }
+ }
+
+ *r_size_expanded = size_expanded;
+ *r_size_compacted = size_compacted;
+}
diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c
index 180d62105c4..abb8ff35a45 100644
--- a/source/blender/blenlib/intern/math_color_inline.c
+++ b/source/blender/blenlib/intern/math_color_inline.c
@@ -65,7 +65,7 @@ MALWAYS_INLINE __m128 linearrgb_to_srgb_v4_simd(const __m128 c)
MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
{
- float r[4] = {srgb[0], srgb[1], srgb[2], 0.0f};
+ float r[4] = {srgb[0], srgb[1], srgb[2], 1.0f};
__m128 *rv = (__m128 *)&r;
*rv = srgb_to_linearrgb_v4_simd(*rv);
linear[0] = r[0];
@@ -75,7 +75,7 @@ MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
{
- float r[4] = {linear[0], linear[1], linear[2], 0.0f};
+ float r[4] = {linear[0], linear[1], linear[2], 1.0f};
__m128 *rv = (__m128 *)&r;
*rv = linearrgb_to_srgb_v4_simd(*rv);
srgb[0] = r[0];
diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c
index 7f2db3743df..988034349e0 100644
--- a/source/blender/blenlib/intern/math_vector.c
+++ b/source/blender/blenlib/intern/math_vector.c
@@ -585,23 +585,27 @@ void angle_poly_v3(float *angles, const float *verts[3], int len)
/********************************* Geometry **********************************/
-/* Project v1 on v2 */
-void project_v2_v2v2(float c[2], const float v1[2], const float v2[2])
+/**
+ * Project \a p onto \a v_proj
+ */
+void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2])
{
- const float mul = dot_v2v2(v1, v2) / dot_v2v2(v2, v2);
+ const float mul = dot_v2v2(p, v_proj) / dot_v2v2(v_proj, v_proj);
- c[0] = mul * v2[0];
- c[1] = mul * v2[1];
+ out[0] = mul * v_proj[0];
+ out[1] = mul * v_proj[1];
}
-/* Project v1 on v2 */
-void project_v3_v3v3(float c[3], const float v1[3], const float v2[3])
+/**
+ * Project \a p onto \a v_proj
+ */
+void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
{
- const float mul = dot_v3v3(v1, v2) / dot_v3v3(v2, v2);
+ const float mul = dot_v3v3(p, v_proj) / dot_v3v3(v_proj, v_proj);
- c[0] = mul * v2[0];
- c[1] = mul * v2[1];
- c[2] = mul * v2[2];
+ out[0] = mul * v_proj[0];
+ out[1] = mul * v_proj[1];
+ out[2] = mul * v_proj[2];
}
/**
@@ -617,35 +621,35 @@ void project_v3_v3v3(float c[3], const float v1[3], const float v2[3])
* sub_v3_v3v3(c, v, c);
* \endcode
*/
-void project_plane_v3_v3v3(float c[3], const float v[3], const float v_plane[3])
+void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
{
- const float mul = dot_v3v3(v, v_plane) / dot_v3v3(v_plane, v_plane);
+ const float mul = dot_v3v3(p, v_plane) / dot_v3v3(v_plane, v_plane);
- c[0] = v[0] - (mul * v_plane[0]);
- c[1] = v[1] - (mul * v_plane[1]);
- c[2] = v[2] - (mul * v_plane[2]);
+ out[0] = p[0] - (mul * v_plane[0]);
+ out[1] = p[1] - (mul * v_plane[1]);
+ out[2] = p[2] - (mul * v_plane[2]);
}
-void project_plane_v2_v2v2(float c[2], const float v[2], const float v_plane[2])
+void project_plane_v2_v2v2(float out[2], const float p[2], const float v_plane[2])
{
- const float mul = dot_v2v2(v, v_plane) / dot_v2v2(v_plane, v_plane);
+ const float mul = dot_v2v2(p, v_plane) / dot_v2v2(v_plane, v_plane);
- c[0] = v[0] - (mul * v_plane[0]);
- c[1] = v[1] - (mul * v_plane[1]);
+ out[0] = p[0] - (mul * v_plane[0]);
+ out[1] = p[1] - (mul * v_plane[1]);
}
/* project a vector on a plane defined by normal and a plane point p */
-void project_v3_plane(float v[3], const float n[3], const float p[3])
+void project_v3_plane(float out[3], const float plane_no[3], const float plane_co[3])
{
float vector[3];
float mul;
- sub_v3_v3v3(vector, v, p);
- mul = dot_v3v3(vector, n) / len_squared_v3(n);
+ sub_v3_v3v3(vector, out, plane_co);
+ mul = dot_v3v3(vector, plane_no) / len_squared_v3(plane_no);
- mul_v3_v3fl(vector, n, mul);
+ mul_v3_v3fl(vector, plane_no, mul);
- sub_v3_v3(v, vector);
+ sub_v3_v3(out, vector);
}
/* Returns a vector bisecting the angle at v2 formed by v1, v2 and v3 */
@@ -664,15 +668,15 @@ void bisect_v3_v3v3v3(float out[3], const float v1[3], const float v2[3], const
* Returns a reflection vector from a vector and a normal vector
* reflect = vec - ((2 * DotVecs(vec, mirror)) * mirror)
*/
-void reflect_v3_v3v3(float out[3], const float vec[3], const float normal[3])
+void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3])
{
- const float dot2 = 2.0f * dot_v3v3(vec, normal);
+ const float dot2 = 2.0f * dot_v3v3(v, normal);
BLI_ASSERT_UNIT_V3(normal);
- out[0] = vec[0] - (dot2 * normal[0]);
- out[1] = vec[1] - (dot2 * normal[1]);
- out[2] = vec[2] - (dot2 * normal[2]);
+ out[0] = v[0] - (dot2 * normal[0]);
+ out[1] = v[1] - (dot2 * normal[1]);
+ out[2] = v[2] - (dot2 * normal[2]);
}
/**
@@ -710,27 +714,27 @@ void ortho_basis_v3v3_v3(float r_n1[3], float r_n2[3], const float n[3])
*
* \note return vector won't maintain same length.
*/
-void ortho_v3_v3(float p[3], const float v[3])
+void ortho_v3_v3(float out[3], const float v[3])
{
const int axis = axis_dominant_v3_single(v);
- BLI_assert(p != v);
+ BLI_assert(out != v);
switch (axis) {
case 0:
- p[0] = -v[1] - v[2];
- p[1] = v[0];
- p[2] = v[0];
+ out[0] = -v[1] - v[2];
+ out[1] = v[0];
+ out[2] = v[0];
break;
case 1:
- p[0] = v[1];
- p[1] = -v[0] - v[2];
- p[2] = v[1];
+ out[0] = v[1];
+ out[1] = -v[0] - v[2];
+ out[2] = v[1];
break;
case 2:
- p[0] = v[2];
- p[1] = v[2];
- p[2] = -v[0] - v[1];
+ out[0] = v[2];
+ out[1] = v[2];
+ out[2] = -v[0] - v[1];
break;
}
}
@@ -738,18 +742,19 @@ void ortho_v3_v3(float p[3], const float v[3])
/**
* no brainer compared to v3, just have for consistency.
*/
-void ortho_v2_v2(float p[2], const float v[2])
+void ortho_v2_v2(float out[2], const float v[2])
{
- BLI_assert(p != v);
+ BLI_assert(out != v);
- p[0] = -v[1];
- p[1] = v[0];
+ out[0] = -v[1];
+ out[1] = v[0];
}
-/* Rotate a point p by angle theta around an arbitrary axis r
+/**
+ * Rotate a point \a p by \a angle around an arbitrary unit length \a axis.
* http://local.wasp.uwa.edu.au/~pbourke/geometry/
*/
-void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
+void rotate_normalized_v3_v3v3fl(float out[3], const float p[3], const float axis[3], const float angle)
{
const float costheta = cosf(angle);
const float sintheta = sinf(angle);
@@ -757,17 +762,17 @@ void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[
/* double check they are normalized */
BLI_ASSERT_UNIT_V3(axis);
- r[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) +
- (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) +
- (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]);
+ out[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) +
+ (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) +
+ (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]);
- r[1] = (((1 - costheta) * axis[0] * axis[1] + axis[2] * sintheta) * p[0]) +
- ((costheta + (1 - costheta) * axis[1] * axis[1]) * p[1]) +
- (((1 - costheta) * axis[1] * axis[2] - axis[0] * sintheta) * p[2]);
+ out[1] = (((1 - costheta) * axis[0] * axis[1] + axis[2] * sintheta) * p[0]) +
+ ((costheta + (1 - costheta) * axis[1] * axis[1]) * p[1]) +
+ (((1 - costheta) * axis[1] * axis[2] - axis[0] * sintheta) * p[2]);
- r[2] = (((1 - costheta) * axis[0] * axis[2] - axis[1] * sintheta) * p[0]) +
- (((1 - costheta) * axis[1] * axis[2] + axis[0] * sintheta) * p[1]) +
- ((costheta + (1 - costheta) * axis[2] * axis[2]) * p[2]);
+ out[2] = (((1 - costheta) * axis[0] * axis[2] - axis[1] * sintheta) * p[0]) +
+ (((1 - costheta) * axis[1] * axis[2] + axis[0] * sintheta) * p[1]) +
+ ((costheta + (1 - costheta) * axis[2] * axis[2]) * p[2]);
}
void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c
index 1b42ab78ad6..73315d6a725 100644
--- a/source/blender/blenlib/intern/rand.c
+++ b/source/blender/blenlib/intern/rand.c
@@ -46,6 +46,7 @@
#define MULTIPLIER 0x5DEECE66Dll
#define MASK 0x0000FFFFFFFFFFFFll
+#define MASK_BYTES 2
#define ADDEND 0xB
#define LOWSEED 0x330E
@@ -107,6 +108,45 @@ BLI_INLINE void rng_step(RNG *rng)
rng->X = (MULTIPLIER * rng->X + ADDEND) & MASK;
}
+void BLI_rng_get_char_n(RNG *rng, char *bytes, size_t bytes_len)
+{
+ size_t last_len = 0;
+ size_t trim_len = bytes_len;
+
+#define RAND_STRIDE (sizeof(rng->X) - MASK_BYTES)
+
+ if (trim_len > RAND_STRIDE) {
+ last_len = trim_len % RAND_STRIDE;
+ trim_len = trim_len - last_len;
+ }
+ else {
+ trim_len = 0;
+ last_len = bytes_len;
+ }
+
+ const char *data_src = (void *)&(rng->X);
+ size_t i = 0;
+ while (i != trim_len) {
+ BLI_assert(i < trim_len);
+#ifdef __BIG_ENDIAN__
+ for (size_t j = (RAND_STRIDE + MASK_BYTES) - 1; j != MASK_BYTES - 1; j--)
+#else
+ for (size_t j = 0; j != RAND_STRIDE; j++)
+#endif
+ {
+ bytes[i++] = data_src[j];
+ }
+ rng_step(rng);
+ }
+ if (last_len) {
+ for (size_t j = 0; j != last_len; j++) {
+ bytes[i++] = data_src[j];
+ }
+ }
+
+#undef RAND_STRIDE
+}
+
int BLI_rng_get_int(RNG *rng)
{
rng_step(rng);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 60a546ec3ee..45f4e59f86d 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -588,6 +588,14 @@ void IDP_WriteProperty(IDProperty *prop, void *wd)
IDP_WriteProperty_OnlyData(prop, wd);
}
+static void write_iddata(void *wd, ID *id)
+{
+ /* ID_WM's id->properties are considered runtime only, and never written in .blend file. */
+ if (id->properties && !ELEM(GS(id->name), ID_WM)) {
+ IDP_WriteProperty(id->properties, wd);
+ }
+}
+
static void write_previews(WriteData *wd, PreviewImage *prv)
{
/* Never write previews when doing memsave (i.e. undo/redo)! */
@@ -716,8 +724,8 @@ static void write_actions(WriteData *wd, ListBase *idbase)
for (act=idbase->first; act; act= act->id.next) {
if (act->id.us>0 || wd->current) {
writestruct(wd, ID_AC, "bAction", 1, act);
- if (act->id.properties) IDP_WriteProperty(act->id.properties, wd);
-
+ write_iddata(wd, &act->id);
+
write_fcurves(wd, &act->curves);
for (grp=act->groups.first; grp; grp=grp->next) {
@@ -1153,7 +1161,8 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
if (part->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_PA, "ParticleSettings", 1, part);
- if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
+ write_iddata(wd, &part->id);
+
if (part->adt) write_animdata(wd, part->adt);
writestruct(wd, DATA, "PartDeflect", 1, part->pd);
writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
@@ -1666,11 +1675,8 @@ static void write_objects(WriteData *wd, ListBase *idbase)
if (ob->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_OB, "Object", 1, ob);
-
- /* Write ID Properties -- and copy this comment EXACTLY for easy finding
- * of library blocks that implement this.*/
- if (ob->id.properties) IDP_WriteProperty(ob->id.properties, wd);
-
+ write_iddata(wd, &ob->id);
+
if (ob->adt) write_animdata(wd, ob->adt);
/* direct data */
@@ -1741,7 +1747,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase)
if (vf->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_VF, "VFont", 1, vf);
- if (vf->id.properties) IDP_WriteProperty(vf->id.properties, wd);
+ write_iddata(wd, &vf->id);
/* direct data */
@@ -1767,8 +1773,8 @@ static void write_keys(WriteData *wd, ListBase *idbase)
if (key->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_KE, "Key", 1, key);
- if (key->id.properties) IDP_WriteProperty(key->id.properties, wd);
-
+ write_iddata(wd, &key->id);
+
if (key->adt) write_animdata(wd, key->adt);
/* direct data */
@@ -1795,8 +1801,8 @@ static void write_cameras(WriteData *wd, ListBase *idbase)
if (cam->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_CA, "Camera", 1, cam);
- if (cam->id.properties) IDP_WriteProperty(cam->id.properties, wd);
-
+ write_iddata(wd, &cam->id);
+
if (cam->adt) write_animdata(wd, cam->adt);
}
@@ -1814,7 +1820,7 @@ static void write_mballs(WriteData *wd, ListBase *idbase)
if (mb->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_MB, "MetaBall", 1, mb);
- if (mb->id.properties) IDP_WriteProperty(mb->id.properties, wd);
+ write_iddata(wd, &mb->id);
/* direct data */
writedata(wd, DATA, sizeof(void *)*mb->totcol, mb->mat);
@@ -1840,10 +1846,10 @@ static void write_curves(WriteData *wd, ListBase *idbase)
if (cu->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_CU, "Curve", 1, cu);
-
+ write_iddata(wd, &cu->id);
+
/* direct data */
writedata(wd, DATA, sizeof(void *)*cu->totcol, cu->mat);
- if (cu->id.properties) IDP_WriteProperty(cu->id.properties, wd);
if (cu->adt) write_animdata(wd, cu->adt);
if (cu->vfont) {
@@ -2035,9 +2041,9 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
+ write_iddata(wd, &mesh->id);
/* direct data */
- if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd);
if (mesh->adt) write_animdata(wd, mesh->adt);
writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
@@ -2093,9 +2099,9 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
#endif
writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh);
+ write_iddata(wd, &mesh->id);
/* direct data */
- if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd);
if (mesh->adt) write_animdata(wd, mesh->adt);
writedata(wd, DATA, sizeof(void *)*mesh->totcol, mesh->mat);
@@ -2148,8 +2154,8 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
if (lt->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_LT, "Lattice", 1, lt);
- if (lt->id.properties) IDP_WriteProperty(lt->id.properties, wd);
-
+ write_iddata(wd, &lt->id);
+
/* write animdata */
if (lt->adt) write_animdata(wd, lt->adt);
@@ -2182,7 +2188,7 @@ static void write_images(WriteData *wd, ListBase *idbase)
/* write LibData */
writestruct(wd, ID_IM, "Image", 1, ima);
- if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd);
+ write_iddata(wd, &ima->id);
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
writestruct(wd, DATA, "ImagePackedFile", 1, imapf);
@@ -2216,7 +2222,7 @@ static void write_textures(WriteData *wd, ListBase *idbase)
if (tex->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_TE, "Tex", 1, tex);
- if (tex->id.properties) IDP_WriteProperty(tex->id.properties, wd);
+ write_iddata(wd, &tex->id);
if (tex->adt) write_animdata(wd, tex->adt);
@@ -2256,13 +2262,8 @@ static void write_materials(WriteData *wd, ListBase *idbase)
if (ma->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_MA, "Material", 1, ma);
-
- /* Write ID Properties -- and copy this comment EXACTLY for easy finding
- * of library blocks that implement this.*/
- /* manually set head group property to IDP_GROUP, just in case it hadn't been
- * set yet :) */
- if (ma->id.properties) IDP_WriteProperty(ma->id.properties, wd);
-
+ write_iddata(wd, &ma->id);
+
if (ma->adt) write_animdata(wd, ma->adt);
for (a=0; a<MAX_MTEX; a++) {
@@ -2294,8 +2295,8 @@ static void write_worlds(WriteData *wd, ListBase *idbase)
if (wrld->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_WO, "World", 1, wrld);
- if (wrld->id.properties) IDP_WriteProperty(wrld->id.properties, wd);
-
+ write_iddata(wd, &wrld->id);
+
if (wrld->adt) write_animdata(wd, wrld->adt);
for (a=0; a<MAX_MTEX; a++) {
@@ -2324,8 +2325,8 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
if (la->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_LA, "Lamp", 1, la);
- if (la->id.properties) IDP_WriteProperty(la->id.properties, wd);
-
+ write_iddata(wd, &la->id);
+
if (la->adt) write_animdata(wd, la->adt);
/* direct data */
@@ -2409,8 +2410,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
while (sce) {
/* write LibData */
writestruct(wd, ID_SCE, "Scene", 1, sce);
- if (sce->id.properties) IDP_WriteProperty(sce->id.properties, wd);
-
+ write_iddata(wd, &sce->id);
+
if (sce->adt) write_animdata(wd, sce->adt);
write_keyingsets(wd, &sce->keyingsets);
@@ -2591,7 +2592,8 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
if (gpd->id.us>0 || wd->current) {
/* write gpd data block to file */
writestruct(wd, ID_GD, "bGPdata", 1, gpd);
-
+ write_iddata(wd, &gpd->id);
+
if (gpd->adt) write_animdata(wd, gpd->adt);
/* write grease-pencil layers to file */
@@ -2620,7 +2622,8 @@ static void write_windowmanagers(WriteData *wd, ListBase *lb)
for (wm= lb->first; wm; wm= wm->id.next) {
writestruct(wd, ID_WM, "wmWindowManager", 1, wm);
-
+ write_iddata(wd, &wm->id);
+
for (win= wm->windows.first; win; win= win->next) {
writestruct(wd, DATA, "wmWindow", 1, win);
writestruct(wd, DATA, "Stereo3dFormat", 1, win->stereo3d_format);
@@ -2720,9 +2723,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
/* write LibData */
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
writestruct(wd, ID_SCRN, "Screen", 1, sc);
- if (sc->id.properties)
- IDP_WriteProperty(sc->id.properties, wd);
-
+ write_iddata(wd, &sc->id);
+
/* direct data */
for (sv= sc->vertbase.first; sv; sv= sv->next)
writestruct(wd, DATA, "ScrVert", 1, sv);
@@ -2877,63 +2879,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
mywrite(wd, MYWRITE_FLUSH, 0);
}
-static void write_libraries(WriteData *wd, Main *main)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- ID *id;
- int a, tot;
- bool found_one;
-
- for (; main; main= main->next) {
-
- a=tot= set_listbasepointers(main, lbarray);
-
- /* test: is lib being used */
- if (main->curlib && main->curlib->packedfile)
- found_one = true;
- else {
- found_one = false;
- while (tot--) {
- for (id= lbarray[tot]->first; id; id= id->next) {
- if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
- found_one = true;
- break;
- }
- }
- if (found_one) break;
- }
- }
-
- /* to be able to restore quit.blend and temp saves, the packed blend has to be in undo buffers... */
- /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the]
- * quit.blend and temp saves */
- if (found_one) {
- writestruct(wd, ID_LI, "Library", 1, main->curlib);
-
- if (main->curlib->packedfile) {
- PackedFile *pf = main->curlib->packedfile;
- writestruct(wd, DATA, "PackedFile", 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- if (wd->current == NULL)
- printf("write packed .blend: %s\n", main->curlib->name);
- }
-
- while (a--) {
- for (id= lbarray[a]->first; id; id= id->next) {
- if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
- if (!BKE_idcode_is_linkable(GS(id->name))) {
- printf("ERROR: write file: datablock '%s' from lib '%s' is not linkable "
- "but is flagged as directly linked", id->name, main->curlib->filepath);
- BLI_assert(0);
- }
- writestruct(wd, ID_ID, "ID", 1, id);
- }
- }
- }
- }
- }
-}
-
static void write_bone(WriteData *wd, Bone *bone)
{
Bone* cbone;
@@ -2966,7 +2911,7 @@ static void write_armatures(WriteData *wd, ListBase *idbase)
while (arm) {
if (arm->id.us>0 || wd->current) {
writestruct(wd, ID_AR, "bArmature", 1, arm);
- if (arm->id.properties) IDP_WriteProperty(arm->id.properties, wd);
+ write_iddata(wd, &arm->id);
if (arm->adt) write_animdata(wd, arm->adt);
@@ -2995,8 +2940,9 @@ static void write_texts(WriteData *wd, ListBase *idbase)
/* write LibData */
writestruct(wd, ID_TXT, "Text", 1, text);
+ write_iddata(wd, &text->id);
+
if (text->name) writedata(wd, DATA, strlen(text->name)+1, text->name);
- if (text->id.properties) IDP_WriteProperty(text->id.properties, wd);
if (!(text->flags & TXT_ISEXT)) {
/* now write the text data, in two steps for optimization in the readfunction */
@@ -3030,7 +2976,7 @@ static void write_speakers(WriteData *wd, ListBase *idbase)
if (spk->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_SPK, "Speaker", 1, spk);
- if (spk->id.properties) IDP_WriteProperty(spk->id.properties, wd);
+ write_iddata(wd, &spk->id);
if (spk->adt) write_animdata(wd, spk->adt);
}
@@ -3049,7 +2995,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase)
if (sound->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_SO, "bSound", 1, sound);
- if (sound->id.properties) IDP_WriteProperty(sound->id.properties, wd);
+ write_iddata(wd, &sound->id);
if (sound->packedfile) {
pf = sound->packedfile;
@@ -3073,7 +3019,7 @@ static void write_groups(WriteData *wd, ListBase *idbase)
if (group->id.us>0 || wd->current) {
/* write LibData */
writestruct(wd, ID_GR, "Group", 1, group);
- if (group->id.properties) IDP_WriteProperty(group->id.properties, wd);
+ write_iddata(wd, &group->id);
write_previews(wd, group->preview);
@@ -3093,11 +3039,11 @@ static void write_nodetrees(WriteData *wd, ListBase *idbase)
for (ntree=idbase->first; ntree; ntree= ntree->id.next) {
if (ntree->id.us>0 || wd->current) {
writestruct(wd, ID_NT, "bNodeTree", 1, ntree);
+ /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
+ * be linked, etc., so we write actual id data here only, for 'real' ID trees. */
+ write_iddata(wd, &ntree->id);
+
write_nodetree(wd, ntree);
-
- if (ntree->id.properties) IDP_WriteProperty(ntree->id.properties, wd);
-
- if (ntree->adt) write_animdata(wd, ntree->adt);
}
}
}
@@ -3176,8 +3122,8 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
for (brush=idbase->first; brush; brush= brush->id.next) {
if (brush->id.us>0 || wd->current) {
writestruct(wd, ID_BR, "Brush", 1, brush);
- if (brush->id.properties) IDP_WriteProperty(brush->id.properties, wd);
-
+ write_iddata(wd, &brush->id);
+
if (brush->curve)
write_curvemapping(wd, brush->curve);
if (brush->gradient)
@@ -3194,7 +3140,7 @@ static void write_palettes(WriteData *wd, ListBase *idbase)
if (palette->id.us > 0 || wd->current) {
PaletteColor *color;
writestruct(wd, ID_PAL, "Palette", 1, palette);
- if (palette->id.properties) IDP_WriteProperty(palette->id.properties, wd);
+ write_iddata(wd, &palette->id);
for (color = palette->colors.first; color; color= color->next)
writestruct(wd, DATA, "PaletteColor", 1, color);
@@ -3209,9 +3155,9 @@ static void write_paintcurves(WriteData *wd, ListBase *idbase)
for (pc = idbase->first; pc; pc = pc->id.next) {
if (pc->id.us > 0 || wd->current) {
writestruct(wd, ID_PC, "PaintCurve", 1, pc);
+ write_iddata(wd, &pc->id);
writestruct(wd, DATA, "PaintCurvePoint", pc->tot_points, pc->points);
- if (pc->id.properties) IDP_WriteProperty(pc->id.properties, wd);
}
}
}
@@ -3261,10 +3207,9 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
if (clip->id.us>0 || wd->current) {
MovieTracking *tracking= &clip->tracking;
MovieTrackingObject *object;
- writestruct(wd, ID_MC, "MovieClip", 1, clip);
- if (clip->id.properties)
- IDP_WriteProperty(clip->id.properties, wd);
+ writestruct(wd, ID_MC, "MovieClip", 1, clip);
+ write_iddata(wd, &clip->id);
if (clip->adt)
write_animdata(wd, clip->adt);
@@ -3302,6 +3247,7 @@ static void write_masks(WriteData *wd, ListBase *idbase)
MaskLayer *masklay;
writestruct(wd, ID_MSK, "Mask", 1, mask);
+ write_iddata(wd, &mask->id);
if (mask->adt)
write_animdata(wd, mask->adt);
@@ -3607,8 +3553,8 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
if (linestyle->id.us>0 || wd->current) {
writestruct(wd, ID_LS, "FreestyleLineStyle", 1, linestyle);
- if (linestyle->id.properties)
- IDP_WriteProperty(linestyle->id.properties, wd);
+ write_iddata(wd, &linestyle->id);
+
if (linestyle->adt)
write_animdata(wd, linestyle->adt);
write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
@@ -3626,6 +3572,65 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
}
}
+/* Keep it last of write_foodata functions. */
+static void write_libraries(WriteData *wd, Main *main)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a, tot;
+ bool found_one;
+
+ for (; main; main= main->next) {
+
+ a=tot= set_listbasepointers(main, lbarray);
+
+ /* test: is lib being used */
+ if (main->curlib && main->curlib->packedfile)
+ found_one = true;
+ else {
+ found_one = false;
+ while (tot--) {
+ for (id= lbarray[tot]->first; id; id= id->next) {
+ if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
+ found_one = true;
+ break;
+ }
+ }
+ if (found_one) break;
+ }
+ }
+
+ /* to be able to restore quit.blend and temp saves, the packed blend has to be in undo buffers... */
+ /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the]
+ * quit.blend and temp saves */
+ if (found_one) {
+ writestruct(wd, ID_LI, "Library", 1, main->curlib);
+ write_iddata(wd, &main->curlib->id);
+
+ if (main->curlib->packedfile) {
+ PackedFile *pf = main->curlib->packedfile;
+ writestruct(wd, DATA, "PackedFile", 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
+ if (wd->current == NULL)
+ printf("write packed .blend: %s\n", main->curlib->name);
+ }
+
+ while (a--) {
+ for (id= lbarray[a]->first; id; id= id->next) {
+ if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
+ if (!BKE_idcode_is_linkable(GS(id->name))) {
+ printf("ERROR: write file: datablock '%s' from lib '%s' is not linkable "
+ "but is flagged as directly linked", id->name, main->curlib->filepath);
+ BLI_assert(0);
+ }
+ writestruct(wd, ID_ID, "ID", 1, id);
+ }
+ }
+ }
+ }
+ }
+}
+
/* context is usually defined by WM, two cases where no WM is available:
* - for forward compatibility, curscreen has to be saved
* - for undofile, curscene needs to be saved */
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 3fe888736f0..d6ca7239e39 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -904,7 +904,7 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
}
else if (ese->htype == BM_FACE) {
BMFace *efa = (BMFace *)ese->ele;
- BM_face_calc_plane(efa, r_plane);
+ BM_face_calc_tangent_auto(efa, r_plane);
}
}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 62b29e61d08..79051a2490f 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -286,64 +286,258 @@ float BM_face_calc_perimeter(const BMFace *f)
return perimeter;
}
-void BM_vert_tri_calc_plane(BMVert *verts[3], float r_plane[3])
+/**
+ * Utility function to calculate the edge which is most different from the other two.
+ *
+ * \return The first edge index, where the second vertex is ``(index + 1) % 3``.
+ */
+static int bm_vert_tri_find_unique_edge(BMVert *verts[3])
{
- float lens[3];
+ /* find the most 'unique' loop, (greatest difference to others) */
+#if 1
+ /* optimized version that avoids sqrt */
float difs[3];
- int order[3] = {0, 1, 2};
+ for (int i_prev = 1, i_curr = 2, i_next = 0;
+ i_next < 3;
+ i_prev = i_curr, i_curr = i_next++)
+ {
+ const float *co = verts[i_curr]->co;
+ const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co};
+ float proj_dir[3];
+ mid_v3_v3v3(proj_dir, co_other[0], co_other[1]);
+ sub_v3_v3(proj_dir, co);
+
+ float proj_pair[2][3];
+ project_v3_v3v3(proj_pair[0], co_other[0], proj_dir);
+ project_v3_v3v3(proj_pair[1], co_other[1], proj_dir);
+ difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]);
+ }
+#else
+ const float lens[3] = {
+ len_v3v3(verts[0]->co, verts[1]->co),
+ len_v3v3(verts[1]->co, verts[2]->co),
+ len_v3v3(verts[2]->co, verts[0]->co),
+ };
+ const float difs[3] = {
+ fabsf(lens[1] - lens[2]),
+ fabsf(lens[2] - lens[0]),
+ fabsf(lens[0] - lens[1]),
+ };
+#endif
- lens[0] = len_v3v3(verts[0]->co, verts[1]->co);
- lens[1] = len_v3v3(verts[1]->co, verts[2]->co);
- lens[2] = len_v3v3(verts[2]->co, verts[0]->co);
+ int order[3] = {0, 1, 2};
+ axis_sort_v3(difs, order);
- /* find the shortest or the longest loop */
- difs[0] = fabsf(lens[1] - lens[2]);
- difs[1] = fabsf(lens[2] - lens[0]);
- difs[2] = fabsf(lens[0] - lens[1]);
+ return order[0];
+}
- axis_sort_v3(difs, order);
- sub_v3_v3v3(r_plane, verts[order[0]]->co, verts[(order[0] + 1) % 3]->co);
+/**
+ * Calculate a tangent from any 3 vertices.
+ *
+ * The tangent aligns to the most *unique* edge
+ * (the edge most unlike the other two).
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
+void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3])
+{
+ const int index = bm_vert_tri_find_unique_edge(verts);
+
+ sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co);
+
+ normalize_v3(r_tangent);
}
/**
- * Compute a meaningful direction along the face (use for manipulator axis).
- * \note result isnt normalized.
+ * Calculate a tangent from any 3 vertices,
+ *
+ * The tangent follows the center-line formed by the most unique edges center
+ * and the opposite vertex.
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
*/
-void BM_face_calc_plane(const BMFace *f, float r_plane[3])
+void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3])
+{
+ const int index = bm_vert_tri_find_unique_edge(verts);
+
+ const float *v_a = verts[index]->co;
+ const float *v_b = verts[(index + 1) % 3]->co;
+ const float *v_other = verts[(index + 2) % 3]->co;
+
+ mid_v3_v3v3(r_tangent, v_a, v_b);
+ sub_v3_v3v3(r_tangent, v_other, r_tangent);
+
+ normalize_v3(r_tangent);
+}
+
+/**
+ * Compute the tanget of the face, using the longest edge.
+ */
+void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
+{
+ const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
+
+ sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co);
+
+ normalize_v3(r_tangent);
+
+}
+
+/**
+ * Compute the tanget of the face, using the two longest disconected edges.
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
+void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
{
if (f->len == 3) {
BMVert *verts[3];
BM_face_as_array_vert_tri((BMFace *)f, verts);
- BM_vert_tri_calc_plane(verts, r_plane);
+ BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent);
}
else if (f->len == 4) {
+ /* Use longest edge pair */
BMVert *verts[4];
float vec[3], vec_a[3], vec_b[3];
- // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4);
BM_face_as_array_vert_quad((BMFace *)f, verts);
sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co);
sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co);
- add_v3_v3v3(r_plane, vec_a, vec_b);
+ add_v3_v3v3(r_tangent, vec_a, vec_b);
sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co);
sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co);
add_v3_v3v3(vec, vec_a, vec_b);
- /* use the biggest edge length */
- if (len_squared_v3(r_plane) < len_squared_v3(vec)) {
- copy_v3_v3(r_plane, vec);
+ /* use the longest edge length */
+ if (len_squared_v3(r_tangent) < len_squared_v3(vec)) {
+ copy_v3_v3(r_tangent, vec);
}
}
else {
- const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
+ /* For ngons use two longest disconnected edges */
+ BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f);
+ BMLoop *l_long_other = NULL;
- sub_v3_v3v3(r_plane, l_long->v->co, l_long->next->v->co);
+ float len_max_sq = 0.0f;
+ float vec_a[3], vec_b[3];
+
+ BMLoop *l_iter = l_long->prev->prev;
+ BMLoop *l_last = l_long->next;
+
+ do {
+ const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co);
+ if (len_sq >= len_max_sq) {
+ l_long_other = l_iter;
+ len_max_sq = len_sq;
+ }
+ } while ((l_iter = l_iter->prev) != l_last);
+
+ sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co);
+ sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co);
+ add_v3_v3v3(r_tangent, vec_a, vec_b);
+
+ /* Edges may not be opposite side of the ngon,
+ * this could cause problems for ngons with multiple-aligned edges of the same length.
+ * Fallback to longest edge. */
+ if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) {
+ normalize_v3_v3(r_tangent, vec_a);
+ }
}
+}
- normalize_v3(r_plane);
+/**
+ * Compute the tanget of the face, using the edge farthest away from any vertex in the face.
+ *
+ * \param r_tangent: Calculated unit length tangent (return value).
+ */
+void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
+{
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* incase of degenerate faces */
+ zero_v3(r_tangent);
+
+ /* warning: O(n^2) loop here, take care! */
+ float dist_max_sq = 0.0f;
+ do {
+ BMLoop *l_iter_other = l_iter->next;
+ BMLoop *l_iter_last = l_iter->prev;
+ do {
+ BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co));
+ float co_other[3], vec[3];
+ closest_to_line_segment_v3(co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co);
+ sub_v3_v3v3(vec, l_iter->v->co, co_other);
+
+ const float dist_sq = len_squared_v3(vec);
+ if (dist_sq > dist_max_sq) {
+ dist_max_sq = dist_sq;
+ copy_v3_v3(r_tangent, vec);
+ }
+ } while ((l_iter_other = l_iter_other->next) != l_iter_last);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ normalize_v3(r_tangent);
+}
+
+/**
+ * Compute the tanget of the face, using longest distance between vertices on the face.
+ *
+ * \note The logic is almost identical to #BM_face_calc_tangent_edge_diagonal
+ */
+void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
+{
+ BMLoop *l_iter, *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ /* incase of degenerate faces */
+ zero_v3(r_tangent);
+
+ /* warning: O(n^2) loop here, take care! */
+ float dist_max_sq = 0.0f;
+ do {
+ BMLoop *l_iter_other = l_iter->next;
+ do {
+ float vec[3];
+ sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co);
+
+ const float dist_sq = len_squared_v3(vec);
+ if (dist_sq > dist_max_sq) {
+ dist_max_sq = dist_sq;
+ copy_v3_v3(r_tangent, vec);
+ }
+ } while ((l_iter_other = l_iter_other->next) != l_iter);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ normalize_v3(r_tangent);
+}
+
+/**
+ * Compute a meaningful direction along the face (use for manipulator axis).
+ *
+ * \note Callers shouldn't depend on the *exact* method used here.
+ */
+void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3])
+{
+ if (f->len == 3) {
+ /* most 'unique' edge of a triangle */
+ BMVert *verts[3];
+ BM_face_as_array_vert_tri((BMFace *)f, verts);
+ BM_vert_tri_calc_tangent_edge(verts, r_tangent);
+ }
+ else if (f->len == 4) {
+ /* longest edge pair of a quad */
+ BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent);
+ }
+ else {
+ /* longest edge of an ngon */
+ BM_face_calc_tangent_edge((BMFace *)f, r_tangent);
+ }
}
/**
diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h
index 8f0df81af73..1e50a504875 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.h
+++ b/source/blender/bmesh/intern/bmesh_polygon.h
@@ -45,7 +45,11 @@ float BM_face_calc_normal_vcos(
float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) ATTR_NONNULL();
float BM_face_calc_area(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_face_calc_perimeter(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void BM_face_calc_plane(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_edge(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
+void BM_face_calc_tangent_auto(const BMFace *f, float r_plane[3]) ATTR_NONNULL();
void BM_face_calc_center_bounds(const BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_calc_center_mean(const BMFace *f, float center[3]) ATTR_NONNULL();
void BM_face_calc_center_mean_vcos(
@@ -90,6 +94,7 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) ATTR_NONNULL();
void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) ATTR_NONNULL();
void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) ATTR_NONNULL();
-void BM_vert_tri_calc_plane(BMVert *verts[3], float r_plane[3]);
+void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3]);
+void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3]);
#endif /* __BMESH_POLYGON_H__ */
diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c
index 34f59aad4f1..8b9c60ada52 100644
--- a/source/blender/bmesh/operators/bmo_connect_concave.c
+++ b/source/blender/bmesh/operators/bmo_connect_concave.c
@@ -85,7 +85,7 @@ static bool bm_face_split_by_concave(
BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
const int quad_method = 0, ngon_method = 0; /* beauty */
- LinkNode *r_faces_double = NULL;
+ LinkNode *faces_double = NULL;
float normal[3];
BLI_assert(f_base->len > 3);
@@ -96,7 +96,7 @@ static bool bm_face_split_by_concave(
bm, f_base,
faces_array, &faces_array_tot,
edges_array, &edges_array_tot,
- &r_faces_double,
+ &faces_double,
quad_method, ngon_method, false,
pf_arena,
pf_heap, pf_ehash);
@@ -163,6 +163,13 @@ static bool bm_face_split_by_concave(
BLI_heap_clear(pf_heap, NULL);
BLI_edgehash_clear_ex(pf_ehash, NULL, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ while (faces_double) {
+ LinkNode *next = faces_double->next;
+ BM_face_kill(bm, faces_double->link);
+ MEM_freeN(faces_double);
+ faces_double = next;
+ }
+
return true;
}
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index a1f40b31fc7..c58b4814726 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -224,22 +224,13 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op)
if (v1 == v2) {
BMO_elem_flag_enable(bm, e, EDGE_COL);
}
- else if (!BM_edge_exists(v1, v2)) {
- BMEdge *e_new = BM_edge_create(bm, v1, v2, e, BM_CREATE_NOP);
-
- /* low level selection, not essential but means we can keep
- * edge selection valid on auto-merge for example. */
- if ((BM_elem_flag_test(e, BM_ELEM_SELECT) == true) &&
- (BM_elem_flag_test(e_new, BM_ELEM_SELECT) == false))
- {
- BM_elem_flag_disable(e, BM_ELEM_SELECT);
- BM_elem_flag_merge_into(e_new, e_new, e);
- BM_elem_flag_enable(e_new, BM_ELEM_SELECT);
- /* bm->totedgesel remains valid */
- }
- else {
- BM_elem_flag_merge_into(e_new, e_new, e);
+ else {
+ /* always merge flags, even for edges we already created */
+ BMEdge *e_new = BM_edge_exists(v1, v2);
+ if (e_new == NULL) {
+ e_new = BM_edge_create(bm, v1, v2, e, BM_CREATE_NOP);
}
+ BM_elem_flag_merge(e_new, e);
}
BMO_elem_flag_enable(bm, e, ELE_DEL);
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index 0a5e5aba86b..fe8b132a2a5 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -34,6 +34,14 @@
#include "BLI_math.h"
#include "BLI_quadric.h"
#include "BLI_heap.h"
+#include "BLI_linklist.h"
+#include "BLI_alloca.h"
+#include "BLI_memarena.h"
+#include "BLI_edgehash.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_polyfill2d_beautify.h"
+#include "BLI_stackdefines.h"
+
#include "BKE_customdata.h"
@@ -55,12 +63,10 @@
/* if the cost from #BLI_quadric_evaluate is 'noise', fallback to topology */
#define USE_TOPOLOGY_FALLBACK
#ifdef USE_TOPOLOGY_FALLBACK
-# define TOPOLOGY_FALLBACK_EPS FLT_EPSILON
+/* cost is calculated with double precision, it's ok to use a very small epsilon, see T48154. */
+# define TOPOLOGY_FALLBACK_EPS 1e-12f
#endif
-/* these checks are for rare cases that we can't avoid since they are valid meshes still */
-#define USE_SAFETY_CHECKS
-
#define BOUNDARY_PRESERVE_WEIGHT 100.0f
#define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */
#define COST_INVALID FLT_MAX
@@ -472,12 +478,58 @@ static int *bm_edge_symmetry_map(BMesh *bm, unsigned int symmetry_axis, float li
*
* \return true if any faces were triangulated.
*/
+static bool bm_face_triangulate(
+ BMesh *bm, BMFace *f_base, LinkNode **r_faces_double, int *r_edges_tri_tot,
-static bool bm_decim_triangulate_begin(BMesh *bm)
+ MemArena *pf_arena,
+ /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */
+ struct Heap *pf_heap, struct EdgeHash *pf_ehash)
+{
+ const int f_base_len = f_base->len;
+ int faces_array_tot = f_base_len - 3;
+ int edges_array_tot = f_base_len - 3;
+ BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot);
+ BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot);
+ const int quad_method = 0, ngon_method = 0; /* beauty */
+
+ bool has_cut = false;
+
+ const int f_index = BM_elem_index_get(f_base);
+
+ BM_face_triangulate(
+ bm, f_base,
+ faces_array, &faces_array_tot,
+ edges_array, &edges_array_tot,
+ r_faces_double,
+ quad_method, ngon_method, false,
+ pf_arena,
+ pf_heap, pf_ehash);
+
+ for (int i = 0; i < edges_array_tot; i++) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = edges_array[i]->l;
+ do {
+ BM_elem_index_set(l_iter, f_index); /* set_dirty */
+ has_cut = true;
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+
+ for (int i = 0; i < faces_array_tot; i++) {
+ BM_face_normal_update(faces_array[i]);
+ }
+
+ *r_edges_tri_tot += edges_array_tot;
+
+ return has_cut;
+}
+
+
+static bool bm_decim_triangulate_begin(BMesh *bm, int *r_edges_tri_tot)
{
BMIter iter;
BMFace *f;
- // bool has_quad; // could optimize this a little
+ bool has_quad;
+ bool has_ngon;
bool has_cut = false;
BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
@@ -492,98 +544,103 @@ static bool bm_decim_triangulate_begin(BMesh *bm)
BM_elem_index_set(l_iter, -1); /* set_dirty */
} while ((l_iter = l_iter->next) != l_first);
- // has_quad |= (f->len == 4)
+ has_quad |= (f->len > 3);
+ has_ngon |= (f->len > 4);
}
bm->elem_index_dirty |= BM_LOOP;
- /* adding new faces as we loop over faces
- * is normally best avoided, however in this case its not so bad because any face touched twice
- * will already be triangulated*/
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (f->len == 4) {
- BMLoop *f_l[4];
- BMLoop *l_a, *l_b;
+ {
+ MemArena *pf_arena;
+ Heap *pf_heap;
+ EdgeHash *pf_ehash;
- {
- BMLoop *l_iter = BM_FACE_FIRST_LOOP(f);
+ LinkNode *faces_double = NULL;
- f_l[0] = l_iter; l_iter = l_iter->next;
- f_l[1] = l_iter; l_iter = l_iter->next;
- f_l[2] = l_iter; l_iter = l_iter->next;
- f_l[3] = l_iter;
- }
+ if (has_ngon) {
+ pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ }
+ else {
+ pf_arena = NULL;
+ pf_heap = NULL;
+ pf_ehash = NULL;
+ }
- if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) <
- len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co))
- {
- l_a = f_l[0];
- l_b = f_l[2];
+ /* adding new faces as we loop over faces
+ * is normally best avoided, however in this case its not so bad because any face touched twice
+ * will already be triangulated*/
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (f->len > 3) {
+ has_cut |= bm_face_triangulate(
+ bm, f, &faces_double,
+ r_edges_tri_tot,
+
+ pf_arena,
+ pf_heap, pf_ehash);
}
- else {
- l_a = f_l[1];
- l_b = f_l[3];
- }
-
-#ifdef USE_SAFETY_CHECKS
- if (BM_edge_exists(l_a->v, l_b->v) == NULL)
-#endif
- {
- BMFace *f_new;
- BMLoop *l_new;
-
- /* warning, NO_DOUBLE option here isn't handled as nice as it could be
- * - if there is a quad that has a free standing edge joining it along
- * where we want to split the face, there isnt a good way we can handle this.
- * currently that edge will get removed when joining the tris back into a quad. */
- f_new = BM_face_split(bm, f, l_a, l_b, &l_new, NULL, false);
-
- if (f_new) {
- /* the value of this doesn't matter, only that the 2 loops match and have unique values */
- const int f_index = BM_elem_index_get(f);
-
- /* since we just split theres only ever 2 loops */
- BLI_assert(BM_edge_is_manifold(l_new->e));
+ }
- BM_elem_index_set(l_new, f_index); /* set_dirty */
- BM_elem_index_set(l_new->radial_next, f_index); /* set_dirty */
+ while (faces_double) {
+ LinkNode *next = faces_double->next;
+ BM_face_kill(bm, faces_double->link);
+ MEM_freeN(faces_double);
+ faces_double = next;
+ }
- BM_face_normal_update(f);
- BM_face_normal_update(f_new);
+ BLI_memarena_free(pf_arena);
- has_cut = true;
- }
- }
+ if (has_ngon) {
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
}
- }
- BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
+ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0);
- if (has_cut) {
- /* now triangulation is done we need to correct index values */
- BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE);
+ if (has_cut) {
+ /* now triangulation is done we need to correct index values */
+ BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE);
+ }
}
return has_cut;
}
-static void bm_decim_triangulate_end(BMesh *bm)
+
+static void bm_decim_triangulate_end(BMesh *bm, const int edges_tri_tot)
{
/* decimation finished, now re-join */
BMIter iter;
- BMEdge *e, *e_next;
+ BMEdge *e;
+
+ /* we need to collect before merging for ngons since the loops indices will be lost */
+ BMEdge **edges_tri = MEM_mallocN(MIN2(edges_tri_tot, bm->totedge) * sizeof(*edges_tri), __func__);
+ STACK_DECLARE(edges_tri);
/* boundary edges */
- BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
BMLoop *l_a, *l_b;
if (BM_edge_loop_pair(e, &l_a, &l_b)) {
const int l_a_index = BM_elem_index_get(l_a);
if (l_a_index != -1) {
const int l_b_index = BM_elem_index_get(l_b);
if (l_a_index == l_b_index) {
- if (LIKELY(l_a->f->len == 3 && l_b->f->len == 3)) {
- if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */
- /* check we are not making a degenerate quad */
+ if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */
+ /* check we are not making a degenerate quad */
+
+#define CAN_LOOP_MERGE(l) \
+ (BM_loop_is_manifold(l) && \
+ ((l)->v != (l)->radial_next->v) && \
+ (l_a_index == BM_elem_index_get(l)) && \
+ (l_a_index == BM_elem_index_get((l)->radial_next)))
+
+ if ((l_a->f->len == 3 && l_b->f->len == 3) &&
+ (!CAN_LOOP_MERGE(l_a->next)) &&
+ (!CAN_LOOP_MERGE(l_a->prev)) &&
+ (!CAN_LOOP_MERGE(l_b->next)) &&
+ (!CAN_LOOP_MERGE(l_b->prev)))
+ {
BMVert *vquad[4] = {
e->v1,
BM_vert_in_edge(e, l_a->next->v) ? l_a->prev->v : l_a->next->v,
@@ -596,17 +653,32 @@ static void bm_decim_triangulate_end(BMesh *bm)
BLI_assert(ELEM(vquad[2], vquad[1], vquad[0], vquad[3]) == false);
BLI_assert(ELEM(vquad[3], vquad[1], vquad[2], vquad[0]) == false);
- if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
- /* highly unlikely to fail, but prevents possible double-ups */
- BMFace *f[2] = {l_a->f, l_b->f};
- BM_faces_join(bm, f, 2, true);
+ if (!is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) {
+ continue;
}
}
+#undef CAN_LOOP_MERGE
+
+ /* highly unlikely to fail, but prevents possible double-ups */
+ STACK_PUSH(edges_tri, e);
}
}
}
}
}
+
+ for (int i = 0; i < STACK_SIZE(edges_tri); i++) {
+ BMLoop *l_a, *l_b;
+ e = edges_tri[i];
+ if (BM_edge_loop_pair(e, &l_a, &l_b)) {
+ BMFace *f_array[2] = {l_a->f, l_b->f};
+ BM_faces_join(bm, f_array, 2, false);
+ if (e->l == NULL) {
+ BM_edge_kill(bm, e);
+ }
+ }
+ }
+ MEM_freeN(edges_tri);
}
#endif /* USE_TRIANGULATE */
@@ -1219,7 +1291,6 @@ void BM_mesh_decimate_collapse(
Quadric *vquadrics; /* vert index aligned quadrics */
int tot_edge_orig;
int face_tot_target;
- bool use_triangulate;
CD_UseFlag customdata_flag = 0;
@@ -1229,8 +1300,11 @@ void BM_mesh_decimate_collapse(
#endif
#ifdef USE_TRIANGULATE
+ int edges_tri_tot = 0;
/* temp convert quads to triangles */
- use_triangulate = bm_decim_triangulate_begin(bm);
+ bool use_triangulate = bm_decim_triangulate_begin(bm, &edges_tri_tot);
+#else
+ UNUSED_VARS(do_triangulate);
#endif
@@ -1415,7 +1489,7 @@ invalidate:
/* its possible we only had triangles, skip this step in that case */
if (LIKELY(use_triangulate)) {
/* temp convert quads to triangles */
- bm_decim_triangulate_end(bm);
+ bm_decim_triangulate_end(bm, edges_tri_tot);
}
}
#endif
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 3adddddb8e7..6085b66a8b8 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -271,38 +271,41 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
const std::string &name = bc_get_dae_name(mesh);
- int hole_count = 0;
for (unsigned i = 0; i < prim_arr.getCount(); i++) {
-
+
COLLADAFW::MeshPrimitive *mp = prim_arr[i];
COLLADAFW::MeshPrimitive::PrimitiveType type = mp->getPrimitiveType();
const char *type_str = bc_primTypeToStr(type);
-
+
// OpenCollada passes POLYGONS type for <polylist>
if (type == COLLADAFW::MeshPrimitive::POLYLIST || type == COLLADAFW::MeshPrimitive::POLYGONS) {
COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
COLLADAFW::Polygons::VertexCountArray& vca = mpvc->getGroupedVerticesVertexCountArray();
-
+
+ int hole_count = 0;
+ int nonface_count = 0;
+
for (unsigned int j = 0; j < vca.getCount(); j++) {
int count = vca[j];
if (abs(count) < 3) {
- fprintf(stderr, "ERROR: Primitive %s in %s has at least one face with vertex count < 3\n",
- type_str, name.c_str());
- return false;
+ nonface_count++;
}
- if (count < 0)
- {
+
+ if (count < 0) {
hole_count ++;
}
}
- if (hole_count > 0)
- {
+ if (hole_count > 0) {
fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
}
+
+ if (nonface_count > 0) {
+ fprintf(stderr, "WARNING: Primitive %s in %s: %d faces with vertex count < 3 (rejected)\n", type_str, name.c_str(), nonface_count);
+ }
}
else if (type == COLLADAFW::MeshPrimitive::LINES) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 0e52c3b44b2..16a708f31d5 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1398,11 +1398,12 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
+ } else {
+ OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
+ add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
}
parchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
- add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
root_map->add_bone(parchan->name, rootchan->name);
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 30d243867b0..fda665b0db4 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -80,11 +80,12 @@ static void flush_init_func(void *data_v, int i)
*/
Depsgraph *graph = (Depsgraph *)data_v;
OperationDepsNode *node = graph->operations[i];
- IDDepsNode *id_node = node->owner->owner;
+ ComponentDepsNode *comp_node = node->owner;
+ IDDepsNode *id_node = comp_node->owner;
id_node->done = 0;
+ comp_node->done = 0;
node->scheduled = false;
- node->owner->flags &= ~DEPSCOMP_FULLY_SCHEDULED;
- if (node->owner->type == DEPSNODE_TYPE_PROXY) {
+ if (comp_node->type == DEPSNODE_TYPE_PROXY) {
node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
}
}
@@ -136,49 +137,10 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
for (;;) {
node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- IDDepsNode *id_node = node->owner->owner;
-
- if (id_node->done == 0) {
- deg_editors_id_update(bmain, id_node->id);
- id_node->done = 1;
- }
-
- lib_id_recalc_tag(bmain, id_node->id);
- /* TODO(sergey): For until we've got proper data nodes in the graph. */
- lib_id_recalc_data_tag(bmain, id_node->id);
-
- ID *id = id_node->id;
- /* This code is used to preserve those areas which does direct
- * object update,
- *
- * Plus it ensures visibility changes and relations and layers
- * visibility update has proper flags to work with.
- */
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- ComponentDepsNode *comp_node = node->owner;
- if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
- object->recalc |= OB_RECALC_TIME;
- }
- else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
- object->recalc |= OB_RECALC_OB;
- }
- else {
- object->recalc |= OB_RECALC_DATA;
- }
- }
-
- /* TODO(sergey): For until incremental updates are possible
- * witin a component at least we tag the whole component
- * for update.
- */
- ComponentDepsNode *component = node->owner;
- if ((component->flags & DEPSCOMP_FULLY_SCHEDULED) == 0) {
- foreach (OperationDepsNode *op, component->operations) {
- op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- }
- component->flags |= DEPSCOMP_FULLY_SCHEDULED;
- }
+ ComponentDepsNode *comp_node = node->owner;
+ IDDepsNode *id_node = comp_node->owner;
+ id_node->done = 1;
+ comp_node->done = 1;
/* Flush to nodes along links... */
if (node->outlinks.size() == 1) {
@@ -203,6 +165,52 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
}
}
}
+
+ GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, graph->id_hash)
+ {
+ if (id_node->done == 1) {
+ ID *id = id_node->id;
+ Object *object = NULL;
+
+ if (GS(id->name) == ID_OB) {
+ object = (Object *)id;
+ }
+
+ deg_editors_id_update(bmain, id_node->id);
+
+ lib_id_recalc_tag(bmain, id_node->id);
+ /* TODO(sergey): For until we've got proper data nodes in the graph. */
+ lib_id_recalc_data_tag(bmain, id_node->id);
+
+ GHASH_FOREACH_BEGIN(const ComponentDepsNode *, comp_node, id_node->components)
+ {
+ if (comp_node->done) {
+ foreach (OperationDepsNode *op, comp_node->operations) {
+ op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ }
+ if (object != NULL) {
+ /* This code is used to preserve those areas which does
+ * direct object update,
+ *
+ * Plus it ensures visibility changes and relations and
+ * layers visibility update has proper flags to work with.
+ */
+ if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+ object->recalc |= OB_RECALC_TIME;
+ }
+ else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
+ object->recalc |= OB_RECALC_OB;
+ }
+ else {
+ object->recalc |= OB_RECALC_DATA;
+ }
+ }
+ }
+ }
+ GHASH_FOREACH_END();
+ }
+ }
+ GHASH_FOREACH_END();
}
static void graph_clear_func(void *data_v, int i)
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index 7e49fec051f..8e74317cfa2 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -86,7 +86,6 @@ static void comp_node_hash_value_free(void *value_v)
ComponentDepsNode::ComponentDepsNode() :
entry_operation(NULL),
exit_operation(NULL),
- flags(0),
layers(0)
{
operations_map = BLI_ghash_new(comp_node_hash_key,
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index df321ea9299..6ff4345d28b 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -47,13 +47,6 @@ struct Depsgraph;
struct OperationDepsNode;
struct BoneComponentDepsNode;
-typedef enum eDepsComponent_Flag {
- /* Temporary flags, meaning all the component's operations has been
- * scheduled for update.
- */
- DEPSCOMP_FULLY_SCHEDULED = 1,
-} eDepsComponent_Flag;
-
/* ID Component - Base type for all components */
struct ComponentDepsNode : public DepsNode {
/* Key used to look up operations within a component */
@@ -165,8 +158,6 @@ struct ComponentDepsNode : public DepsNode {
// XXX: a poll() callback to check if component's first node can be started?
- int flags;
-
/* Temporary bitmask, used during graph construction. */
int layers;
};
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 172f2b9069e..66b3a63c669 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -2035,7 +2035,7 @@ bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
else {
/* Normal Mode (or treat as being normal mode):
*
- * Just in case the flags are't set properly (i.e. only on/off is set, without a mode)
+ * Just in case the flags aren't set properly (i.e. only on/off is set, without a mode)
* let's set the "normal" flag too, so that it will all be sane everywhere...
*/
scene->toolsettings->autokey_mode = AUTOKEY_MODE_NORMAL;
diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt
index ebdf6bb43ff..2f5b2ab6e87 100644
--- a/source/blender/editors/curve/CMakeLists.txt
+++ b/source/blender/editors/curve/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
editcurve_paint.c
editcurve_select.c
editfont.c
+ editfont_undo.c
curve_intern.h
)
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index bb7cc61f580..38018541929 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -911,7 +911,7 @@ static int curve_draw_exec(bContext *C, wmOperator *op)
unsigned int corners_index_len = 0;
const int result = curve_fit_cubic_to_points_fl(
- coords, stroke_len, dims, error_threshold,
+ coords, stroke_len, dims, error_threshold, CURVE_FIT_CALC_HIGH_QUALIY,
corners, corners_len,
&cubic_spline, &cubic_spline_len,
NULL,
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 7c1fe0cadf0..053a7ee5023 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -1794,64 +1794,6 @@ void FONT_OT_unlink(wmOperatorType *ot)
ot->exec = font_unlink_exec;
}
-
-/* **************** undo for font object ************** */
-
-static void undoFont_to_editFont(void *strv, void *ecu, void *UNUSED(obdata))
-{
- Curve *cu = (Curve *)ecu;
- EditFont *ef = cu->editfont;
- const char *str = strv;
-
- ef->pos = *((const short *)str);
- ef->len = *((const short *)(str + 2));
-
- memcpy(ef->textbuf, str + 4, (ef->len + 1) * sizeof(wchar_t));
- memcpy(ef->textbufinfo, str + 4 + (ef->len + 1) * sizeof(wchar_t), ef->len * sizeof(CharInfo));
-
- ef->selstart = ef->selend = 0;
-
-}
-
-static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
-{
- Curve *cu = (Curve *)ecu;
- EditFont *ef = cu->editfont;
- char *str;
-
- /* The undo buffer includes [MAXTEXT+6]=actual string and [MAXTEXT+4]*sizeof(CharInfo)=charinfo */
- str = MEM_callocN((MAXTEXT + 6) * sizeof(wchar_t) + (MAXTEXT + 4) * sizeof(CharInfo), "string undo");
-
- /* Copy the string and string information */
- memcpy(str + 4, ef->textbuf, (ef->len + 1) * sizeof(wchar_t));
- memcpy(str + 4 + (ef->len + 1) * sizeof(wchar_t), ef->textbufinfo, ef->len * sizeof(CharInfo));
-
- *((short *)(str + 0)) = ef->pos;
- *((short *)(str + 2)) = ef->len;
-
- return str;
-}
-
-static void free_undoFont(void *strv)
-{
- MEM_freeN(strv);
-}
-
-static void *get_undoFont(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_FONT) {
- return obedit->data;
- }
- return NULL;
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_font(bContext *C, const char *name)
-{
- undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);
-}
-
/**
* TextBox selection
*/
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
new file mode 100644
index 00000000000..a0453f9694d
--- /dev/null
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -0,0 +1,311 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/curve/editfont_undo.c
+ * \ingroup edcurve
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_font.h"
+
+#include "ED_curve.h"
+#include "ED_util.h"
+
+#define USE_ARRAY_STORE
+
+#ifdef USE_ARRAY_STORE
+// # define DEBUG_PRINT
+# include "BLI_array_store.h"
+# include "BLI_array_store_utils.h"
+# include "BLI_listbase.h"
+# define ARRAY_CHUNK_SIZE 32
+#endif
+
+typedef struct UndoFont {
+ wchar_t *textbuf;
+ struct CharInfo *textbufinfo;
+
+ int len, pos;
+
+#ifdef USE_ARRAY_STORE
+ struct {
+ BArrayState *textbuf;
+ BArrayState *textbufinfo;
+ } store;
+#endif
+} UndoFont;
+
+
+#ifdef USE_ARRAY_STORE
+
+/** \name Array Store
+ * \{ */
+
+static struct {
+ struct BArrayStore_AtSize bs_stride;
+ int users;
+
+ /* We could have the undo API pass in the previous state, for now store a local list */
+ ListBase local_links;
+
+} uf_arraystore = {NULL};
+
+/**
+ * \param create: When false, only free the arrays.
+ * This is done since when reading from an undo state, they must be temporarily expanded.
+ * then discarded afterwards, having this argument avoids having 2x code paths.
+ */
+static void uf_arraystore_compact_ex(
+ UndoFont *uf, const UndoFont *uf_ref,
+ bool create)
+{
+#define STATE_COMPACT(uf, id, len) \
+ if ((uf)->id) { \
+ BLI_assert(create == ((uf)->store.id == NULL)); \
+ if (create) { \
+ BArrayState *state_reference = uf_ref ? uf_ref->store.id : NULL; \
+ const size_t stride = sizeof(*(uf)->id); \
+ BArrayStore *bs = BLI_array_store_at_size_ensure(&uf_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); \
+ (uf)->store.id = BLI_array_store_state_add( \
+ bs, (uf)->id, (size_t)(len) * stride, state_reference); \
+ } \
+ /* keep uf->len for validation */ \
+ MEM_freeN((uf)->id); \
+ (uf)->id = NULL; \
+ } ((void)0)
+
+ STATE_COMPACT(uf, textbuf, uf->len + 1);
+ STATE_COMPACT(uf, textbufinfo, uf->len + 1);
+
+#undef STATE_COMPACT
+
+ if (create) {
+ uf_arraystore.users += 1;
+ }
+}
+
+/**
+ * Move data from allocated arrays to de-duplicated states and clear arrays.
+ */
+static void uf_arraystore_compact(UndoFont *um, const UndoFont *uf_ref)
+{
+ uf_arraystore_compact_ex(um, uf_ref, true);
+}
+
+static void uf_arraystore_compact_with_info(UndoFont *um, const UndoFont *uf_ref)
+{
+#ifdef DEBUG_PRINT
+ size_t size_expanded_prev, size_compacted_prev;
+ BLI_array_store_at_size_calc_memory_usage(&uf_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
+#endif
+
+ uf_arraystore_compact(um, uf_ref);
+
+#ifdef DEBUG_PRINT
+ {
+ size_t size_expanded, size_compacted;
+ BLI_array_store_at_size_calc_memory_usage(&uf_arraystore.bs_stride, &size_expanded, &size_compacted);
+
+ const double percent_total = size_expanded ?
+ (((double)size_compacted / (double)size_expanded) * 100.0) : -1.0;
+
+ size_t size_expanded_step = size_expanded - size_expanded_prev;
+ size_t size_compacted_step = size_compacted - size_compacted_prev;
+ const double percent_step = size_expanded_step ?
+ (((double)size_compacted_step / (double)size_expanded_step) * 100.0) : -1.0;
+
+ printf("overall memory use: %.8f%% of expanded size\n", percent_total);
+ printf("step memory use: %.8f%% of expanded size\n", percent_step);
+ }
+#endif
+}
+
+/**
+ * Remove data we only expanded for temporary use.
+ */
+static void uf_arraystore_expand_clear(UndoFont *um)
+{
+ uf_arraystore_compact_ex(um, NULL, false);
+}
+
+static void uf_arraystore_expand(UndoFont *uf)
+{
+#define STATE_EXPAND(uf, id, len) \
+ if ((uf)->store.id) { \
+ const size_t stride = sizeof(*(uf)->id); \
+ BArrayState *state = (uf)->store.id; \
+ size_t state_len; \
+ (uf)->id = BLI_array_store_state_data_get_alloc(state, &state_len); \
+ BLI_assert((len) == (state_len / stride)); \
+ UNUSED_VARS_NDEBUG(stride); \
+ } ((void)0)
+
+ STATE_EXPAND(uf, textbuf, uf->len + 1);
+ STATE_EXPAND(uf, textbufinfo, uf->len + 1);
+
+#undef STATE_EXPAND
+}
+
+static void uf_arraystore_free(UndoFont *uf)
+{
+#define STATE_FREE(uf, id) \
+ if ((uf)->store.id) { \
+ const size_t stride = sizeof(*(uf)->id); \
+ BArrayStore *bs = BLI_array_store_at_size_get(&uf_arraystore.bs_stride, stride); \
+ BArrayState *state = (uf)->store.id; \
+ BLI_array_store_state_remove(bs, state); \
+ (uf)->store.id = NULL; \
+ } ((void)0)
+
+ STATE_FREE(uf, textbuf);
+ STATE_FREE(uf, textbufinfo);
+
+#undef STATE_FREE
+
+ uf_arraystore.users -= 1;
+
+ BLI_assert(uf_arraystore.users >= 0);
+
+ if (uf_arraystore.users == 0) {
+#ifdef DEBUG_PRINT
+ printf("editfont undo store: freeing all data!\n");
+#endif
+
+ BLI_array_store_at_size_clear(&uf_arraystore.bs_stride);
+ }
+
+}
+
+/** \} */
+
+#endif /* USE_ARRAY_STORE */
+
+static void undoFont_to_editFont(void *uf_v, void *ecu, void *UNUSED(obdata))
+{
+ Curve *cu = (Curve *)ecu;
+ EditFont *ef = cu->editfont;
+ const UndoFont *uf = uf_v;
+
+ size_t final_size;
+
+#ifdef USE_ARRAY_STORE
+ uf_arraystore_expand(uf_v);
+#endif
+
+ final_size = sizeof(wchar_t) * (uf->len + 1);
+ memcpy(ef->textbuf, uf->textbuf, final_size);
+
+ final_size = sizeof(CharInfo) * (uf->len + 1);
+ memcpy(ef->textbufinfo, uf->textbufinfo, final_size);
+
+ ef->pos = uf->pos;
+ ef->len = uf->len;
+
+ ef->selstart = ef->selend = 0;
+
+#ifdef USE_ARRAY_STORE
+ uf_arraystore_expand_clear(uf_v);
+#endif
+}
+
+static void *editFont_to_undoFont(void *ecu, void *UNUSED(obdata))
+{
+ Curve *cu = (Curve *)ecu;
+ EditFont *ef = cu->editfont;
+
+ UndoFont *uf = MEM_callocN(sizeof(*uf), __func__);
+
+ size_t final_size;
+
+ final_size = sizeof(wchar_t) * (ef->len + 1);
+ uf->textbuf = MEM_mallocN(final_size, __func__);
+ memcpy(uf->textbuf, ef->textbuf, final_size);
+
+ final_size = sizeof(CharInfo) * (ef->len + 1);
+ uf->textbufinfo = MEM_mallocN(final_size, __func__);
+ memcpy(uf->textbufinfo, ef->textbufinfo, final_size);
+
+ uf->pos = ef->pos;
+ uf->len = ef->len;
+
+#ifdef USE_ARRAY_STORE
+ {
+ const UndoFont *uf_ref = uf_arraystore.local_links.last ?
+ ((LinkData *)uf_arraystore.local_links.last)->data : NULL;
+
+ /* add oursrlves */
+ BLI_addtail(&uf_arraystore.local_links, BLI_genericNodeN(uf));
+
+ uf_arraystore_compact_with_info(uf, uf_ref);
+ }
+#endif
+
+ return uf;
+}
+
+static void free_undoFont(void *uf_v)
+{
+ UndoFont *uf = uf_v;
+
+#ifdef USE_ARRAY_STORE
+ {
+ LinkData *link = BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data));
+ BLI_remlink(&uf_arraystore.local_links, link);
+ MEM_freeN(link);
+ }
+ uf_arraystore_free(uf);
+#endif
+
+ if (uf->textbuf) {
+ MEM_freeN(uf->textbuf);
+ }
+ if (uf->textbufinfo) {
+ MEM_freeN(uf->textbufinfo);
+ }
+
+ MEM_freeN(uf);
+}
+
+static void *get_undoFont(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_FONT) {
+ return obedit->data;
+ }
+ return NULL;
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_font(bContext *C, const char *name)
+{
+ undo_editmode_push(C, name, get_undoFont, free_undoFont, undoFont_to_editFont, editFont_to_undoFont, NULL);
+}
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 0329598d711..79a2c494239 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -763,6 +763,7 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness
}
glEnd();
+ glShadeModel(GL_SMOOTH);
}
/* draw debug points of curve on top? (original stroke points) */
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 0ac5c17a552..d3d2c465d46 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -94,6 +94,7 @@ void glutil_draw_filled_arc(float start, float angle, float radius, int nsegment
* The param must cause only one value to be gotten from GL.
*/
float glaGetOneFloat(int param);
+int glaGetOneInt(int param);
/**
* Functions like glRasterPos2i, except ensures that the resulting
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index fb4897c6532..27e1051a336 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -608,7 +608,7 @@ typedef enum eAnimUnitConv_Flags {
ANIM_UNITCONV_SKIPKNOTS = (1 << 4),
/* Scale FCurve i a way it fits to -1..1 space */
ANIM_UNITCONV_NORMALIZE = (1 << 5),
- /* Only whennormalization is used: use scale factor from previous run,
+ /* Only when normalization is used: use scale factor from previous run,
* prevents curves from jumping all over the place when tweaking them.
*/
ANIM_UNITCONV_NORMALIZE_FREEZE = (1 << 6),
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index 278e3f97ba7..859d45e9c86 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -72,8 +72,7 @@ void ED_curve_deselect_all(struct EditNurb *editnurb);
void ED_curve_select_all(struct EditNurb *editnurb);
void ED_curve_select_swap(struct EditNurb *editnurb, bool hide_handles);
-/* editfont.h */
-void undo_push_font(struct bContext *C, const char *name);
+/* editfont.c */
void ED_curve_editfont_load(struct Object *obedit);
void ED_curve_editfont_make(struct Object *obedit);
void ED_curve_editfont_free(struct Object *obedit);
@@ -89,6 +88,9 @@ bool ED_curve_active_center(struct Curve *cu, float center[3]);
bool ED_curve_editfont_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
+/* editfont_undo.c */
+void undo_push_font(struct bContext *C, const char *name);
+
#if 0
/* debug only */
void printknots(struct Object *obedit);
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 186a2a26825..80f930a0c30 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -104,7 +104,8 @@ void ED_fileselect_clear(struct wmWindowManager *wm, struct ScrArea *sa, struct
void ED_fileselect_exit(struct wmWindowManager *wm, struct ScrArea *sa, struct SpaceFile *sfile);
-int ED_file_extension_icon(const char *relname);
+int ED_path_extension_type(const char *path);
+int ED_file_extension_icon(const char *path);
void ED_file_read_bookmarks(void);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 8fbc545cb77..72a6a04feec 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -181,7 +181,6 @@ void UI_draw_roundbox_shade_x(
coldown[1] = max_ff(0.0f, color[1] + shadedown);
coldown[2] = max_ff(0.0f, color[2] + shadedown);
- glShadeModel(GL_SMOOTH);
glBegin(mode);
/* start with corner right-bottom */
@@ -260,7 +259,6 @@ void UI_draw_roundbox_shade_x(
}
glEnd();
- glShadeModel(GL_FLAT);
}
/* linear vertical shade within button or in outline */
@@ -291,7 +289,6 @@ void UI_draw_roundbox_shade_y(
colRight[1] = max_ff(0.0f, color[1] + shadeRight);
colRight[2] = max_ff(0.0f, color[2] + shadeRight);
- glShadeModel(GL_SMOOTH);
glBegin(mode);
/* start with corner right-bottom */
@@ -367,7 +364,6 @@ void UI_draw_roundbox_shade_y(
}
glEnd();
- glShadeModel(GL_FLAT);
}
/* plain antialiased unfilled rectangle */
@@ -531,7 +527,6 @@ static void histogram_draw_one(
}
else {
/* under the curve */
- glShadeModel(GL_FLAT);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(x, y);
glVertex2f(x, y + (data[0] * h));
@@ -1087,7 +1082,6 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
/* layer: color ramp */
- glShadeModel(GL_FLAT);
glEnable(GL_BLEND);
CBData *cbd = coba->data;
@@ -1133,7 +1127,6 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
glEnd();
glDisable(GL_BLEND);
- glShadeModel(GL_SMOOTH);
/* layer: box outline */
glColor4f(0.0, 0.0, 0.0, 1.0);
@@ -1212,9 +1205,8 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
- glShadeModel(GL_SMOOTH);
+ GPU_basic_shader_bind(GPU_basic_shader_bound_options());
gluSphere(qobj, 100.0, 32, 24);
- glShadeModel(GL_FLAT);
gluDeleteQuadric(qobj);
glEndList();
@@ -1545,10 +1537,12 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
BLI_rctf_size_x(&rect),
BLI_rctf_size_y(&rect));
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
+
for (int a = 0; a < 2; a++) {
if (a == 1) {
- glLineStipple(3, 0xaaaa);
- glEnable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_enable(GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
UI_ThemeColor(TH_SEL_MARKER);
}
else {
@@ -1562,9 +1556,10 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glVertex2f(0.0f, 10.0f);
glEnd();
}
+
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
- glDisable(GL_LINE_STIPPLE);
glPopMatrix();
ok = true;
@@ -1677,7 +1672,6 @@ static void ui_shadowbox(float minx, float miny, float maxx, float maxy, float s
void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy)
{
glEnable(GL_BLEND);
- glShadeModel(GL_SMOOTH);
glBegin(GL_QUADS);
@@ -1689,7 +1683,6 @@ void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx,
glEnd();
glDisable(GL_BLEND);
- glShadeModel(GL_FLAT);
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 5b8b8ae5bdb..133487e1846 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6981,13 +6981,15 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
!IS_EVENT_MOD(event, shift, oskey) &&
(event->val == KM_PRESS))
{
- if (event->alt)
- ui_but_anim_remove_driver(C);
- else if (event->ctrl)
- ui_but_anim_add_driver(C);
-
- ED_region_tag_redraw(data->region);
-
+ /* quick check to prevent this opening within the popup menu its self */
+ if (!ELEM(NULL, but->rnapoin.data, but->rnaprop)) {
+ if (event->alt)
+ ui_but_anim_remove_driver(C);
+ else if (event->ctrl)
+ ui_but_anim_add_driver(C);
+
+ ED_region_tag_redraw(data->region);
+ }
return WM_UI_HANDLER_BREAK;
}
/* handle keyingsets */
@@ -8436,6 +8438,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
uiListDyn *dyn_data;
int retval = WM_UI_HANDLER_CONTINUE;
int type = event->type, val = event->val;
+ bool redraw = false;
int mx, my;
ui_list = listbox->custom_data;
@@ -8525,7 +8528,7 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
ui_apply_but_undo(listbox);
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ED_region_tag_redraw(ar);
+ redraw = true;
}
retval = WM_UI_HANDLER_BREAK;
}
@@ -8537,8 +8540,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
ui_list->list_grip += (type == WHEELUPMOUSE) ? -1 : 1;
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
- ED_region_tag_redraw(ar);
+ redraw = true;
retval = WM_UI_HANDLER_BREAK;
}
else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
@@ -8546,13 +8549,22 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
/* list template will clamp */
ui_list->list_scroll += (type == WHEELUPMOUSE) ? -1 : 1;
- ED_region_tag_redraw(ar);
-
+ redraw = true;
retval = WM_UI_HANDLER_BREAK;
}
}
}
+ if (redraw) {
+ if (listbox->block->flag & UI_BLOCK_POPUP) {
+ /* popups need special refreshing */
+ ED_region_tag_refresh_ui(ar);
+ }
+ else {
+ ED_region_tag_redraw(ar);
+ }
+ }
+
return retval;
}
@@ -9794,11 +9806,21 @@ static int ui_handle_menus_recursive(
}
else {
uiBlock *block = menu->region->uiblocks.first;
+ uiBut *listbox = ui_list_find_mouse_over(menu->region, event);
- if (block->flag & UI_BLOCK_RADIAL)
+ if (block->flag & UI_BLOCK_RADIAL) {
retval = ui_pie_handler(C, event, menu);
- else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK)
- retval = ui_handle_menu_event(C, event, menu, level, is_parent_inside, is_parent_menu, is_floating);
+ }
+ else if (event->type == LEFTMOUSE || event->val != KM_DBL_CLICK) {
+ if (listbox) {
+ retval = ui_handle_list_event(C, event, menu->region, listbox);
+ }
+ if (retval == WM_UI_HANDLER_CONTINUE) {
+ retval = ui_handle_menu_event(
+ C, event, menu, level,
+ is_parent_inside, is_parent_menu, is_floating);
+ }
+ }
}
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 222b0366791..6dc60f1d70b 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -368,7 +368,6 @@ static void vicon_disclosure_tri_right_draw(int x, int y, int w, int UNUSED(h),
viconutil_set_point(pts[1], cx - d2, cy - d);
viconutil_set_point(pts[2], cx + d2, cy);
- glShadeModel(GL_SMOOTH);
glBegin(GL_TRIANGLES);
glColor4f(0.8f, 0.8f, 0.8f, alpha);
glVertex2iv(pts[0]);
@@ -376,7 +375,6 @@ static void vicon_disclosure_tri_right_draw(int x, int y, int w, int UNUSED(h),
glColor4f(0.3f, 0.3f, 0.3f, alpha);
glVertex2iv(pts[2]);
glEnd();
- glShadeModel(GL_FLAT);
glColor4f(0.0f, 0.0f, 0.0f, 1);
viconutil_draw_lineloop_smooth(pts, 3);
@@ -395,13 +393,11 @@ static void vicon_small_tri_right_draw(int x, int y, int w, int UNUSED(h), float
glColor4f(0.2f, 0.2f, 0.2f, alpha);
- glShadeModel(GL_SMOOTH);
glBegin(GL_TRIANGLES);
glVertex2iv(pts[0]);
glVertex2iv(pts[1]);
glVertex2iv(pts[2]);
glEnd();
- glShadeModel(GL_FLAT);
}
static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), float alpha)
@@ -415,7 +411,6 @@ static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), f
viconutil_set_point(pts[1], cx - d, cy + d2);
viconutil_set_point(pts[2], cx, cy - d2);
- glShadeModel(GL_SMOOTH);
glBegin(GL_TRIANGLES);
glColor4f(0.8f, 0.8f, 0.8f, alpha);
glVertex2iv(pts[0]);
@@ -423,7 +418,6 @@ static void vicon_disclosure_tri_down_draw(int x, int y, int w, int UNUSED(h), f
glColor4f(0.3f, 0.3f, 0.3f, alpha);
glVertex2iv(pts[2]);
glEnd();
- glShadeModel(GL_FLAT);
glColor4f(0.0f, 0.0f, 0.0f, 1);
viconutil_draw_lineloop_smooth(pts, 3);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 62b373c58c8..85e32144bcd 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -1763,12 +1763,10 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
tab_curve_radius, roundboxtype, true, true, NULL);
/* tab highlight (3d look) */
- glShadeModel(GL_SMOOTH);
glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
- tab_curve_radius, roundboxtype, true, false,
- is_active ? theme_col_back : theme_col_tab_inactive);
- glShadeModel(GL_FLAT);
+ tab_curve_radius, roundboxtype, true, false,
+ is_active ? theme_col_back : theme_col_tab_inactive);
}
/* tab blackline */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index a3b04e1c9bc..9f0c4b16523 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2818,7 +2818,7 @@ static void uilist_prepare(
layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len);
}
-static void uilist_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSED(arg2))
+static void uilist_resize_update_cb(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiList *ui_list = arg1;
uiListDyn *dyn_data = ui_list->dyn_data;
@@ -2831,6 +2831,9 @@ static void uilist_resize_update_cb(bContext *UNUSED(C), void *arg1, void *UNUSE
dyn_data->resize_prev += diff * UI_UNIT_Y;
ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM;
}
+
+ /* In case uilist is in popup, we need special refreshing */
+ ED_region_tag_refresh_ui(CTX_wm_menu(C));
}
static void *uilist_item_use_dynamic_tooltip(PointerRNA *itemptr, const char *propname)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 19e0b55374e..5098e701638 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -712,8 +712,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
unsigned char *col_pt = col_array;
shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
-
- glShadeModel(GL_SMOOTH);
+
for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
}
@@ -725,8 +724,6 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
glDrawArrays(GL_POLYGON, 0, wtb->totvert);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
-
- glShadeModel(GL_FLAT);
}
}
@@ -2311,8 +2308,6 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
- glShadeModel(GL_SMOOTH);
-
glBegin(GL_TRIANGLE_FAN);
glColor3fv(colcent);
glVertex2f(centx, centy);
@@ -2330,8 +2325,6 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
}
glEnd();
- glShadeModel(GL_FLAT);
-
/* fully rounded outline */
glPushMatrix();
glTranslatef(centx, centy, 0.0f);
@@ -2363,7 +2356,6 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
float col1[4][3]; /* right half, rect bottom to top */
/* draw series of gouraud rects */
- glShadeModel(GL_SMOOTH);
switch (type) {
case UI_GRAD_SV:
@@ -2486,8 +2478,6 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
}
glEnd();
}
-
- glShadeModel(GL_FLAT);
}
bool ui_but_is_colorpicker_display_space(uiBut *but)
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index b1ca95efe04..3803221b496 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -482,7 +482,7 @@ void WM_OT_collada_import(wmOperatorType *ot)
RNA_def_boolean(ot->srna,
"auto_connect", 0, "Auto Connect",
- "set use_connect for parent bones which have exactly one child bone");
+ "Set use_connect for parent bones which have exactly one child bone");
RNA_def_int(ot->srna,
"min_chain_length",
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 9a8382b2136..2b4f94a37ef 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -51,6 +51,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_basic_shader.h"
+
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -100,10 +102,10 @@ static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
if (!spline->tot_point)
return;
- glColor3ub(0, 0, 0);
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(1, 0xAAAA);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(1, 0xAAAA);
+ glColor3ub(0, 0, 0);
glBegin(GL_LINES);
for (i = 0; i < spline->tot_point; i++) {
@@ -121,7 +123,7 @@ static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
glEnd();
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
#endif
@@ -455,7 +457,8 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
case MASK_DT_DASH:
default:
- glEnable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
#ifdef USE_XOR
glEnable(GL_COLOR_LOGIC_OP);
@@ -463,7 +466,6 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
#endif
mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
glColor4ubv(rgb_tmp);
- glLineStipple(3, 0xaaaa);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, points);
glDrawArrays(draw_method, 0, tot_point);
@@ -473,10 +475,10 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
#endif
mask_color_active_tint(rgb_tmp, rgb_black, is_active);
glColor4ubv(rgb_tmp);
- glLineStipple(3, 0x5555);
+ GPU_basic_shader_line_stipple(3, 0x5555);
glDrawArrays(draw_method, 0, tot_point);
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
break;
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 0f871cd4127..302ca407add 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -61,27 +61,42 @@
/* until implement profile = 0 case, need to clamp somewhat above zero */
#define PROFILE_HARD_MIN 0.15f
+#define SEGMENTS_HARD_MAX 1000
+
+/* which value is mouse movement and numeric input controlling? */
+#define OFFSET_VALUE 0
+#define OFFSET_VALUE_PERCENT 1
+#define PROFILE_VALUE 2
+#define SEGMENTS_VALUE 3
+#define NUM_VALUE_KINDS 4
+
+static const char *value_rna_name[NUM_VALUE_KINDS] = {"offset", "offset", "profile", "segments"};
+static const float value_clamp_min[NUM_VALUE_KINDS] = {0.0f, 0.0f, PROFILE_HARD_MIN, 1.0f};
+static const float value_clamp_max[NUM_VALUE_KINDS] = {1e6, 100.0f, 1.0f, SEGMENTS_HARD_MAX};
+static const float value_start[NUM_VALUE_KINDS] = {0.0f, 0.0f, 0.5f, 1.0f};
+static const float value_scale_per_inch[NUM_VALUE_KINDS] = { 0.0f, 100.0f, 1.0f, 4.0f};
+
typedef struct {
BMEditMesh *em;
- float initial_length;
- float pixel_size; /* use when mouse input is interpreted as spatial distance */
+ float initial_length[NUM_VALUE_KINDS];
+ float scale[NUM_VALUE_KINDS];
+ NumInput num_input[NUM_VALUE_KINDS];
+ float shift_value[NUM_VALUE_KINDS]; /* The current value when shift is pressed. Negative when shift not active. */
bool is_modal;
- NumInput num_input;
- float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */
/* modal only */
float mcenter[2];
BMBackup mesh_backup;
void *draw_handle_pixel;
short twtype;
- bool mouse_controls_profile;
+ short value_mode; /* Which value does mouse movement and numeric input affect? */
float segments; /* Segments as float so smooth mouse pan works in small increments */
} BevelData;
static void edbm_bevel_update_header(bContext *C, wmOperator *op)
{
const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Clamp Overlap: %s (C), "
- "Vertex Only: %s (V), Profile Control: %s (P), Offset: %s, Segments: %d");
+ "Vertex Only: %s (V), Profile Control: %s (P), Offset: %s, Segments: %d, Profile: %.3f");
char msg[UI_MAX_DRAW_STR];
ScrArea *sa = CTX_wm_area(C);
@@ -93,8 +108,8 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
const char *type_str;
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset_type");
- if (hasNumInput(&opdata->num_input)) {
- outputNumInput(&opdata->num_input, offset_str, &sce->unit);
+ if (hasNumInput(&opdata->num_input[OFFSET_VALUE])) {
+ outputNumInput(&opdata->num_input[OFFSET_VALUE], offset_str, &sce->unit);
}
else {
BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset"));
@@ -105,8 +120,8 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
BLI_snprintf(msg, sizeof(msg), str, type_str,
WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")),
WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")),
- WM_bool_as_string(opdata->mouse_controls_profile),
- offset_str, RNA_int_get(op->ptr, "segments"));
+ WM_bool_as_string(opdata->value_mode == PROFILE_VALUE),
+ offset_str, RNA_int_get(op->ptr, "segments"), RNA_float_get(op->ptr, "profile"));
ED_area_headerprint(sa, msg);
}
@@ -118,6 +133,8 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
Scene *scene = CTX_data_scene(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BevelData *opdata;
+ float pixels_per_inch;
+ int i;
if (em->bm->totvertsel == 0) {
return false;
@@ -127,14 +144,25 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
opdata->em = em;
opdata->is_modal = is_modal;
- opdata->shift_factor = -1.0f;
- opdata->mouse_controls_profile = false;
-
- initNumInput(&opdata->num_input);
- opdata->num_input.idx_max = 0;
- opdata->num_input.val_flag[0] |= NUM_NO_NEGATIVE;
- opdata->num_input.unit_sys = scene->unit.system;
- opdata->num_input.unit_type[0] = B_UNIT_NONE; /* Not sure this is a factor or a unit? */
+ opdata->value_mode = OFFSET_VALUE;
+ pixels_per_inch = U.dpi * U.pixelsize;
+
+ for (i = 0; i < NUM_VALUE_KINDS; i++) {
+ opdata->shift_value[i] = -1.0f;
+ /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */
+ opdata->scale[i] = value_scale_per_inch[i] / pixels_per_inch;
+
+ initNumInput(&opdata->num_input[i]);
+ opdata->num_input[i].idx_max = 0;
+ opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
+ if (i == SEGMENTS_VALUE) {
+ opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO;
+ }
+ if (i == OFFSET_VALUE) {
+ opdata->num_input[i].unit_sys = scene->unit.system;
+ }
+ opdata->num_input[i].unit_type[0] = B_UNIT_NONE; /* Not sure this is a factor or a unit? */
+ }
/* avoid the cost of allocating a bm copy */
if (is_modal) {
@@ -142,7 +170,8 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
ARegion *ar = CTX_wm_region(C);
opdata->mesh_backup = EDBM_redo_state_store(em);
- opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb,
+ opdata->mcenter, REGION_DRAW_POST_PIXEL);
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
@@ -173,13 +202,15 @@ static bool edbm_bevel_calc(wmOperator *op)
EDBM_redo_state_restore(opdata->mesh_backup, em, false);
}
- if (em->ob)
+ if (em->ob) {
material = CLAMPIS(material, -1, em->ob->totcol - 1);
+ }
EDBM_op_init(em, &bmop, op,
"bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
"material=%i loop_slide=%b",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile, clamp_overlap, material, loop_slide);
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
+ clamp_overlap, material, loop_slide);
BMO_op_exec(em->bm, &bmop);
@@ -191,8 +222,9 @@ static bool edbm_bevel_calc(wmOperator *op)
}
/* no need to de-select existing geometry */
- if (!EDBM_op_finish(em, &bmop, op, true))
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
return false;
+ }
EDBM_mesh_normals_update(opdata->em);
@@ -256,12 +288,37 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
+{
+ BevelData *opdata;
+ float mlen[2], len, value, sc, st;
+ int vmode;
+
+ opdata = op->customdata;
+ mlen[0] = opdata->mcenter[0] - event->mval[0];
+ mlen[1] = opdata->mcenter[1] - event->mval[1];
+ len = len_v2(mlen);
+ vmode = opdata->value_mode;
+ if (mode_changed) {
+ /* If current value is not default start value, adjust len so that
+ * the scaling and offset in edbm_bevel_mouse_set_value will
+ * start at current value */
+ value = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
+ sc = opdata->scale[vmode];
+ st = value_start[vmode];
+ if (value != value_start[vmode]) {
+ len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
+ }
+ }
+ opdata->initial_length[opdata->value_mode] = len;
+}
+
static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
/* TODO make modal keymap (see fly mode) */
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BevelData *opdata;
- float mlen[2];
float center_3d[3];
if (!edbm_bevel_init(C, op, true)) {
@@ -276,10 +333,10 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
* ideally this will never happen and should be checked for above */
opdata->mcenter[0] = opdata->mcenter[1] = 0;
}
- mlen[0] = opdata->mcenter[0] - event->mval[0];
- mlen[1] = opdata->mcenter[1] - event->mval[1];
- opdata->initial_length = len_v2(mlen);
- opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
+ edbm_bevel_calc_initial_length(op, event, false);
+
+ /* for OFFSET_VALUE only, the scale is the size of a pixel under the mouse in 3d space */
+ opdata->scale[OFFSET_VALUE] = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f;
edbm_bevel_update_header(C, op);
@@ -293,69 +350,72 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
+static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
- bool use_dist;
- bool is_percent, is_profile;
+ int vmode = opdata->value_mode;
float mdiff[2];
- float factor;
+ float value;
mdiff[0] = opdata->mcenter[0] - event->mval[0];
mdiff[1] = opdata->mcenter[1] - event->mval[1];
- is_percent = (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT);
- use_dist = !is_percent;
- is_profile = opdata->mouse_controls_profile;
- factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size;
+ value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
+
+ /* Scale according to value mode */
+ value = value_start[vmode] + value * opdata->scale[vmode];
/* Fake shift-transform... */
if (event->shift) {
- if (opdata->shift_factor < 0.0f) {
- if (is_profile)
- opdata->shift_factor = RNA_float_get(op->ptr, "profile");
- else {
- opdata->shift_factor = RNA_float_get(op->ptr, "offset");
- if (is_percent) {
- opdata->shift_factor /= 100.0f;
- }
- }
+ if (opdata->shift_value[vmode] < 0.0f) {
+ opdata->shift_value[vmode] = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
}
- factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
+ value = (value - opdata->shift_value[vmode]) * 0.1f + opdata->shift_value[vmode];
}
- else if (opdata->shift_factor >= 0.0f) {
- opdata->shift_factor = -1.0f;
+ else if (opdata->shift_value[vmode] >= 0.0f) {
+ opdata->shift_value[vmode] = -1.0f;
}
- /* clamp differently based on distance/factor/profile */
- if (is_profile) {
- CLAMP(factor, PROFILE_HARD_MIN, 1.0f);
+ /* clamp accordingto value mode, and store value back */
+ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
+ if (vmode == SEGMENTS_VALUE) {
+ opdata->segments = value;
+ RNA_int_set(op->ptr, "segments", (int)(value + 0.5f));
}
else {
- if (use_dist) {
- if (factor < 0.0f) factor = 0.0f;
- }
- else {
- CLAMP(factor, 0.0f, 1.0f);
- if (is_percent) {
- factor *= 100.0f;
- }
- }
+ RNA_float_set(op->ptr, value_rna_name[vmode], value);
}
+}
- return factor;
+static void edbm_bevel_numinput_set_value(wmOperator *op)
+{
+ BevelData *opdata = op->customdata;
+ float value;
+ int vmode;
+
+ vmode = opdata->value_mode;
+ value = (vmode == SEGMENTS_VALUE) ?
+ opdata->segments : RNA_float_get(op->ptr, value_rna_name[vmode]);
+ applyNumInput(&opdata->num_input[vmode], &value);
+ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
+ if (vmode == SEGMENTS_VALUE) {
+ opdata->segments = value;
+ RNA_int_set(op->ptr, "segments", (int)value);
+ }
+ else {
+ RNA_float_set(op->ptr, value_rna_name[vmode], value);
+ }
}
static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
- const bool has_numinput = hasNumInput(&opdata->num_input);
+ const bool has_numinput = hasNumInput(&opdata->num_input[opdata->value_mode]);
/* Modal numinput active, try to handle numeric inputs first... */
- if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input, event)) {
- float value = RNA_float_get(op->ptr, "offset");
- applyNumInput(&opdata->num_input, &value);
- RNA_float_set(op->ptr, "offset", value);
+ if (event->val == KM_PRESS && has_numinput && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
+ edbm_bevel_numinput_set_value(op);
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -370,12 +430,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE:
if (!has_numinput) {
- const float factor = edbm_bevel_mval_factor(op, event);
- if (opdata->mouse_controls_profile)
- RNA_float_set(op->ptr, "profile", factor);
- else
- RNA_float_set(op->ptr, "offset", factor);
-
+ edbm_bevel_mouse_set_value(op, event);
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
handled = true;
@@ -445,12 +500,18 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (type > BEVEL_AMT_PERCENT) {
type = BEVEL_AMT_OFFSET;
}
+ if (opdata->value_mode == OFFSET_VALUE && type == BEVEL_AMT_PERCENT)
+ opdata->value_mode = OFFSET_VALUE_PERCENT;
+ else if (opdata->value_mode == OFFSET_VALUE_PERCENT && type != BEVEL_AMT_PERCENT)
+ opdata->value_mode = OFFSET_VALUE;
RNA_property_enum_set(op->ptr, prop, type);
}
- /* Update factor accordingly to new offset_type. */
- if (!has_numinput) {
- RNA_float_set(op->ptr, "offset", edbm_bevel_mval_factor(op, event));
- }
+ /* Update offset accordingly to new offset_type. */
+ if (!has_numinput &&
+ (opdata->value_mode == OFFSET_VALUE || opdata->value_mode == OFFSET_VALUE_PERCENT))
+ {
+ edbm_bevel_mouse_set_value(op, event);
+ }
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
handled = true;
@@ -470,7 +531,24 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
case PKEY:
if (event->val == KM_RELEASE)
break;
- opdata->mouse_controls_profile = !opdata->mouse_controls_profile;
+ if (opdata->value_mode == PROFILE_VALUE) {
+ opdata->value_mode = OFFSET_VALUE;
+ }
+ else {
+ opdata->value_mode = PROFILE_VALUE;
+ }
+ edbm_bevel_calc_initial_length(op, event, true);
+ break;
+ case SKEY:
+ if (event->val == KM_RELEASE)
+ break;
+ if (opdata->value_mode == SEGMENTS_VALUE) {
+ opdata->value_mode = OFFSET_VALUE;
+ }
+ else {
+ opdata->value_mode = SEGMENTS_VALUE;
+ }
+ edbm_bevel_calc_initial_length(op, event, true);
break;
case VKEY:
if (event->val == KM_RELEASE)
@@ -488,10 +566,8 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* Modal numinput inactive, try to handle numeric inputs last... */
- if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input, event)) {
- float value = RNA_float_get(op->ptr, "offset");
- applyNumInput(&opdata->num_input, &value);
- RNA_float_set(op->ptr, "offset", value);
+ if (!handled && event->val == KM_PRESS && handleNumInput(C, &opdata->num_input[opdata->value_mode], event)) {
+ edbm_bevel_numinput_set_value(op);
edbm_bevel_calc(op);
edbm_bevel_update_header(C, op);
return OPERATOR_RUNNING_MODAL;
@@ -542,12 +618,13 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
- RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
+ RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
- "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
+ "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices");
RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap",
- "Do not allow beveled edges/vertices to overlap each other");
+ "Do not allow beveled edges/vertices to overlap each other");
RNA_def_boolean(ot->srna, "loop_slide", true, "Loop Slide", "Prefer slide along edge to even widths");
- RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material", "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
+ RNA_def_int(ot->srna, "material", -1, -1, INT_MAX, "Material",
+ "Material for bevel faces (-1 means use adjacent faces)", -1, 100);
}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index b9d3fd6c8be..8b16b2a977e 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -49,7 +49,7 @@
# endif
# include "BLI_array_store.h"
-# include "BLI_math_base.h"
+# include "BLI_array_store_utils.h"
/* check on best size later... */
# define ARRAY_CHUNK_SIZE 256
@@ -89,8 +89,7 @@ typedef struct UndoMesh {
#ifdef USE_ARRAY_STORE
/* NULL arrays are considered empty */
- struct {
- /* most data is stored as 'custom' data */
+ struct { /* most data is stored as 'custom' data */
BArrayCustomData *vdata, *edata, *ldata, *pdata;
BArrayState **keyblocks;
BArrayState *mselect;
@@ -105,8 +104,7 @@ typedef struct UndoMesh {
* \{ */
static struct {
- BArrayStore **bs_all;
- int bs_all_len;
+ struct BArrayStore_AtSize bs_stride;
int users;
/* We could have the undo API pass in the previous state, for now store a local list */
@@ -118,57 +116,6 @@ static struct {
} um_arraystore = {NULL};
-static BArrayStore *array_store_at_size_ensure(const int stride)
-{
- if (um_arraystore.bs_all_len < stride) {
- um_arraystore.bs_all_len = stride;
- um_arraystore.bs_all = MEM_recallocN(um_arraystore.bs_all, sizeof(*um_arraystore.bs_all) * stride);
- }
- BArrayStore **bs_p = &um_arraystore.bs_all[stride - 1];
-
- if ((*bs_p) == NULL) {
-#if 0
- unsigned int chunk_count = ARRAY_CHUNK_SIZE;
-#else
- /* calculate best chunk-count to fit a power of two */
- unsigned int chunk_count = ARRAY_CHUNK_SIZE;
- {
- unsigned int size = chunk_count * stride;
- size = power_of_2_max_u(size);
- size = MEM_SIZE_OPTIMAL(size);
- chunk_count = size / stride;
- }
-#endif
-
- (*bs_p) = BLI_array_store_create(stride, chunk_count);
- }
- return *bs_p;
-}
-
-static BArrayStore *array_store_at_size_get(const int stride)
-{
- BLI_assert(stride > 0 && stride <= um_arraystore.bs_all_len);
- return um_arraystore.bs_all[stride - 1];
-}
-
-#ifdef DEBUG_PRINT
-static void um_arraystore_memory_usage(size_t *r_size_expanded, size_t *r_size_compacted)
-{
- size_t size_compacted = 0;
- size_t size_expanded = 0;
- for (int i = 0; i < um_arraystore.bs_all_len; i++) {
- BArrayStore *bs = um_arraystore.bs_all[i];
- if (bs) {
- size_compacted += BLI_array_store_calc_size_compacted_get(bs);
- size_expanded += BLI_array_store_calc_size_expanded_get(bs);
- }
- }
-
- *r_size_expanded = size_expanded;
- *r_size_compacted = size_compacted;
-}
-#endif
-
static void um_arraystore_cd_compact(
struct CustomData *cdata, const size_t data_len,
bool create,
@@ -194,7 +141,7 @@ static void um_arraystore_cd_compact(
}
const int stride = CustomData_sizeof(type);
- BArrayStore *bs = create ? array_store_at_size_ensure(stride) : NULL;
+ BArrayStore *bs = create ? BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) : NULL;
const int layer_len = layer_end - layer_start;
if (create) {
@@ -299,7 +246,7 @@ static void um_arraystore_cd_free(BArrayCustomData *bcd)
while (bcd) {
BArrayCustomData *bcd_next = bcd->next;
const int stride = CustomData_sizeof(bcd->type);
- BArrayStore *bs = array_store_at_size_get(stride);
+ BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
for (int i = 0; i < bcd->states_len; i++) {
if (bcd->states[i]) {
BLI_array_store_state_remove(bs, bcd->states[i]);
@@ -328,7 +275,7 @@ static void um_arraystore_compact_ex(
if (me->key && me->key->totkey) {
const size_t stride = me->key->elemsize;
- BArrayStore *bs = create ? array_store_at_size_ensure(stride) : NULL;
+ BArrayStore *bs = create ? BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE) : NULL;
if (create) {
um->store.keyblocks = MEM_mallocN(me->key->totkey * sizeof(*um->store.keyblocks), __func__);
}
@@ -355,7 +302,7 @@ static void um_arraystore_compact_ex(
if (create) {
BArrayState *state_reference = um_ref ? um_ref->store.mselect : NULL;
const size_t stride = sizeof(*me->mselect);
- BArrayStore *bs = array_store_at_size_ensure(stride);
+ BArrayStore *bs = BLI_array_store_at_size_ensure(&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE);
um->store.mselect = BLI_array_store_state_add(
bs, me->mselect, (size_t)me->totselect * stride, state_reference);
}
@@ -384,7 +331,7 @@ static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref
{
#ifdef DEBUG_PRINT
size_t size_expanded_prev, size_compacted_prev;
- um_arraystore_memory_usage(&size_expanded_prev, &size_compacted_prev);
+ BLI_array_store_at_size_calc_memory_usage(&um_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev);
#endif
#ifdef DEBUG_TIME
@@ -400,7 +347,7 @@ static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref
#ifdef DEBUG_PRINT
{
size_t size_expanded, size_compacted;
- um_arraystore_memory_usage(&size_expanded, &size_compacted);
+ BLI_array_store_at_size_calc_memory_usage(&um_arraystore.bs_stride, &size_expanded, &size_compacted);
const double percent_total = size_expanded ?
(((double)size_compacted / (double)size_expanded) * 100.0) : -1.0;
@@ -483,7 +430,7 @@ static void um_arraystore_free(UndoMesh *um)
if (um->store.keyblocks) {
const size_t stride = me->key->elemsize;
- BArrayStore *bs = array_store_at_size_get(stride);
+ BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
for (int i = 0; i < me->key->totkey; i++) {
BArrayState *state = um->store.keyblocks[i];
BLI_array_store_state_remove(bs, state);
@@ -494,7 +441,7 @@ static void um_arraystore_free(UndoMesh *um)
if (um->store.mselect) {
const size_t stride = sizeof(*me->mselect);
- BArrayStore *bs = array_store_at_size_get(stride);
+ BArrayStore *bs = BLI_array_store_at_size_get(&um_arraystore.bs_stride, stride);
BArrayState *state = um->store.mselect;
BLI_array_store_state_remove(bs, state);
um->store.mselect = NULL;
@@ -508,15 +455,7 @@ static void um_arraystore_free(UndoMesh *um)
#ifdef DEBUG_PRINT
printf("mesh undo store: freeing all data!\n");
#endif
- for (int i = 0; i < um_arraystore.bs_all_len; i += 1) {
- if (um_arraystore.bs_all[i]) {
- BLI_array_store_destroy(um_arraystore.bs_all[i]);
- }
- }
-
- MEM_freeN(um_arraystore.bs_all);
- um_arraystore.bs_all = NULL;
- um_arraystore.bs_all_len = 0;
+ BLI_array_store_at_size_clear(&um_arraystore.bs_stride);
#ifdef USE_ARRAY_STORE_THREAD
BLI_task_pool_free(um_arraystore.task_pool);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 014268262c4..93bac3f6660 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -327,6 +327,13 @@ float glaGetOneFloat(int param)
return v;
}
+int glaGetOneInt(int param)
+{
+ GLint v;
+ glGetIntegerv(param, &v);
+ return v;
+}
+
void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y)
{
GLubyte dummy = 0;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d273f8320a1..e4c26064fec 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -202,7 +202,7 @@ typedef struct ProjPaintImage {
*/
typedef struct ProjStrokeHandle {
/* Support for painting from multiple views at once,
- * currently used to impliment summetry painting,
+ * currently used to impliment symmetry painting,
* we can assume at least the first is set while painting. */
struct ProjPaintState *ps_views[8];
int ps_views_tot;
@@ -717,7 +717,7 @@ static bool project_paint_PickColor(
}
/**
- * Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test)
+ * Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusion test)
* \return
* - `0`: no occlusion
* - `-1`: no occlusion but 2D intersection is true
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 65857cccb15..67fbd000b64 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -58,6 +58,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_basic_shader.h"
+
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -160,11 +162,11 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(3, 0xAAAA);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+ GPU_basic_shader_line_width(3.0);
glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
- glLineWidth(3.0);
if (stroke->constrain_line) {
sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
stroke->constrained_pos[0], stroke->constrained_pos[1]);
@@ -175,7 +177,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
}
glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
- glLineWidth(1.0);
+ GPU_basic_shader_line_width(1.0);
if (stroke->constrain_line) {
sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
stroke->constrained_pos[0], stroke->constrained_pos[1]);
@@ -185,7 +187,7 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
x, y);
}
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 15ab4ca04a7..2a1e7704b51 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1323,7 +1323,7 @@ static bool do_weight_paint_normalize_all_locked(
/**
* \note same as function above except it does a second pass without active group
- * if nomalize fails with it.
+ * if normalize fails with it.
*/
static void do_weight_paint_normalize_all_locked_try_active(
MDeformVert *dvert, const int defbase_tot, const bool *vgroup_validmap,
@@ -1340,7 +1340,7 @@ static void do_weight_paint_normalize_all_locked_try_active(
* - With 1.0 weight painted into active:
* nonzero locked weight; first pass zeroed out unlocked weight; scale 1 down to fit.
* - With 0.0 weight painted into active:
- * no unlocked groups; first pass did nothing; increaze 0 to fit.
+ * no unlocked groups; first pass did nothing; increase 0 to fit.
*/
do_weight_paint_normalize_all_locked(dvert, defbase_tot, vgroup_validmap, lock_flags);
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 1c5be3d1fb5..695d04d3850 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -336,8 +336,10 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
/* draw boundary border for frame if stabilization is enabled */
if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
glColor3f(0.0f, 0.0f, 0.0f);
- glLineStipple(3, 0xaaaa);
- glEnable(GL_LINE_STIPPLE);
+
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_NOR);
@@ -357,7 +359,7 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
glPopMatrix();
glDisable(GL_COLOR_LOGIC_OP);
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
}
@@ -627,8 +629,8 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
glEnd();
glColor3f(0.0f, 0.0f, 0.0f);
- glLineStipple(3, 0xaaaa);
- glEnable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_NOR);
@@ -638,7 +640,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
glEnd();
glDisable(GL_COLOR_LOGIC_OP);
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
}
@@ -647,8 +649,11 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
glTranslate2fv(marker_pos);
if (tiny) {
- glLineStipple(3, 0xaaaa);
- glEnable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+ }
+ else {
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
}
if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
@@ -713,8 +718,12 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
glEnd();
}
- if (tiny)
- glDisable(GL_LINE_STIPPLE);
+ if (tiny) {
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ }
+ else {
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE);
+ }
glPopMatrix();
}
@@ -852,16 +861,12 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
glLineWidth(outline ? 3.0f : 1.0f);
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(3, 0xaaaa);
-
glBegin(GL_LINES);
glVertex2f(0.0f, 0.0f);
glVertex2fv(tilt_ctrl);
glEnd();
- glDisable(GL_LINE_STIPPLE);
-
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
/* slider to control pattern tilt */
draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
@@ -1133,11 +1138,14 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
const bool thick = draw_outline && !tiny;
if (stipple) {
- glLineStipple(3, 0xaaaa);
- glEnable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+ }
+ else {
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
}
- glLineWidth(thick ? 3.0f : 1.0f);
+ GPU_basic_shader_line_width(thick ? 3.0f : 1.0f);
/* Draw rectangle itself. */
glBegin(GL_LINE_LOOP);
@@ -1169,8 +1177,12 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
glPopAttrib();
}
- if (stipple)
- glDisable(GL_LINE_STIPPLE);
+ if (stipple) {
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ }
+ else {
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE);
+ }
}
/* Draw sliders. */
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 8e1f781827a..fc3341bfb92 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1925,7 +1925,8 @@ static bool file_is_blend_backup(const char *str)
return (retval);
}
-static int path_extension_type(const char *path)
+/* TODO: Maybe we should move this to BLI? On the other hand, it's using defines from spacefile area, so not sure... */
+int ED_path_extension_type(const char *path)
{
if (BLO_has_bfile_extension(path)) {
return FILE_TYPE_BLENDER;
@@ -1977,12 +1978,12 @@ static int file_extension_type(const char *dir, const char *relpath)
{
char path[FILE_MAX];
BLI_join_dirfile(path, sizeof(path), dir, relpath);
- return path_extension_type(path);
+ return ED_path_extension_type(path);
}
int ED_file_extension_icon(const char *path)
{
- int type = path_extension_type(path);
+ const int type = ED_path_extension_type(path);
switch (type) {
case FILE_TYPE_BLENDER:
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index b624c7cba75..554009da8be 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1579,11 +1579,19 @@ static void outliner_draw_tree_element(
glDisable(GL_BLEND);
/* name */
- if (active == OL_DRAWSEL_NORMAL) UI_ThemeColor(TH_TEXT_HI);
- else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
- else UI_ThemeColor(TH_TEXT);
-
- UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name);
+ if ((tselem->flag & TSE_TEXTBUT) == 0) {
+ if (active == OL_DRAWSEL_NORMAL) {
+ UI_ThemeColor(TH_TEXT_HI);
+ }
+ else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f);
+ }
+ else {
+ UI_ThemeColor(TH_TEXT);
+ }
+
+ UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name);
+ }
offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 9c2d115108d..adb7cf4940c 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -593,7 +593,6 @@ void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, f
ymid1 = (y2 - y1) * 0.25f + y1;
ymid2 = (y2 - y1) * 0.65f + y1;
- glShadeModel(GL_SMOOTH);
glBegin(GL_QUADS);
if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; }
@@ -840,25 +839,25 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
else
UI_GetColorPtrShade3ubv(col, col, outline_tint);
- glColor3ubv((GLubyte *)col);
-
+ if ((seq->type == SEQ_TYPE_META) ||
+ ((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
+ {
+ drawmeta_contents(scene, seq, x1, y1, x2, y2);
+ }
+
if (seq->flag & SEQ_MUTE) {
glEnable(GL_LINE_STIPPLE);
glLineStipple(1, 0x8888);
}
+ glColor3ubv((GLubyte *)col);
+
UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0);
if (seq->flag & SEQ_MUTE) {
glDisable(GL_LINE_STIPPLE);
}
- if ((seq->type == SEQ_TYPE_META) ||
- ((seq->type == SEQ_TYPE_SCENE) && (seq->flag & SEQ_SCENE_STRIPS)))
- {
- drawmeta_contents(scene, seq, x1, y1, x2, y2);
- }
-
/* calculate if seq is long enough to print a name */
x1 = seq->startdisp + handsize_clamped;
x2 = seq->enddisp - handsize_clamped;
@@ -1630,7 +1629,8 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
// NOTE: the gridlines are currently spaced every 25 frames, which is only fine for 25 fps, but maybe not for 30...
UI_view2d_constant_grid_draw(v2d);
- if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
+ /* Only draw backdrop in pure sequence view. */
+ if (sseq->view == SEQ_VIEW_SEQUENCE && sseq->draw_flag & SEQ_DRAW_BACKDROP) {
draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, true);
UI_view2d_view_ortho(v2d);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 7475e8b27fd..48c49f36471 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -943,16 +943,26 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot)
/* ****** Selected Grouped ****** */
+enum {
+ SEQ_SELECT_GROUP_TYPE,
+ SEQ_SELECT_GROUP_TYPE_BASIC,
+ SEQ_SELECT_GROUP_TYPE_EFFECT,
+ SEQ_SELECT_GROUP_DATA,
+ SEQ_SELECT_GROUP_EFFECT,
+ SEQ_SELECT_GROUP_EFFECT_LINK,
+ SEQ_SELECT_GROUP_OVERLAP,
+};
+
static EnumPropertyItem sequencer_prop_select_grouped_types[] = {
- {1, "TYPE", 0, "Type", "Shared strip type"},
- {2, "TYPE_BASIC", 0, "Global Type", "All strips of same basic type (Graphical or Sound)"},
- {3, "TYPE_EFFECT", 0, "Effect Type",
+ {SEQ_SELECT_GROUP_TYPE, "TYPE", 0, "Type", "Shared strip type"},
+ {SEQ_SELECT_GROUP_TYPE_BASIC, "TYPE_BASIC", 0, "Global Type", "All strips of same basic type (Graphical or Sound)"},
+ {SEQ_SELECT_GROUP_TYPE_EFFECT, "TYPE_EFFECT", 0, "Effect Type",
"Shared strip effect type (if active strip is not an effect one, select all non-effect strips)"},
- {4, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"},
- {5, "EFFECT", 0, "Effect", "Shared effects"},
- {6, "EFFECT_LINK", 0, "Effect/Linked",
+ {SEQ_SELECT_GROUP_DATA, "DATA", 0, "Data", "Shared data (scene, image, sound, etc.)"},
+ {SEQ_SELECT_GROUP_EFFECT, "EFFECT", 0, "Effect", "Shared effects"},
+ {SEQ_SELECT_GROUP_EFFECT_LINK, "EFFECT_LINK", 0, "Effect/Linked",
"Other strips affected by the active one (sharing some time, and below or effect-assigned)"},
- {7, "OVERLAP", 0, "Overlap", "Overlapping time"},
+ {SEQ_SELECT_GROUP_OVERLAP, "OVERLAP", 0, "Overlap", "Overlapping time"},
{0, NULL, 0, NULL, NULL}
};
@@ -962,14 +972,16 @@ static EnumPropertyItem sequencer_prop_select_grouped_types[] = {
#define SEQ_USE_DATA(_seq) (ELEM(_seq->type, SEQ_TYPE_SCENE, SEQ_TYPE_MOVIECLIP, SEQ_TYPE_MASK) || SEQ_HAS_PATH(_seq))
-static bool select_grouped_type(Editing *ed, Sequence *actseq)
+#define SEQ_CHANNEL_CHECK(_seq, _chan) (ELEM((_chan), 0, (_seq)->machine))
+
+static bool select_grouped_type(Editing *ed, Sequence *actseq, const int channel)
{
Sequence *seq;
bool changed = false;
SEQP_BEGIN (ed, seq)
{
- if (seq->type == actseq->type) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == actseq->type) {
seq->flag |= SELECT;
changed = true;
}
@@ -979,7 +991,7 @@ static bool select_grouped_type(Editing *ed, Sequence *actseq)
return changed;
}
-static bool select_grouped_type_basic(Editing *ed, Sequence *actseq)
+static bool select_grouped_type_basic(Editing *ed, Sequence *actseq, const int channel)
{
Sequence *seq;
bool changed = false;
@@ -987,7 +999,7 @@ static bool select_grouped_type_basic(Editing *ed, Sequence *actseq)
SEQP_BEGIN (ed, seq)
{
- if (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq)) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && (is_sound ? SEQ_IS_SOUND(seq) : !SEQ_IS_SOUND(seq))) {
seq->flag |= SELECT;
changed = true;
}
@@ -997,7 +1009,7 @@ static bool select_grouped_type_basic(Editing *ed, Sequence *actseq)
return changed;
}
-static bool select_grouped_type_effect(Editing *ed, Sequence *actseq)
+static bool select_grouped_type_effect(Editing *ed, Sequence *actseq, const int channel)
{
Sequence *seq;
bool changed = false;
@@ -1005,7 +1017,7 @@ static bool select_grouped_type_effect(Editing *ed, Sequence *actseq)
SEQP_BEGIN (ed, seq)
{
- if (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq)) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && (is_effect ? SEQ_IS_EFFECT(seq) : !SEQ_IS_EFFECT(seq))) {
seq->flag |= SELECT;
changed = true;
}
@@ -1015,7 +1027,7 @@ static bool select_grouped_type_effect(Editing *ed, Sequence *actseq)
return changed;
}
-static bool select_grouped_data(Editing *ed, Sequence *actseq)
+static bool select_grouped_data(Editing *ed, Sequence *actseq, const int channel)
{
Sequence *seq;
bool changed = false;
@@ -1027,7 +1039,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
if (SEQ_HAS_PATH(actseq) && dir) {
SEQP_BEGIN (ed, seq)
{
- if (SEQ_HAS_PATH(seq) && seq->strip && STREQ(seq->strip->dir, dir)) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && SEQ_HAS_PATH(seq) && seq->strip && STREQ(seq->strip->dir, dir)) {
seq->flag |= SELECT;
changed = true;
}
@@ -1038,7 +1050,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
Scene *sce = actseq->scene;
SEQP_BEGIN (ed, seq)
{
- if (seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_SCENE && seq->scene == sce) {
seq->flag |= SELECT;
changed = true;
}
@@ -1049,7 +1061,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
MovieClip *clip = actseq->clip;
SEQP_BEGIN (ed, seq)
{
- if (seq->type == SEQ_TYPE_MOVIECLIP && seq->clip == clip) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MOVIECLIP && seq->clip == clip) {
seq->flag |= SELECT;
changed = true;
}
@@ -1060,7 +1072,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
struct Mask *mask = actseq->mask;
SEQP_BEGIN (ed, seq)
{
- if (seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && seq->type == SEQ_TYPE_MASK && seq->mask == mask) {
seq->flag |= SELECT;
changed = true;
}
@@ -1071,7 +1083,7 @@ static bool select_grouped_data(Editing *ed, Sequence *actseq)
return changed;
}
-static bool select_grouped_effect(Editing *ed, Sequence *actseq)
+static bool select_grouped_effect(Editing *ed, Sequence *actseq, const int channel)
{
Sequence *seq;
bool changed = false;
@@ -1083,7 +1095,9 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq)
SEQP_BEGIN (ed, seq)
{
- if ((seq->type & SEQ_TYPE_EFFECT) && ELEM(actseq, seq->seq1, seq->seq2, seq->seq3)) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && (seq->type & SEQ_TYPE_EFFECT) &&
+ ELEM(actseq, seq->seq1, seq->seq2, seq->seq3))
+ {
effects[seq->type] = true;
}
}
@@ -1091,7 +1105,7 @@ static bool select_grouped_effect(Editing *ed, Sequence *actseq)
SEQP_BEGIN (ed, seq)
{
- if (effects[seq->type]) {
+ if (SEQ_CHANNEL_CHECK(seq, channel) && effects[seq->type]) {
if (seq->seq1) seq->seq1->flag |= SELECT;
if (seq->seq2) seq->seq2->flag |= SELECT;
if (seq->seq3) seq->seq3->flag |= SELECT;
@@ -1120,7 +1134,7 @@ static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq)
return changed;
}
-static bool select_grouped_effect_link(Editing *ed, Sequence *actseq)
+static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int channel)
{
Sequence *seq = NULL;
bool changed = false;
@@ -1144,7 +1158,8 @@ static bool select_grouped_effect_link(Editing *ed, Sequence *actseq)
/* Ignore all seqs already selected! */
/* Ignore all seqs not sharing some time with active one. */
/* Ignore all seqs of incompatible types (audio vs video). */
- if ((seq->flag & SELECT) || (seq->startdisp >= enddisp) || (seq->enddisp < startdisp) ||
+ if (!SEQ_CHANNEL_CHECK(seq, channel) ||
+ (seq->flag & SELECT) || (seq->startdisp >= enddisp) || (seq->enddisp < startdisp) ||
(!is_audio && SEQ_IS_SOUND(seq)) ||
(is_audio && !((seq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(seq))))
{
@@ -1190,17 +1205,19 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq, *actseq = BKE_sequencer_active_get(scene);
- int type = RNA_enum_get(op->ptr, "type");
- bool changed = false, extend;
- extend = RNA_boolean_get(op->ptr, "extend");
+ const int type = RNA_enum_get(op->ptr, "type");
+ const int channel = RNA_boolean_get(op->ptr, "use_active_channel") ? actseq->machine : 0;
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+
+ bool changed = false;
if (actseq == NULL) {
BKE_report(op->reports, RPT_ERROR, "No active sequence!");
return OPERATOR_CANCELLED;
}
- if (extend == 0) {
+ if (!extend) {
SEQP_BEGIN (ed, seq)
{
seq->flag &= ~SELECT;
@@ -1209,13 +1226,32 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
SEQ_END;
}
- if (type == 1) changed |= select_grouped_type(ed, actseq);
- else if (type == 2) changed |= select_grouped_type_basic(ed, actseq);
- else if (type == 3) changed |= select_grouped_type_effect(ed, actseq);
- else if (type == 4) changed |= select_grouped_data(ed, actseq);
- else if (type == 5) changed |= select_grouped_effect(ed, actseq);
- else if (type == 6) changed |= select_grouped_effect_link(ed, actseq);
- else if (type == 7) changed |= select_grouped_time_overlap(ed, actseq);
+ switch (type) {
+ case SEQ_SELECT_GROUP_TYPE:
+ changed |= select_grouped_type(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_TYPE_BASIC:
+ changed |= select_grouped_type_basic(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_TYPE_EFFECT:
+ changed |= select_grouped_type_effect(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_DATA:
+ changed |= select_grouped_data(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_EFFECT:
+ changed |= select_grouped_effect(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_EFFECT_LINK:
+ changed |= select_grouped_effect_link(ed, actseq, channel);
+ break;
+ case SEQ_SELECT_GROUP_OVERLAP:
+ changed |= select_grouped_time_overlap(ed, actseq);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
@@ -1241,7 +1277,9 @@ void SEQUENCER_OT_select_grouped(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
ot->prop = RNA_def_enum(ot->srna, "type", sequencer_prop_select_grouped_types, 0, "Type", "");
+ RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "use_active_channel", false, "Same Channel",
+ "Only consider strips on the same channel as the active one");
}
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 04cff288b03..c38c57b9528 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -259,10 +259,8 @@ static void confirm_suggestion(Text *text)
// for (i = 0; i < skipleft; i++)
// txt_move_left(text, 0);
- for (i = 0; i < over; i++)
- txt_move_left(text, 1);
-
- txt_insert_buf(text, sel->name);
+ BLI_assert(memcmp(sel->name, &line[i], over) == 0);
+ txt_insert_buf(text, sel->name + over);
// for (i = 0; i < skipleft; i++)
// txt_move_right(text, 0);
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index 9872b05da63..cf738de0202 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -130,7 +130,6 @@ void draw_motion_path_instance(Scene *scene,
mpv_start = (mpath->points + sind);
/* draw curve-line of path */
- glShadeModel(GL_SMOOTH);
glBegin(GL_LINE_STRIP);
for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
@@ -187,7 +186,6 @@ void draw_motion_path_instance(Scene *scene,
}
glEnd();
- glShadeModel(GL_FLAT);
glPointSize(1.0);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index f7c1e2ee981..1d9a515a5f2 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -431,10 +431,9 @@ static void draw_bonevert_solid(void)
glNewList(displist, GL_COMPILE);
qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- glShadeModel(GL_SMOOTH);
+ gluQuadricDrawStyle(qobj, GLU_FILL);
+ /* Draw tips of a bone */
gluSphere(qobj, 0.05, 8, 5);
- glShadeModel(GL_FLAT);
gluDeleteQuadric(qobj);
glEndList();
@@ -890,7 +889,6 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
gluQuadricDrawStyle(qobj, GLU_FILL);
- glShadeModel(GL_SMOOTH);
}
else {
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
@@ -968,7 +966,6 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
/* restore */
if (dt == OB_SOLID) {
- glShadeModel(GL_FLAT);
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
@@ -986,10 +983,11 @@ static GLubyte bm_dot7[] = {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38};
static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
+ /* call this once, avoid constant changing */
+ BLI_assert(glaGetOneInt(GL_UNPACK_ALIGNMENT) == 1);
+
float length;
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
if (pchan)
length = pchan->bone->length;
else
@@ -1769,7 +1767,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* and draw blended distances */
if (arm->flag & ARM_POSEMODE) {
glEnable(GL_BLEND);
- //glShadeModel(GL_SMOOTH);
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -1792,7 +1789,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
- //glShadeModel(GL_FLAT);
}
}
@@ -2216,7 +2212,6 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* and draw blended distances */
glEnable(GL_BLEND);
- //glShadeModel(GL_SMOOTH);
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -2231,7 +2226,6 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
- //glShadeModel(GL_FLAT);
}
/* if solid we draw it first */
@@ -2699,6 +2693,11 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (v3d->flag2 & V3D_RENDER_OVERRIDE)
return true;
+ /* needed for 'draw_line_bone' which draws pixel. */
+ if (arm->drawtype == ARM_LINE) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ }
+
if (dt > OB_WIRE) {
/* we use color for solid lighting */
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
@@ -2774,5 +2773,9 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* restore */
glFrontFace(GL_CCW);
+ if (arm->drawtype == ARM_LINE) {
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ }
+
return retval;
}
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 86f3edfff28..ee82a4c5072 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -369,15 +369,18 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material
}
if (c_badtex) lit = 0;
- if (lit != c_lit || ma != c_ma) {
- if (lit) {
- int options = GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR;
+ if (lit != c_lit || ma != c_ma || textured != c_textured) {
+ int options = GPU_SHADER_USE_COLOR;
- if (gtexdraw.two_sided_lighting)
- options |= GPU_SHADER_TWO_SIDED;
- if (c_textured && !c_badtex)
- options |= GPU_SHADER_TEXTURE_2D;
+ if (c_textured && !c_badtex) {
+ options |= GPU_SHADER_TEXTURE_2D;
+ }
+ if (gtexdraw.two_sided_lighting) {
+ options |= GPU_SHADER_TWO_SIDED;
+ }
+ if (lit) {
+ options |= GPU_SHADER_LIGHTING;
if (!ma)
ma = give_current_material_or_def(NULL, 0); /* default material */
@@ -385,12 +388,10 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material
mul_v3_v3fl(specular, &ma->specr, ma->spec);
GPU_basic_shader_colors(NULL, specular, ma->har, 1.0f);
- GPU_basic_shader_bind(options);
- }
- else {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
+ GPU_basic_shader_bind(options);
+
c_lit = lit;
c_ma = ma;
}
@@ -495,7 +496,6 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
- glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
}
@@ -527,7 +527,6 @@ static void draw_textured_end(void)
GPU_set_tpage(NULL, 0, 0);
}
- glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
@@ -1311,8 +1310,8 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, DerivedMesh *dm,
}
glColor4ub(255, 255, 255, 96);
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(1, 0xAAAA);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(1, 0xAAAA);
dm->drawMappedEdges(dm, (DMSetDrawOptions)edgemask_cb, user_data);
@@ -1324,7 +1323,7 @@ void draw_mesh_paint_weight_edges(RegionView3D *rv3d, DerivedMesh *dm,
glEnable(GL_DEPTH_TEST);
}
- glDisable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
if (use_alpha) {
glDisable(GL_BLEND);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 848772600ba..07e8325756f 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -1209,7 +1209,7 @@ static void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
if ((drawcone || drawshadowbox) && !v3d->transp) {
/* in this case we need to draw delayed */
- ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag);
+ ED_view3d_after_add(v3d->xray ? &v3d->afterdraw_xraytransp : &v3d->afterdraw_transp, base, dflag);
return;
}
@@ -1592,12 +1592,9 @@ static void draw_bundle_sphere(void)
displist = glGenLists(1);
glNewList(displist, GL_COMPILE);
-
qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
- glShadeModel(GL_SMOOTH);
gluSphere(qobj, 0.05, 8, 8);
- glShadeModel(GL_FLAT);
gluDeleteQuadric(qobj);
glEndList();
@@ -1779,8 +1776,6 @@ static void draw_viewport_reconstruction(
GPU_basic_shader_colors(NULL, NULL, 0, 1.0f);
GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- glShadeModel(GL_SMOOTH);
-
tracking_object = tracking->objects.first;
while (tracking_object) {
draw_viewport_object_reconstruction(
@@ -1791,7 +1786,6 @@ static void draw_viewport_reconstruction(
}
/* restore */
- glShadeModel(GL_FLAT);
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
@@ -1930,16 +1924,15 @@ static void drawcamera_stereo3d(
if (is_stereo3d_cameras) {
/* draw connecting lines */
- glPushAttrib(GL_ENABLE_BIT);
-
- glLineStipple(2, 0xAAAA);
- glEnable(GL_LINE_STIPPLE);
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(2, 0xAAAA);
glBegin(GL_LINES);
glVertex3fv(origin[0]);
glVertex3fv(origin[1]);
glEnd();
- glPopAttrib();
+
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
}
/* draw convergence plane */
@@ -2351,7 +2344,6 @@ static void drawlattice(View3D *v3d, Object *ob)
if (ob->defbase.first && lt->dvert) {
actdef_wcol = ob->actdef;
- glShadeModel(GL_SMOOTH);
}
}
@@ -2380,10 +2372,6 @@ static void drawlattice(View3D *v3d, Object *ob)
}
}
glEnd();
-
- /* restoration for weight colors */
- if (actdef_wcol)
- glShadeModel(GL_FLAT);
if (is_edit) {
BPoint *actbp = BKE_lattice_active_point_get(lt);
@@ -3248,17 +3236,15 @@ static void draw_em_fancy_edges(BMEditMesh *em, Scene *scene, View3D *v3d,
((ts->selectmode & SCE_SELECT_VERTEX) || (me->drawflag & ME_DRAWEIGHT)))
{
if (draw_dm_edges_weight_check(me, v3d)) {
- glShadeModel(GL_SMOOTH);
+ // Interpolate vertex weights
draw_dm_edges_weight_interp(em, cageDM, ts->weightuser);
- glShadeModel(GL_FLAT);
}
else if (ts->selectmode == SCE_SELECT_FACE) {
draw_dm_edges_sel(em, cageDM, wireCol, selCol, actCol, eed_act);
}
else {
- glShadeModel(GL_SMOOTH);
+ // Interpolate vertex selection
draw_dm_edges_sel_interp(em, cageDM, wireCol, selCol);
- glShadeModel(GL_FLAT);
}
}
else {
@@ -4461,10 +4447,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
glEnableClientState(GL_VERTEX_ARRAY);
- if (ob->type == OB_MBALL) { /* mball always smooth shaded */
- glShadeModel(GL_SMOOTH);
- }
-
/* track current material, -1 for none (needed for lines) */
short col = -1;
@@ -4486,7 +4468,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
// glVertexPointer(3, GL_FLOAT, 0, dl->verts);
// glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
-
glBegin(GL_LINE_STRIP);
for (int nr = dl->nr; nr; nr--, data += 3)
glVertex3fv(data);
@@ -4517,15 +4498,15 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL);
col = dl->col;
}
-
- if (dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH);
- else glShadeModel(GL_FLAT);
+ /* FLAT/SMOOTH shading for surfaces */
+ glShadeModel((dl->rt & CU_SMOOTH) ? GL_SMOOTH : GL_FLAT);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, dl->verts);
glNormalPointer(GL_FLOAT, 0, dl->nors);
glDrawElements(GL_QUADS, 4 * dl->totindex, GL_UNSIGNED_INT, dl->index);
glDisableClientState(GL_NORMAL_ARRAY);
+ glShadeModel(GL_SMOOTH);
}
break;
@@ -4570,7 +4551,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
}
glDisableClientState(GL_VERTEX_ARRAY);
- glShadeModel(GL_FLAT);
glFrontFace(GL_CCW);
if (col != -1) {
@@ -5780,8 +5760,6 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
- glShadeModel(GL_SMOOTH);
-
if (pset->brushtype == PE_BRUSH_WEIGHT)
glLineWidth(2.0f);
@@ -5896,7 +5874,6 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
- glShadeModel(GL_FLAT);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 445a4cbdfd6..9fb990b35a0 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -657,7 +657,6 @@ static void draw_rotation_guide(RegionView3D *rv3d)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glShadeModel(GL_SMOOTH);
glPointSize(5);
glEnable(GL_POINT_SMOOTH);
glDepthMask(0); /* don't overwrite zbuf */
@@ -2999,18 +2998,16 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
glLoadIdentity();
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
}
-
+ // Draw world
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
- glShadeModel(GL_SMOOTH);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glEnd();
- glShadeModel(GL_FLAT);
-
+ //
if (material_not_bound) {
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -3048,8 +3045,6 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
glPushMatrix();
glLoadIdentity();
- glShadeModel(GL_SMOOTH);
-
/* calculate buffers the first time only */
if (!buf_calculated) {
for (x = 0; x < VIEWGRAD_RES_X; x++) {
@@ -3135,8 +3130,6 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
- glShadeModel(GL_FLAT);
-
#undef VIEWGRAD_RES_X
#undef VIEWGRAD_RES_Y
}
@@ -3160,7 +3153,6 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
- glShadeModel(GL_SMOOTH);
glBegin(GL_QUADS);
UI_ThemeColor(TH_LOW_GRAD);
glVertex3f(-1.0, -1.0, 1.0);
@@ -3169,8 +3161,6 @@ static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glEnd();
- glShadeModel(GL_FLAT);
-
glDepthFunc(GL_LEQUAL);
glDisable(GL_DEPTH_TEST);
@@ -4071,6 +4061,10 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
v3d->flag |= V3D_INVALID_BACKBUF;
+
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xray));
+ BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_xraytransp));
}
#ifdef DEBUG_DRAW
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 155c7503acf..c25ea33109d 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4911,7 +4911,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
* Get the world-space 3d location from a screen-space 2d point.
*
* \param mval: Input screen-space pixel location.
- * \param mouse_worldloc: Output world-space loction.
+ * \param mouse_worldloc: Output world-space location.
* \param fallback_depth_pt: Use this points depth when no depth can be found.
*/
bool ED_view3d_autodist(
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 5b1a58497f0..74ed2014f55 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -4144,7 +4144,12 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3])
r_snap[2] = r_snap[1] * 0.1f;
}
}
- else if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) {
+ else if (t->spacetype == SPACE_IMAGE) {
+ r_snap[0] = 0.0f;
+ r_snap[1] = 0.0625f;
+ r_snap[2] = 0.03125f;
+ }
+ else if (t->spacetype == SPACE_CLIP) {
r_snap[0] = 0.0f;
r_snap[1] = 0.125f;
r_snap[2] = 0.0625f;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index fa5e86813fa..f98fc7bf226 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2676,6 +2676,20 @@ void flushTransSeq(TransInfo *t)
BKE_sequence_calc(t->scene, seq);
}
}
+
+ /* update effects inside meta's */
+ for (a = 0, seq_prev = NULL, td = t->data, td2d = t->data2d;
+ a < t->total;
+ a++, td++, td2d++, seq_prev = seq)
+ {
+ tdsq = (TransDataSeq *)td->extra;
+ seq = tdsq->seq;
+ if ((seq != seq_prev) && (seq->depth != 0)) {
+ if (seq->seq1 || seq->seq2 || seq->seq3) {
+ BKE_sequence_calc(t->scene, seq);
+ }
+ }
+ }
}
/* need to do the overlap check in a new loop otherwise adjacent strips
@@ -4920,44 +4934,47 @@ static void freeSeqData(TransInfo *t, TransCustomData *custom_data)
{
int overlap = 0;
- seq_prev = NULL;
- for (a = 0; a < t->total; a++, td++) {
+ for (a = 0, seq_prev = NULL; a < t->total; a++, td++, seq_prev = seq) {
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) {
overlap = 1;
break;
}
- seq_prev = seq;
}
if (overlap) {
- bool has_effect = false;
+ bool has_effect_root = false, has_effect_any = false;
for (seq = seqbasep->first; seq; seq = seq->next)
seq->tmp = NULL;
td = t->data;
- seq_prev = NULL;
- for (a = 0; a < t->total; a++, td++) {
+ for (a = 0, seq_prev = NULL; a < t->total; a++, td++, seq_prev = seq) {
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev)) {
/* check effects strips, we cant change their time */
if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
- has_effect = true;
+ has_effect_any = true;
+ if (seq->depth == 0) {
+ has_effect_root = true;
+ }
}
else {
- /* Tag seq with a non zero value, used by BKE_sequence_base_shuffle_time to identify the ones to shuffle */
- seq->tmp = (void *)1;
+ /* Tag seq with a non zero value,
+ * used by BKE_sequence_base_shuffle_time to identify the ones to shuffle */
+ if (seq->depth == 0) {
+ seq->tmp = (void *)1;
+ }
}
}
+
}
if (t->flag & T_ALT_TRANSFORM) {
int minframe = MAXFRAME;
td = t->data;
- seq_prev = NULL;
- for (a = 0; a < t->total; a++, td++) {
+ for (a = 0, seq_prev = NULL; a < t->total; a++, td++, seq_prev = seq) {
seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev)) {
+ if ((seq != seq_prev) && (seq->depth == 0)) {
minframe = min_ii(minframe, seq->startdisp);
}
}
@@ -4989,11 +5006,10 @@ static void freeSeqData(TransInfo *t, TransCustomData *custom_data)
BKE_sequence_base_shuffle_time(seqbasep, t->scene);
}
- if (has_effect) {
+ if (has_effect_any) {
/* update effects strips based on strips just moved in time */
td = t->data;
- seq_prev = NULL;
- for (a = 0; a < t->total; a++, td++) {
+ for (a = 0, seq_prev = NULL; a < t->total; a++, td++, seq_prev = seq) {
seq = ((TransDataSeq *)td->extra)->seq;
if ((seq != seq_prev)) {
if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
@@ -5001,13 +5017,14 @@ static void freeSeqData(TransInfo *t, TransCustomData *custom_data)
}
}
}
+ }
+ if (has_effect_root) {
/* now if any effects _still_ overlap, we need to move them up */
td = t->data;
- seq_prev = NULL;
- for (a = 0; a < t->total; a++, td++) {
+ for (a = 0, seq_prev = NULL; a < t->total; a++, td++, seq_prev = seq) {
seq = ((TransDataSeq *)td->extra)->seq;
- if ((seq != seq_prev)) {
+ if ((seq != seq_prev) && (seq->depth == 0)) {
if ((seq->type & SEQ_TYPE_EFFECT) && seq->seq1) {
if (BKE_sequence_test_overlap(seqbasep, seq)) {
BKE_sequence_base_shuffle(seqbasep, seq, t->scene);
@@ -5874,6 +5891,7 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
BMesh *bm = em->bm;
char hflag;
+ bool has_face_sel = (bm->totfacesel != 0);
if (t->flag & T_MIRROR) {
TransData *td;
@@ -5897,8 +5915,10 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
EDBM_automerge(t->scene, t->obedit, true, hflag);
- if ((em->selectmode & SCE_SELECT_VERTEX) == 0) {
- EDBM_select_flush(em);
+ /* Special case, this is needed or faces won't re-select.
+ * Flush selected edges to faces. */
+ if (has_face_sel && (em->selectmode == SCE_SELECT_FACE)) {
+ EDBM_selectmode_flush_ex(em, SCE_SELECT_EDGE);
}
}
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 5d49d1d9315..2fb92d73515 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -686,7 +686,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot)
{
/* identifiers */
ot->name = "Tilt";
- /* optionals -
+ /* optional -
* "Tilt selected vertices"
* "Specify an extra axis rotation for selected vertices of 3D curve" */
ot->description = "Tilt selected control vertices of 3D curve";
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 59d2485c964..90a4aa3614d 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -636,7 +636,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
- BM_face_calc_plane(efa, vec);
+ BM_face_calc_tangent_auto(efa, vec);
add_v3_v3(normal, efa->no);
add_v3_v3(plane, vec);
}
@@ -690,7 +690,7 @@ int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3
sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co);
}
else {
- BM_vert_tri_calc_plane(v_tri, plane);
+ BM_vert_tri_calc_tangent_edge(v_tri, plane);
}
}
else {
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index d7486372c36..f92f0b33faa 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -198,7 +198,7 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
mul_m3_v3((float(*)[3])data->timat, normal);
normalize_v3(normal);
- /* currently unused, and causes issues when looptri's havn't been calculated.
+ /* currently unused, and causes issues when looptri's haven't been calculated.
* since theres some overhead in ensuring this data is valid, it may need to be optional. */
#if 0
if (data->dm) {
@@ -735,7 +735,7 @@ static bool snapDerivedMesh(
if (bb) {
BoundBox bb_temp;
- /* We cannot aford a bbox with some null dimension, which may happen in some cases...
+ /* We cannot afford a bounding box with some null dimension, which may happen in some cases...
* Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index baa471e920b..94d69a0169f 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -279,8 +279,6 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
col[3] = 0.5f; /* hard coded alpha, not that nice */
- glShadeModel(GL_SMOOTH);
-
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
@@ -344,8 +342,6 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
BLI_buffer_free(&av_buf);
BLI_buffer_free(&auv_buf);
- glShadeModel(GL_FLAT);
-
break;
}
}
@@ -794,8 +790,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1);
if (interpedges) {
- glShadeModel(GL_SMOOTH);
-
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_TAG))
continue;
@@ -810,8 +805,6 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
}
glEnd();
}
-
- glShadeModel(GL_FLAT);
}
else {
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
diff --git a/source/blender/gpu/GPU_basic_shader.h b/source/blender/gpu/GPU_basic_shader.h
index 1e2db6acc52..d9bf3d1ced3 100644
--- a/source/blender/gpu/GPU_basic_shader.h
+++ b/source/blender/gpu/GPU_basic_shader.h
@@ -51,7 +51,8 @@ typedef enum GPUBasicShaderOption {
GPU_SHADER_SOLID_LIGHTING = (1 << 5), /* use faster lighting (set automatically) */
GPU_SHADER_STIPPLE = (1 << 6), /* use stipple */
GPU_SHADER_LINE = (1 << 7), /* draw lines */
- GPU_SHADER_OPTIONS_NUM = 8,
+ GPU_SHADER_FLAT_NORMAL = (1 << 8), /* use flat normals */
+ GPU_SHADER_OPTIONS_NUM = 9,
GPU_SHADER_OPTION_COMBINATIONS = (1 << GPU_SHADER_OPTIONS_NUM)
} GPUBasicShaderOption;
@@ -75,6 +76,9 @@ void GPU_basic_shaders_init(void);
void GPU_basic_shaders_exit(void);
void GPU_basic_shader_bind(int options);
+void GPU_basic_shader_bind_enable(int options);
+void GPU_basic_shader_bind_disable(int options);
+
int GPU_basic_shader_bound_options(void);
/* Only use for small blocks of code that don't support glsl shader. */
@@ -93,8 +97,9 @@ if (GPU_basic_shader_use_glsl_get()) { \
} ((void)0)
-void GPU_basic_shader_colors(const float diffuse[3], const float specular[3],
- int shininess, float alpha);
+void GPU_basic_shader_colors(
+ const float diffuse[3], const float specular[3],
+ int shininess, float alpha);
/* Fixed Function Lighting */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 75d6362f13e..bc732387c85 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -97,8 +97,9 @@ void GPU_clear_tpage(bool force);
* - this affects fixed functions materials and texface, not glsl */
int GPU_default_lights(void);
-int GPU_scene_object_lights(struct Scene *scene, struct Object *ob,
- int lay, float viewmat[4][4], int ortho);
+int GPU_scene_object_lights(
+ struct Scene *scene, struct Object *ob,
+ int lay, float viewmat[4][4], int ortho);
/* Text render
* - based on moving uv coordinates */
@@ -132,13 +133,15 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h);
void GPU_update_images_framechange(void);
int GPU_update_image_time(struct Image *ima, double time);
-int GPU_verify_image(struct Image *ima,
- struct ImageUser *iuser, int textarget, int tftile, bool compare, bool mipmap, bool is_data);
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
- int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima);
+int GPU_verify_image(
+ struct Image *ima, struct ImageUser *iuser,
+ int textarget, int tftile, bool compare, bool mipmap, bool is_data);
+void GPU_create_gl_tex(
+ unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
+ int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima);
void GPU_create_gl_tex_compressed(
- unsigned int *bind, unsigned int *pix, int x, int y, int mipmap,
- int textarget, struct Image *ima, struct ImBuf *ibuf);
+ unsigned int *bind, unsigned int *pix, int x, int y, int mipmap,
+ int textarget, struct Image *ima, struct ImBuf *ibuf);
bool GPU_upload_dxt_texture(struct ImBuf *ibuf);
void GPU_free_image(struct Image *ima);
void GPU_free_images(void);
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index b0669225a4d..a2b89239344 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -376,6 +376,8 @@ static GPUShader *gpu_basic_shader(int options)
strcat(defines, "#define DRAW_LINE\n");
geom_glsl = datatoc_gpu_shader_basic_geom_glsl;
}
+ if (options & GPU_SHADER_FLAT_NORMAL)
+ strcat(defines, "#define USE_FLAT_NORMAL\n");
if (options & GPU_SHADER_SOLID_LIGHTING)
strcat(defines, "#define USE_SOLID_LIGHTING\n");
else if (options & GPU_SHADER_LIGHTING)
@@ -500,18 +502,35 @@ void GPU_basic_shader_bind(int options)
else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) {
glDisable(GL_LINE_STIPPLE);
}
- else {
- if (options & GPU_SHADER_STIPPLE)
- glEnable(GL_POLYGON_STIPPLE);
- else if (bound_options & GPU_SHADER_STIPPLE)
- glDisable(GL_POLYGON_STIPPLE);
+
+ if (((options & GPU_SHADER_LINE) == 0) && (options & GPU_SHADER_STIPPLE)) {
+ glEnable(GL_POLYGON_STIPPLE);
+ }
+ else if (((bound_options & GPU_SHADER_LINE) == 0) && (bound_options & GPU_SHADER_STIPPLE)) {
+ glDisable(GL_POLYGON_STIPPLE);
}
+ if (options & GPU_SHADER_FLAT_NORMAL) {
+ glShadeModel(GL_FLAT);
+ }
+ else if (bound_options & GPU_SHADER_FLAT_NORMAL) {
+ glShadeModel(GL_SMOOTH);
+ }
}
GPU_MATERIAL_STATE.bound_options = options;
}
+void GPU_basic_shader_bind_enable(int options)
+{
+ GPU_basic_shader_bind(GPU_MATERIAL_STATE.bound_options | options);
+}
+
+void GPU_basic_shader_bind_disable(int options)
+{
+ GPU_basic_shader_bind(GPU_MATERIAL_STATE.bound_options & ~options);
+}
+
int GPU_basic_shader_bound_options(void)
{
/* ideally this should disappear, anything that uses this is making fragile
@@ -521,8 +540,9 @@ int GPU_basic_shader_bound_options(void)
/* Material Colors */
-void GPU_basic_shader_colors(const float diffuse[3], const float specular[3],
- int shininess, float alpha)
+void GPU_basic_shader_colors(
+ const float diffuse[3], const float specular[3],
+ int shininess, float alpha)
{
float gl_diffuse[4], gl_specular[4];
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 2c6f204d9d0..36d297fb9fe 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -53,8 +53,6 @@
#include "BKE_mesh.h"
#include "BKE_pbvh.h"
-#include "DNA_userdef_types.h"
-
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_basic_shader.h"
@@ -1845,15 +1843,15 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
if (buffers->vert_buf) {
char *base = NULL;
char *index_base = NULL;
- int bound_options = 0;
+ /* weak inspection of bound options, should not be necessary ideally */
+ const int bound_options_old = GPU_basic_shader_bound_options();
+ int bound_options_new = 0;
glEnableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
- /* weak inspection of bound options, should not be necessary ideally */
- bound_options = GPU_basic_shader_bound_options();
- GPU_basic_shader_bind(bound_options | GPU_SHADER_USE_COLOR);
+ bound_options_new |= GPU_SHADER_USE_COLOR;
}
GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
@@ -1865,10 +1863,18 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX);
}
- if (wireframe)
+ if (wireframe) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- else
- glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT);
+ }
+ else {
+ if ((buffers->smooth == false) && (buffers->face_indices_len == 0)) {
+ bound_options_new |= GPU_SHADER_FLAT_NORMAL;
+ }
+ }
+
+ if (bound_options_new & ~bound_options_old) {
+ GPU_basic_shader_bind(bound_options_old | bound_options_new);
+ }
if (buffers->tot_quad) {
const char *offset = base;
@@ -1942,7 +1948,10 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
if (!wireframe) {
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
- GPU_basic_shader_bind(bound_options);
+ }
+
+ if (bound_options_new & ~bound_options_old) {
+ GPU_basic_shader_bind(bound_options_old);
}
}
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 58ef4063430..3c028ff0805 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -86,8 +86,10 @@ typedef struct GPUFunction {
} GPUFunction;
/* Indices match the GPUType enum */
-static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
- NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
+static const char *GPU_DATATYPE_STR[17] = {
+ "", "float", "vec2", "vec3", "vec4",
+ NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4",
+};
/* GLSL code parsing for finding function definitions.
* These are stored in a hash for lookup when creating a material. */
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index c2a2b1804ca..964c2b5051e 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -34,16 +34,11 @@
#include "BLI_sys_types.h"
#include "BLI_rect.h"
#include "BLI_math.h"
-#include "BLI_listbase.h"
-#include "BLI_linklist.h"
#include "BLI_rand.h"
#include "DNA_vec_types.h"
-#include "DNA_view3d_types.h"
#include "DNA_scene_types.h"
-#include "DNA_object_types.h"
-#include "DNA_camera_types.h"
#include "DNA_gpu_types.h"
#include "GPU_compositing.h"
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index e5d51772bb2..f998dc9904e 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -39,7 +39,6 @@
#include <string.h>
#include "GPU_glew.h"
-#include "GPU_debug.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
@@ -70,10 +69,11 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
-#include "BKE_object.h"
#include "BKE_scene.h"
-#include "BKE_subsurf.h"
#include "BKE_DerivedMesh.h"
+#ifdef WITH_GAMEENGINE
+# include "BKE_object.h"
+#endif
#include "GPU_basic_shader.h"
#include "GPU_buffers.h"
@@ -85,9 +85,13 @@
#include "PIL_time.h"
-#include "smoke_API.h"
+#ifdef WITH_SMOKE
+# include "smoke_API.h"
+#endif
#ifdef WITH_OPENSUBDIV
+# include "BKE_subsurf.h"
+# include "BKE_DerivedMesh.h"
# include "BKE_editmesh.h"
# include "gpu_codegen.h"
@@ -561,7 +565,9 @@ static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect,
}
}
-int GPU_verify_image(Image *ima, ImageUser *iuser, int textarget, int tftile, bool compare, bool mipmap, bool is_data)
+int GPU_verify_image(
+ Image *ima, ImageUser *iuser,
+ int textarget, int tftile, bool compare, bool mipmap, bool is_data)
{
unsigned int *bind = NULL;
int tpx = 0, tpy = 0;
@@ -843,8 +849,9 @@ static void gpu_del_cube_map(void **cube_map)
}
/* Image *ima can be NULL */
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
- int textarget, bool mipmap, bool use_high_bit_depth, Image *ima)
+void GPU_create_gl_tex(
+ unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
+ int textarget, bool mipmap, bool use_high_bit_depth, Image *ima)
{
ImBuf *ibuf = NULL;
@@ -1988,8 +1995,9 @@ int GPU_object_material_bind(int nr, void *attribs)
}
else {
/* or do fixed function opengl material */
- GPU_basic_shader_colors(GMS.matbuf[nr].diff,
- GMS.matbuf[nr].spec, GMS.matbuf[nr].hard, GMS.matbuf[nr].alpha);
+ GPU_basic_shader_colors(
+ GMS.matbuf[nr].diff,
+ GMS.matbuf[nr].spec, GMS.matbuf[nr].hard, GMS.matbuf[nr].alpha);
if (GMS.two_sided_lighting)
GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_TWO_SIDED);
@@ -2283,8 +2291,6 @@ void GPU_state_init(void)
/* scaling matrices */
glEnable(GL_NORMALIZE);
- glShadeModel(GL_FLAT);
-
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 3c96b628cd6..b8a39c81122 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -32,9 +32,6 @@
* with checks for drivers and GPU support.
*/
-#include "MEM_guardedalloc.h"
-
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
@@ -42,7 +39,6 @@
#include "BKE_global.h"
#include "GPU_basic_shader.h"
-#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
#include "GPU_texture.h"
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index a6d120b8943..c0400cdb04c 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -29,8 +29,6 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-#include "BLI_math_base.h"
-#include "BLI_math_vector.h"
#include "BKE_global.h"
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 8fed6a9ee80..c72c83b6b07 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -29,11 +29,8 @@
* \ingroup gpu
*/
-#include "BKE_DerivedMesh.h"
-
#include "BLI_sys_types.h"
#include "GPU_init_exit.h" /* interface */
-#include "GPU_buffers.h"
#include "BKE_global.h"
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 02f58ea6df2..f14b2e6e170 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -31,7 +31,6 @@
* Manages materials, lights and textures.
*/
-
#include <math.h>
#include <string.h>
@@ -49,7 +48,6 @@
#include "BKE_anim.h"
#include "BKE_colortools.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -68,7 +66,9 @@
#include "gpu_codegen.h"
-#include <string.h>
+#ifdef WITH_OPENSUBDIV
+# include "BKE_DerivedMesh.h"
+#endif
/* Structs */
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 25352001056..5a1b38e6be7 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -27,7 +27,6 @@
#include "MEM_guardedalloc.h"
-#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
#include "BLI_math_vector.h"
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 294b08f155a..827c52c9a5f 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -32,7 +32,6 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
-#include "BLI_math_vector.h"
#include "BKE_global.h"
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index ea5f6aef005..01a335af048 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
@@ -28,8 +28,11 @@
#define STIPPLE_S3D_INTERLACE_CHECKERBOARD_SWAP 11
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+#if defined(USE_FLAT_NORMAL)
+varying vec3 eyespace_vert_pos;
+#else
varying vec3 varying_normal;
-
+#endif
#ifndef USE_SOLID_LIGHTING
varying vec3 varying_position;
#endif
@@ -146,7 +149,11 @@ void main()
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
/* compute normal */
+#if defined(USE_FLAT_NORMAL)
+ vec3 N = normalize(cross(dFdx(eyespace_vert_pos), dFdy(eyespace_vert_pos)));
+#else
vec3 N = normalize(varying_normal);
+#endif
#ifdef USE_TWO_SIDED
if (!gl_FrontFacing)
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
index cef28ea3026..42fbdadf1d1 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
@@ -1,6 +1,10 @@
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+#if defined(USE_FLAT_NORMAL)
+varying vec3 eyespace_vert_pos;
+#else
varying vec3 varying_normal;
+#endif
#ifndef USE_SOLID_LIGHTING
varying vec3 varying_position;
@@ -28,7 +32,13 @@ void main()
vec4 co = gl_ModelViewMatrix * gl_Vertex;
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
+#if !defined(USE_FLAT_NORMAL)
varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+#endif
+#if defined(USE_FLAT_NORMAL)
+ /* transform vertex into eyespace */
+ eyespace_vert_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+#endif
#ifndef USE_SOLID_LIGHTING
varying_position = co.xyz;
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index 5ec0a87890c..6fb1bccf491 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -296,10 +296,11 @@ static int logImageSetData10(LogImageFile *logImage, LogImageElement logElement,
row[index] = swap_uint(pixel, logImage->isMSB);
if (logimage_fwrite(row, rowLength, 1, logImage) == 0) {
- if (verbose) printf("DPX/Cineon: Error while writing file.\n"); {
- MEM_freeN(row);
- return 1;
+ if (verbose) {
+ printf("DPX/Cineon: Error while writing file.\n");
}
+ MEM_freeN(row);
+ return 1;
}
}
MEM_freeN(row);
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 06823a26c77..1f34d8f23d4 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -898,7 +898,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_bbone_relative_start_handle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_START_REL);
RNA_def_property_ui_text(prop, "Relative B-Bone Start Handle",
- "Use treat custom start handle position as a relative value");
+ "Treat custom start handle position as a relative value");
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
@@ -914,7 +914,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_bbone_relative_end_handle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bboneflag", PCHAN_BBONE_CUSTOM_END_REL);
RNA_def_property_ui_text(prop, "Relative B-Bone End Handle",
- "Use treat custom end handle position as a relative value");
+ "Treat custom end handle position as a relative value");
RNA_def_property_editable_func(prop, "rna_PoseChannel_proxy_editable");
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 29b1e5bc5c7..afccef46174 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -199,6 +199,12 @@ void register_node_tree_type_sh(void)
/* GPU material from shader nodes */
+static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
+ bNode *node_from,
+ bNodeSocket *socket_from,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket);
+
/* Find an output node of the shader tree.
*
* NOTE: it will only return output which is NOT in the group, which isn't how
@@ -277,32 +283,138 @@ static bool ntree_shader_has_displacement(bNodeTree *ntree,
return displacement->link != NULL;
}
+static bool ntree_shader_relink_node_normal(bNodeTree *ntree,
+ bNode *node,
+ bNode *node_from,
+ bNodeSocket *socket_from)
+{
+ bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
+ /* TODO(sergey): Can we do something smarter here than just a name-based
+ * matching?
+ */
+ if (sock == NULL) {
+ /* There's no Normal input, nothing to link. */
+ return false;
+ }
+ if (sock->link != NULL) {
+ /* Something is linked to the normal input already. can't
+ * use other input for that.
+ */
+ return false;
+ }
+ /* Create connection between specified node and the normal input. */
+ nodeAddLink(ntree, node_from, socket_from, node, sock);
+ return true;
+}
+
+static void ntree_shader_link_builtin_group_normal(
+ bNodeTree *ntree,
+ bNode *group_node,
+ bNode *node_from,
+ bNodeSocket *socket_from,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket)
+{
+ bNodeTree *group_ntree = (bNodeTree *)group_node->id;
+ /* Create input socket to plug displacement connection to. */
+ bNodeSocket *group_normal_socket =
+ ntreeAddSocketInterface(group_ntree,
+ SOCK_IN,
+ "NodeSocketVector",
+ "Normal");
+ /* Need to update tree so all node instances nodes gets proper sockets. */
+ ntreeUpdateTree(G.main, group_ntree);
+ /* Assumes sockets are always added at the end. */
+ bNodeSocket *group_node_normal_socket = (bNodeSocket*)group_node->inputs.last;
+ if (displacement_node == group_node) {
+ /* If displacement is coming from this node group we need to perform
+ * some internal re-linking in order to avoid cycles.
+ */
+ bNode *group_output_node = ntreeFindType(group_ntree, NODE_GROUP_OUTPUT);
+ BLI_assert(group_output_node != NULL);
+ bNodeSocket *group_output_node_displacement_socket =
+ nodeFindSocket(group_output_node,
+ SOCK_IN,
+ displacement_socket->identifier);
+ bNodeLink *group_displacement_link = group_output_node_displacement_socket->link;
+ if (group_displacement_link == NULL) {
+ /* Displacement output is not connected to anything, can just stop
+ * right away.
+ */
+ return;
+ }
+ /* This code is similar to ntree_shader_relink_displacement() */
+ bNode *group_displacement_node = group_displacement_link->fromnode;
+ bNodeSocket *group_displacement_socket = group_displacement_link->fromsock;
+ nodeRemLink(group_ntree, group_displacement_link);
+ /* Create and link bump node.
+ * Can't re-use bump node from parent tree because it'll cause cycle.
+ */
+ bNode *bump_node = nodeAddStaticNode(NULL, group_ntree, SH_NODE_BUMP);
+ bNodeSocket *bump_input_socket = ntree_shader_node_find_input(bump_node, "Height");
+ bNodeSocket *bump_output_socket = ntree_shader_node_find_output(bump_node, "Normal");
+ BLI_assert(bump_input_socket != NULL);
+ BLI_assert(bump_output_socket != NULL);
+ nodeAddLink(group_ntree,
+ group_displacement_node, group_displacement_socket,
+ bump_node, bump_input_socket);
+ /* Relink normals inside of the instanced tree. */
+ ntree_shader_link_builtin_normal(group_ntree,
+ bump_node,
+ bump_output_socket,
+ group_displacement_node,
+ group_displacement_socket);
+ ntreeUpdateTree(G.main, group_ntree);
+ }
+ else {
+ /* Connect group node normal input. */
+ nodeAddLink(ntree,
+ node_from, socket_from,
+ group_node, group_node_normal_socket);
+ bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
+ BLI_assert(group_input_node != NULL);
+ bNodeSocket *group_input_node_normal_socket =
+ nodeFindSocket(group_input_node,
+ SOCK_OUT,
+ group_normal_socket->identifier);
+ BLI_assert(group_input_node_normal_socket != NULL);
+ /* Relink normals inside of the instanced tree. */
+ ntree_shader_link_builtin_normal(group_ntree,
+ group_input_node,
+ group_input_node_normal_socket,
+ displacement_node,
+ displacement_socket);
+ ntreeUpdateTree(G.main, group_ntree);
+ }
+}
+
/* Use specified node and socket as an input for unconnected normal sockets. */
static void ntree_shader_link_builtin_normal(bNodeTree *ntree,
bNode *node_from,
- bNodeSocket *socket_from)
+ bNodeSocket *socket_from,
+ bNode *displacement_node,
+ bNodeSocket *displacement_socket)
{
for (bNode *node = ntree->nodes.first; node != NULL; node = node->next) {
if (node == node_from) {
/* Don't connect node itself! */
continue;
}
- bNodeSocket *sock = ntree_shader_node_find_input(node, "Normal");
- /* TODO(sergey): Can we do something smarter here than just a name-based
- * matching?
- */
- if (sock == NULL) {
- /* There's no Normal input, nothing to link. */
+ if (node->type == NODE_GROUP && node->id) {
+ /* Special re-linking for group nodes. */
+ ntree_shader_link_builtin_group_normal(ntree,
+ node,
+ node_from,
+ socket_from,
+ displacement_node,
+ displacement_socket);
continue;
}
- if (sock->link != NULL) {
- /* Something is linked to the normal input already. can't
- * use other input for that.
- */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ /* Group inputs and outputs needs nothing special. */
continue;
}
- /* Create connection between specified node and the normal input. */
- nodeAddLink(ntree, node_from, socket_from, node, sock);
+ ntree_shader_relink_node_normal(ntree, node, node_from, socket_from);
}
}
@@ -346,7 +458,11 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree,
displacement_node, displacement_socket,
bump_node, bump_input_socket);
/* Connect all free-standing Normal inputs. */
- ntree_shader_link_builtin_normal(ntree, bump_node, bump_output_socket);
+ ntree_shader_link_builtin_normal(ntree,
+ bump_node,
+ bump_output_socket,
+ displacement_node,
+ displacement_socket);
/* TODO(sergey): Reconnect Geometry Info->Normal sockets to the new
* bump node.
*/
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index 832d516b839..2ad8ee0547f 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -1586,8 +1586,11 @@ bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, floa
// calculate elonglation
spring_length(data, i, j, extent, dir, &length, vel);
-
- if (length > restlen || no_compress) {
+
+ /* This code computes not only the force, but also its derivative.
+ Zero derivative effectively disables the spring for the implicit solver.
+ Thus length > restlen makes cloth unconstrained at the start of simulation. */
+ if ((length >= restlen && length > 0) || no_compress) {
float stretch_force, f[3], dfdx[3][3], dfdv[3][3];
stretch_force = stiffness * (length - restlen);
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index a0722af522b..fe4360d1e3b 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -1803,6 +1803,82 @@ static PyObject *bpy_bmface_calc_perimeter(BPy_BMFace *self)
}
+PyDoc_STRVAR(bpy_bmface_calc_tangent_edge_doc,
+".. method:: calc_tangent_edge()\n"
+"\n"
+" Return face tangent based on longest edge.\n"
+"\n"
+" :return: a normalized vector.\n"
+" :rtype: :class:`mathutils.Vector`\n"
+);
+static PyObject *bpy_bmface_calc_tangent_edge(BPy_BMFace *self)
+{
+ float tangent[3];
+
+ BPY_BM_CHECK_OBJ(self);
+ BM_face_calc_tangent_edge(self->f, tangent);
+ return Vector_CreatePyObject(tangent, 3, NULL);
+}
+
+
+PyDoc_STRVAR(bpy_bmface_calc_tangent_edge_pair_doc,
+".. method:: calc_tangent_edge_pair()\n"
+"\n"
+" Return face tangent based on the two longest disconected edges.\n"
+"\n"
+" - Tris: Use the edge pair with the most similar lengths.\n"
+" - Quads: Use the longest edge pair.\n"
+" - NGons: Use the two longest disconnected edges.\n"
+"\n"
+" :return: a normalized vector.\n"
+" :rtype: :class:`mathutils.Vector`\n"
+);
+static PyObject *bpy_bmface_calc_tangent_edge_pair(BPy_BMFace *self)
+{
+ float tangent[3];
+
+ BPY_BM_CHECK_OBJ(self);
+ BM_face_calc_tangent_edge_pair(self->f, tangent);
+ return Vector_CreatePyObject(tangent, 3, NULL);
+}
+
+
+PyDoc_STRVAR(bpy_bmface_calc_tangent_edge_diagonal_doc,
+".. method:: calc_tangent_edge_diagonal()\n"
+"\n"
+" Return face tangent based on the edge farthest from any vertex.\n"
+"\n"
+" :return: a normalized vector.\n"
+" :rtype: :class:`mathutils.Vector`\n"
+);
+static PyObject *bpy_bmface_calc_tangent_edge_diagonal(BPy_BMFace *self)
+{
+ float tangent[3];
+
+ BPY_BM_CHECK_OBJ(self);
+ BM_face_calc_tangent_edge_diagonal(self->f, tangent);
+ return Vector_CreatePyObject(tangent, 3, NULL);
+}
+
+
+PyDoc_STRVAR(bpy_bmface_calc_tangent_vert_diagonal_doc,
+".. method:: calc_tangent_vert_diagonal()\n"
+"\n"
+" Return face tangent based on the two most distent vertices.\n"
+"\n"
+" :return: a normalized vector.\n"
+" :rtype: :class:`mathutils.Vector`\n"
+);
+static PyObject *bpy_bmface_calc_tangent_vert_diagonal(BPy_BMFace *self)
+{
+ float tangent[3];
+
+ BPY_BM_CHECK_OBJ(self);
+ BM_face_calc_tangent_vert_diagonal(self->f, tangent);
+ return Vector_CreatePyObject(tangent, 3, NULL);
+}
+
+
PyDoc_STRVAR(bpy_bmface_calc_center_mean_doc,
".. method:: calc_center_median()\n"
"\n"
@@ -2702,6 +2778,10 @@ static struct PyMethodDef bpy_bmface_methods[] = {
{"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc},
{"calc_perimeter", (PyCFunction)bpy_bmface_calc_perimeter, METH_NOARGS, bpy_bmface_calc_perimeter_doc},
+ {"calc_tangent_edge", (PyCFunction)bpy_bmface_calc_tangent_edge, METH_NOARGS, bpy_bmface_calc_tangent_edge_doc},
+ {"calc_tangent_edge_pair", (PyCFunction)bpy_bmface_calc_tangent_edge_pair, METH_NOARGS, bpy_bmface_calc_tangent_edge_pair_doc},
+ {"calc_tangent_edge_diagonal", (PyCFunction)bpy_bmface_calc_tangent_edge_diagonal, METH_NOARGS, bpy_bmface_calc_tangent_edge_diagonal_doc},
+ {"calc_tangent_vert_diagonal", (PyCFunction)bpy_bmface_calc_tangent_vert_diagonal, METH_NOARGS, bpy_bmface_calc_tangent_vert_diagonal_doc},
{"calc_center_median", (PyCFunction)bpy_bmface_calc_center_mean, METH_NOARGS, bpy_bmface_calc_center_mean_doc},
{"calc_center_median_weighted", (PyCFunction)bpy_bmface_calc_center_mean_weighted, METH_NOARGS, bpy_bmface_calc_center_mean_weighted_doc},
{"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index db933ad2d76..1357729e898 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -233,19 +233,15 @@ static void wm_gesture_draw_circle(wmGesture *gt)
}
struct LassoFillData {
- unsigned int *px;
+ unsigned char *px;
int width;
};
static void draw_filled_lasso_px_cb(int x, int x_end, int y, void *user_data)
{
struct LassoFillData *data = user_data;
- unsigned char *col = (unsigned char *)&(data->px[(y * data->width) + x]);
- do {
- col[0] = col[1] = col[2] = 0xff;
- col[3] = 0x10;
- col += 4;
- } while (++x != x_end);
+ unsigned char *col = &(data->px[(y * data->width) + x]);
+ memset(col, 0x10, x_end - x);
}
static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
@@ -273,7 +269,7 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
if (BLI_rcti_is_empty(&rect) == false) {
const int w = BLI_rcti_size_x(&rect);
const int h = BLI_rcti_size_y(&rect);
- unsigned int *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__);
+ unsigned char *pixel_buf = MEM_callocN(sizeof(*pixel_buf) * w * h, __func__);
struct LassoFillData lasso_fill_data = {pixel_buf, w};
fill_poly_v2i_n(
@@ -281,19 +277,27 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
(const int (*)[2])moves, tot,
draw_filled_lasso_px_cb, &lasso_fill_data);
- int bound_options;
- GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glColor4f(1, 1, 1, 1);
+ glPixelTransferf(GL_RED_BIAS, 1);
+ glPixelTransferf(GL_GREEN_BIAS, 1);
+ glPixelTransferf(GL_BLUE_BIAS, 1);
+
+ GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glEnable(GL_BLEND);
- // glColor4f(1.0, 1.0, 1.0, 0.05);
+ glaDrawPixelsTex(rect.xmin, rect.ymin, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, GL_NEAREST, pixel_buf);
+ glDisable(GL_BLEND);
- glRasterPos2f(rect.xmin, rect.ymin);
+ GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_buf);
+ glPixelTransferf(GL_RED_BIAS, 0);
+ glPixelTransferf(GL_GREEN_BIAS, 0);
+ glPixelTransferf(GL_BLUE_BIAS, 0);
- GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- glDisable(GL_BLEND);
MEM_freeN(pixel_buf);
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index b4295bb2607..866e332b34f 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1391,7 +1391,7 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
}
}
-static void dialog_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
+static void popup_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
{
wmOperator *op = op_ptr;
if (op->type->check) {
@@ -1423,7 +1423,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- UI_block_func_set(block, dialog_check_cb, op, NULL);
+ UI_block_func_set(block, popup_check_cb, op, NULL);
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
@@ -1463,9 +1463,13 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
+ UI_block_func_set(block, popup_check_cb, op, NULL);
+
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
+ UI_block_func_set(block, NULL, NULL, NULL);
+
UI_block_bounds_set_popup(block, 4, 0, 0);
return block;