diff options
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 347 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/render/attribute.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 32 | ||||
-rw-r--r-- | intern/cycles/render/mesh.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 4 | ||||
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 21 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_regions.c | 5 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_utils.c | 4 |
11 files changed, 237 insertions, 194 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 31f3e1e4859..9e9ab030146 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -80,204 +80,195 @@ inline void face_split_tri_indices(const int face_flag, struct MikkUserData { MikkUserData(const BL::Mesh& b_mesh, BL::MeshTextureFaceLayer *layer, - int num_faces) - : b_mesh(b_mesh), - layer(layer), - num_faces(num_faces) + const Mesh *mesh, + float3 *tangent, + float *tangent_sign) + : mesh(mesh), + texface(NULL), + orco(NULL), + tangent(tangent), + tangent_sign(tangent_sign) { - tangent.resize(num_faces*4); + Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); + vertex_normal = attr_vN->data_float3(); + + if(layer == NULL) { + Attribute *attr_orco = mesh->attributes.find(ATTR_STD_GENERATED); + orco = attr_orco->data_float3(); + mesh_texture_space(*(BL::Mesh*)&b_mesh, orco_loc, orco_size); + } + else { + Attribute *attr_uv = mesh->attributes.find(ustring(layer->name())); + if(attr_uv != NULL) { + texface = attr_uv->data_float3(); + } + } } - BL::Mesh b_mesh; - BL::MeshTextureFaceLayer *layer; + const Mesh *mesh; int num_faces; - vector<float4> tangent; + + float3 *vertex_normal; + float3 *texface; + float3 *orco; + float3 orco_loc, orco_size; + + float3 *tangent; + float *tangent_sign; }; static int mikk_get_num_faces(const SMikkTSpaceContext *context) { - MikkUserData *userdata = (MikkUserData*)context->m_pUserData; - return userdata->num_faces; + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + return userdata->mesh->num_triangles(); } -static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) +static int mikk_get_num_verts_of_face(const SMikkTSpaceContext * /*context*/, + const int /*face_num*/) { - MikkUserData *userdata = (MikkUserData*)context->m_pUserData; - BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num]; - int4 vi = get_int4(f.vertices_raw()); - - return (vi[3] == 0)? 3: 4; + return 3; } -static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num) +static void mikk_get_position(const SMikkTSpaceContext *context, + float P[3], + const int face_num, const int vert_num) { - MikkUserData *userdata = (MikkUserData*)context->m_pUserData; - BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num]; - int4 vi = get_int4(f.vertices_raw()); - BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]]; - float3 vP = get_float3(v.co()); + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + const Mesh *mesh = userdata->mesh; + const int vert_index = mesh->triangles[face_num * 3 + vert_num]; + const float3 vP = mesh->verts[vert_index]; P[0] = vP.x; P[1] = vP.y; P[2] = vP.z; } -static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num) +static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, + float uv[2], + const int face_num, const int vert_num) { - MikkUserData *userdata = (MikkUserData*)context->m_pUserData; - if(userdata->layer != NULL) { - BL::MeshTextureFace tf = userdata->layer->data[face_num]; - float3 tfuv; - - switch(vert_num) { - case 0: - tfuv = get_float3(tf.uv1()); - break; - case 1: - tfuv = get_float3(tf.uv2()); - break; - case 2: - tfuv = get_float3(tf.uv3()); - break; - default: - tfuv = get_float3(tf.uv4()); - break; - } - + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + if(userdata->texface != NULL) { + const size_t corner_index = face_num * 3 + vert_num; + float3 tfuv = userdata->texface[corner_index]; uv[0] = tfuv.x; uv[1] = tfuv.y; } - else { - int vert_idx = userdata->b_mesh.tessfaces[face_num].vertices()[vert_num]; - float3 orco = - get_float3(userdata->b_mesh.vertices[vert_idx].undeformed_co()); - float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2])); + else if(userdata->orco != NULL) { + const Mesh *mesh = userdata->mesh; + const size_t vertex_index = mesh->triangles[face_num * 3 + vert_num]; + const float3 orco_loc = userdata->orco_loc; + const float3 orco_size = userdata->orco_size; + const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size; + + const float2 tmp = map_to_sphere(orco); uv[0] = tmp.x; uv[1] = tmp.y; } + else { + uv[0] = 0.0f; + uv[1] = 0.0f; + } } -static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num) +static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], + const int face_num, const int vert_num) { - MikkUserData *userdata = (MikkUserData*)context->m_pUserData; - BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num]; + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + const Mesh *mesh = userdata->mesh; float3 vN; - - if(f.use_smooth()) { - int4 vi = get_int4(f.vertices_raw()); - BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]]; - vN = get_float3(v.normal()); + if(mesh->smooth[face_num]) { + const size_t vert_index = mesh->triangles[face_num * 3 + vert_num]; + vN = userdata->vertex_normal[vert_index]; } else { - vN = get_float3(f.normal()); + const Mesh::Triangle tri = mesh->get_triangle(face_num); + vN = tri.compute_normal(&mesh->verts[0]); } - N[0] = vN.x; N[1] = vN.y; N[2] = vN.z; } -static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert) +static void mikk_set_tangent_space(const SMikkTSpaceContext *context, + const float T[], + const float sign, + const int face_num, const int vert_num) { - MikkUserData *userdata = (MikkUserData*)context->m_pUserData; - - userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign); + MikkUserData *userdata = (MikkUserData *)context->m_pUserData; + const size_t corner_index = face_num * 3 + vert_num; + userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]); + if(userdata->tangent_sign != NULL) { + userdata->tangent_sign[corner_index] = sign; + } } -static void mikk_compute_tangents(BL::Mesh& b_mesh, +static void mikk_compute_tangents(const BL::Mesh& b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, - const vector<int>& nverts, - const vector<int>& face_flags, bool need_sign, bool active_render) { - /* setup userdata */ - MikkUserData userdata(b_mesh, b_layer, nverts.size()); - - /* setup interface */ - SMikkTSpaceInterface sm_interface; - memset(&sm_interface, 0, sizeof(sm_interface)); - sm_interface.m_getNumFaces = mikk_get_num_faces; - sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; - sm_interface.m_getPosition = mikk_get_position; - sm_interface.m_getTexCoord = mikk_get_texture_coordinate; - sm_interface.m_getNormal = mikk_get_normal; - sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; - - /* setup context */ - SMikkTSpaceContext context; - memset(&context, 0, sizeof(context)); - context.m_pUserData = &userdata; - context.m_pInterface = &sm_interface; - - /* compute tangents */ - genTangSpaceDefault(&context); - - /* create tangent attributes */ + /* Create tangent attributes. */ Attribute *attr; ustring name; - if(b_layer != NULL) + if(b_layer != NULL) { name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str()); - else + } + else { name = ustring("orco.tangent"); - - if(active_render) + } + if(active_render) { attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); - else - attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER); - + } + else { + attr = mesh->attributes.add(name, + TypeDesc::TypeVector, + ATTR_ELEMENT_CORNER); + } float3 *tangent = attr->data_float3(); - - /* create bitangent sign attribute */ + /* Create bitangent sign attribute. */ float *tangent_sign = NULL; - if(need_sign) { Attribute *attr_sign; ustring name_sign; - if(b_layer != NULL) - name_sign = ustring((string(b_layer->name().c_str()) + ".tangent_sign").c_str()); - else + if(b_layer != NULL) { + name_sign = ustring((string(b_layer->name().c_str()) + + ".tangent_sign").c_str()); + } + else { name_sign = ustring("orco.tangent_sign"); - - if(active_render) - attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); - else - attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER); - - tangent_sign = attr_sign->data_float(); - } - - for(int i = 0; i < nverts.size(); i++) { - int tri_a[3], tri_b[3]; - face_split_tri_indices(face_flags[i], tri_a, tri_b); - - tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]); - tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]); - tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_a[2]]); - tangent += 3; - - if(tangent_sign) { - tangent_sign[0] = userdata.tangent[i*4 + tri_a[0]].w; - tangent_sign[1] = userdata.tangent[i*4 + tri_a[1]].w; - tangent_sign[2] = userdata.tangent[i*4 + tri_a[2]].w; - tangent_sign += 3; } - if(nverts[i] == 4) { - tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_b[0]]); - tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_b[1]]); - tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_b[2]]); - tangent += 3; - - if(tangent_sign) { - tangent_sign[0] = userdata.tangent[i*4 + tri_b[0]].w; - tangent_sign[1] = userdata.tangent[i*4 + tri_b[1]].w; - tangent_sign[2] = userdata.tangent[i*4 + tri_b[2]].w; - tangent_sign += 3; - } + if(active_render) { + attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, + name_sign); + } + else { + attr_sign = mesh->attributes.add(name_sign, + TypeDesc::TypeFloat, + ATTR_ELEMENT_CORNER); } + tangent_sign = attr_sign->data_float(); } + /* Setup userdata. */ + MikkUserData userdata(b_mesh, b_layer, mesh, tangent, tangent_sign); + /* Setup interface. */ + SMikkTSpaceInterface sm_interface; + memset(&sm_interface, 0, sizeof(sm_interface)); + sm_interface.m_getNumFaces = mikk_get_num_faces; + sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; + sm_interface.m_getPosition = mikk_get_position; + sm_interface.m_getTexCoord = mikk_get_texture_coordinate; + sm_interface.m_getNormal = mikk_get_normal; + sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; + /* Setup context. */ + SMikkTSpaceContext context; + memset(&context, 0, sizeof(context)); + context.m_pUserData = &userdata; + context.m_pInterface = &sm_interface; + /* Compute tangents. */ + genTangSpaceDefault(&context); } /* Create Volume Attribute */ @@ -450,21 +441,39 @@ static void attr_create_uv_map(Scene *scene, BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { - bool active_render = l->active_render(); - AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; - ustring name = ustring(l->name().c_str()); + const bool active_render = l->active_render(); + AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; + ustring uv_name = ustring(l->name().c_str()); + AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT + : ATTR_STD_NONE; + ustring tangent_name = ustring( + (string(l->name().c_str()) + ".tangent").c_str()); + + /* Denotes whether UV map was requested directly. */ + const bool need_uv = mesh->need_attribute(scene, uv_name) || + mesh->need_attribute(scene, uv_std); + /* Denotes whether tangent was requested directly. */ + const bool need_tangent = + mesh->need_attribute(scene, tangent_name) || + (active_render && mesh->need_attribute(scene, tangent_std)); /* UV map */ - if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { - Attribute *attr; - - if(active_render) - attr = mesh->attributes.add(std, name); - else - attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); + /* NOTE: We create temporary UV layer if its needed for tangent but + * wasn't requested by other nodes in shaders. + */ + Attribute *uv_attr = NULL; + if(need_uv || need_tangent) { + if(active_render) { + uv_attr = mesh->attributes.add(uv_std, uv_name); + } + else { + uv_attr = mesh->attributes.add(uv_name, + TypeDesc::TypePoint, + ATTR_ELEMENT_CORNER); + } BL::MeshTextureFaceLayer::data_iterator t; - float3 *fdata = attr->data_float3(); + float3 *fdata = uv_attr->data_float3(); size_t i = 0; for(l->data.begin(t); t != l->data.end(); ++t, ++i) { @@ -494,33 +503,32 @@ static void attr_create_uv_map(Scene *scene, } /* UV tangent */ - std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE; - name = ustring((string(l->name().c_str()) + ".tangent").c_str()); - - if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) { - std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE; - name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); - bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); - + if(need_tangent) { + AttributeStandard sign_std = + (active_render)? ATTR_STD_UV_TANGENT_SIGN + : ATTR_STD_NONE; + ustring sign_name = ustring( + (string(l->name().c_str()) + ".tangent_sign").c_str()); + bool need_sign = (mesh->need_attribute(scene, sign_name) || + mesh->need_attribute(scene, sign_std)); mikk_compute_tangents(b_mesh, &(*l), mesh, - nverts, - face_flags, need_sign, active_render); } + /* Remove temporarily created UV attribute. */ + if(!need_uv && uv_attr != NULL) { + mesh->attributes.remove(uv_attr); + } } } else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); - mikk_compute_tangents(b_mesh, - NULL, - mesh, - nverts, - face_flags, - need_sign, - true); + mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true); + if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + mesh->attributes.remove(ATTR_STD_GENERATED); + } } } @@ -758,7 +766,13 @@ static void create_mesh(Scene *scene, N = attr_N->data_float3(); /* create generated coordinates from undeformed coordinates */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + const bool need_default_tangent = + (subdivision == false) && + (b_mesh.tessface_uv_textures.length() == 0) && + (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)); + if(mesh->need_attribute(scene, ATTR_STD_GENERATED) || + need_default_tangent) + { Attribute *attr = attributes.add(ATTR_STD_GENERATED); attr->flags |= ATTR_SUBDIVIDED; @@ -768,8 +782,9 @@ static void create_mesh(Scene *scene, float3 *generated = attr->data_float3(); size_t i = 0; - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) + for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) { generated[i++] = get_float3(v->undeformed_co())*size - loc; + } } /* create faces */ diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index e157a385904..9dff18691cd 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -502,6 +502,16 @@ Attribute *AttributeSet::find(AttributeRequest& req) return find(req.std); } +void AttributeSet::remove(Attribute *attribute) +{ + if(attribute->std == ATTR_STD_NONE) { + remove(attribute->name); + } + else { + remove(attribute->std); + } +} + void AttributeSet::resize(bool reserve_only) { foreach(Attribute& attr, attributes) { diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index a64eb6542d5..d15ee401a72 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -120,6 +120,8 @@ public: Attribute *find(AttributeRequest& req); + void remove(Attribute *attribute); + void resize(bool reserve_only = false); void clear(); }; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index c02a5222463..c5eb3a0d3a8 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -107,6 +107,19 @@ void Mesh::Triangle::verts_for_step(const float3 *verts, } } +float3 Mesh::Triangle::compute_normal(const float3 *verts) const +{ + const float3& v0 = verts[v[0]]; + const float3& v1 = verts[v[1]]; + const float3& v2 = verts[v[2]]; + const float3 norm = cross(v1 - v0, v2 - v0); + const float normlen = len(norm); + if(normlen == 0.0f) { + return make_float3(1.0f, 0.0f, 0.0f); + } + return norm / normlen; +} + /* Curve */ void Mesh::Curve::bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox& bounds) const @@ -701,21 +714,6 @@ void Mesh::compute_bounds() bounds = bnds; } -static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts) -{ - float3 v0 = verts[t.v[0]]; - float3 v1 = verts[t.v[1]]; - float3 v2 = verts[t.v[2]]; - - float3 norm = cross(v1 - v0, v2 - v0); - float normlen = len(norm); - - if(normlen == 0.0f) - return make_float3(1.0f, 0.0f, 0.0f); - - return norm / normlen; -} - void Mesh::add_face_normals() { /* don't compute if already there */ @@ -733,7 +731,7 @@ void Mesh::add_face_normals() float3 *verts_ptr = verts.data(); for(size_t i = 0; i < triangles_size; i++) { - fN[i] = compute_face_normal(get_triangle(i), verts_ptr); + fN[i] = get_triangle(i).compute_normal(verts_ptr); } } @@ -795,7 +793,7 @@ void Mesh::add_vertex_normals() for(size_t i = 0; i < triangles_size; i++) { for(size_t j = 0; j < 3; j++) { - float3 fN = compute_face_normal(get_triangle(i), mP); + float3 fN = get_triangle(i).compute_normal(mP); mN[get_triangle(i).v[j]] += fN; } } diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 9a51ca73950..3483ab4fd69 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -70,6 +70,8 @@ public: size_t num_steps, size_t step, float3 r_verts[3]) const; + + float3 compute_normal(const float3 *verts) const; }; Triangle get_triangle(size_t i) const diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index ec4c7c7c50d..4ec485d521b 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -982,6 +982,8 @@ public: /* ideally we could beter detect this, but we can't query this now */ bool has_spatial_varying() { return true; } + bool has_volume_support() { return true; } + virtual bool equals(const ShaderNode& /*other*/) { return false; } string filepath; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index d36f128cef1..6b2d809c31a 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -420,7 +420,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) ListBase rl, rv; sce_copy = BKE_scene_add(bmain, sce->id.name + 2); - + rl = sce_copy->r.layers; rv = sce_copy->r.views; curvemapping_free_data(&sce_copy->r.mblur_shutter_curve); @@ -517,6 +517,8 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) } else { BKE_id_copy_ex(bmain, (ID *)sce, (ID **)&sce_copy, LIB_ID_COPY_ACTIONS, false); + id_us_min(&sce_copy->id); + id_us_ensure_real(&sce_copy->id); /* Extra actions, most notably SCE_FULL_COPY also duplicates several 'children' datablocks... */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index f6826deaf3a..158cc53dfb3 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -444,7 +444,7 @@ void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *blo * */ uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, short dt); -void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2]); +void UI_block_end_ex(const struct bContext *C, uiBlock *block, const int xy[2], int r_xy[2]); void UI_block_end(const struct bContext *C, uiBlock *block); void UI_block_draw(const struct bContext *C, struct uiBlock *block); void UI_block_update_from_old(const struct bContext *C, struct uiBlock *block); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5eb1d362394..35cbcccf515 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -367,10 +367,10 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block) static void ui_block_bounds_calc_popup( wmWindow *window, uiBlock *block, - eBlockBoundsCalc bounds_calc, const int xy[2]) + eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2]) { int width, height, oldwidth, oldheight; - int oldbounds, xmax, ymax; + int oldbounds, xmax, ymax, raw_x, raw_y; const int margin = UI_SCREEN_MARGIN; rcti rect, rect_bounds; int ofs_dummy[2]; @@ -408,8 +408,8 @@ static void ui_block_bounds_calc_popup( /* offset block based on mouse position, user offset is scaled * along in case we resized the block in ui_block_bounds_calc_text */ - rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth; - rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight; + raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->mx * width) / oldwidth; + raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->my * height) / oldheight; rect.xmax = rect.xmin + width; rect.ymax = rect.ymin + height; @@ -423,6 +423,13 @@ static void ui_block_bounds_calc_popup( /* now recompute bounds and safety */ ui_block_bounds_calc(block); + + /* If given, adjust input coordinates such that they would generate real final popup position. + * Needed to handle correctly floating panels once they have been dragged around, see T52999. */ + if (r_xy) { + r_xy[0] = xy[0] + block->rect.xmin - raw_x; + r_xy[1] = xy[1] + block->rect.ymin - raw_y; + } } /* used for various cases */ @@ -1233,7 +1240,7 @@ void UI_block_update_from_old(const bContext *C, uiBlock *block) block->oldblock = NULL; } -void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) +void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_xy[2]) { wmWindow *window = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); @@ -1301,7 +1308,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2]) /* fallback */ case UI_BLOCK_BOUNDS_POPUP_MOUSE: case UI_BLOCK_BOUNDS_POPUP_MENU: - ui_block_bounds_calc_popup(window, block, block->bounds_type, xy); + ui_block_bounds_calc_popup(window, block, block->bounds_type, xy, r_xy); break; } @@ -1319,7 +1326,7 @@ void UI_block_end(const bContext *C, uiBlock *block) { wmWindow *window = CTX_wm_window(C); - UI_block_end_ex(C, block, &window->eventstate->x); + UI_block_end_ex(C, block, &window->eventstate->x, NULL); } /* ************** BLOCK DRAWING FUNCTION ************* */ diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 57290c47210..aabb165b483 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1877,8 +1877,9 @@ uiBlock *ui_popup_block_refresh( /* defer this until blocks are translated (below) */ block->oldblock = NULL; - if (!block->endblock) - UI_block_end_ex(C, block, handle->popup_create_vars.event_xy); + if (!block->endblock) { + UI_block_end_ex(C, block, handle->popup_create_vars.event_xy, handle->popup_create_vars.event_xy); + } /* if this is being created from a button */ if (but) { diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 89c196dbcad..fc0cd9e475b 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -565,6 +565,10 @@ PyDoc_STRVAR(bpy_bm_utils_face_split_edgenet_doc, " :type edgenet: :class:`bmesh.types.BMEdge`\n" " :return: The newly created faces.\n" " :rtype: tuple of (:class:`bmesh.types.BMFace`)\n" +"\n" +" .. note::\n" +"\n" +" Regions defined by edges need to connect to the face, otherwise they're ignored as loose edges.\n" ); static PyObject *bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { |