rna/python api change: rename Mesh.faces --> tessfaces, since existing scripts are...
authorCampbell Barton <ideasman42@gmail.com>
Fri, 23 Mar 2012 00:28:29 +0000 (00:28 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 23 Mar 2012 00:28:29 +0000 (00:28 +0000)
This also makes it clearer that the faces are for tessellated results only.

Added a section on the Gotcha's about upgrading scripts, the pros and cons of MeshTessFace/MeshPoly/BMFace.
and spesifically how to upgrade importers and exporters for 2.63+.

doc/python_api/rst/info_gotcha.rst
doc/python_api/sphinx_doc_gen.py
release/scripts/modules/bpy_extras/mesh_utils.py
release/scripts/modules/bpy_types.py
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_mesh.c

index be11e88b2faca76ffc8d2e2d97c444d53485ea23..0a2918ca43c1dfdef80af1bf700a3a853c999eb9 100644 (file)
@@ -132,6 +132,86 @@ write useful tools in python which are also fast to execute while in edit-mode.
 For the time being this limitation just has to be worked around but we're aware its frustrating needs to be addressed.
 
 
+NGons and Tessellation Faces
+============================
+
+Since 2.63 NGons are supported, this adds some complexity since in some cases you need to access triangles still (some exporters for example).
+
+There are now 3 ways to access faces:
+
+* :class:`bpy.types.MeshPolygon` - this is the data stricture which now stores faces in object mode (access as ``mesh.polygons`` rather then ``mesh.faces``).
+* :class:`bpy.types.MeshTessFace` - the result of triangulating (tessellated) polygons, the main method of face access in 2.62 or older.
+* :class:`bmesh.types.BMFace` - the polygons as used in editmode.
+
+For the purpose of the following documentation, these will be referred to as polygons, tessfaces and bmesh-faces respectively.
+
+5+ sided faces will be referred to as ``ngons``.
+
+Support Overview
+----------------
+
++--------------+------------------------------+--------------------------------+--------------------------------+
+|Usage         |:class:`bpy.types.MeshPolygon`|:class:`bpy.types.MeshTessFace` |:class:`bmesh.types.BMFace`     |
++==============+==============================+================================+================================+
+|Import/Create |Bad (inflexible)              |Fine (supported as upgrade path)|Best                            |
++--------------+------------------------------+--------------------------------+--------------------------------+
+|Manipulate    |Bad (inflexible)              |Bad (looses ngons)              |Best                            |
++--------------+------------------------------+--------------------------------+--------------------------------+
+|Export/Output |Good (ngons)                  |Good (When ngons can't be used) |Good (ngons, memory overhead)   |
++--------------+------------------------------+--------------------------------+--------------------------------+
+
+
+Creating
+--------
+
+All 3 datatypes can be used for face creation.
+
+* polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible, you must have all your vertes and faces ready and create them all at once. This is further complicated by the fact that each polygon does not store its own verts (as with tessfaces), rather they reference an index and size in :class:`bpy.types.Mesh.loops` which in-turn is a fixed array.
+* tessfaces ideally should not be used for creating faces since they are really only tessellation cache of polygons, however for scripts upgrading from 2.62 this is by far the most straightforward option. This works by creating tessfaces and when finished - they can be converted into polygons by calling :class:`bpy.types.Mesh.update`. The obvious limitation is ngons cant be created this way.
+* bmesh-faces are most likely the easiest way for new scripts to create faces, since faces can be added one by one and the api has features intended for mesh manipulation. While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
+
+
+Editing
+-------
+
+Editing is where the 3 data types vary most.
+
+* polygons are very limited for editing, changing materials and options like smooth works but for anything else they are too inflexible and are only intended for storage.
+* tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated.
+* bmesh-faces are by far the best way to manipulate geometry.
+
+Exporting
+---------
+
+All 3 data types can be used for exporting, the choice mostly depends on weather the target format supports ngons or not.
+
+* polygons are the most direct & efficient way to export providing they convert into the output format easily enough.
+* tessfaces work well for exporting to formats which dont support ngons, in fact this is the only place where their use is encouraged.
+* bmesh-faces can work for exporting too but may not be necessary if polygons can be used since using bmesh gives some overhead because its not the native storage format in object mode.
+
+
+Upgrading Importers from 2.62
+-----------------------------
+
+Importers can be upgraded to work with only minor changes.
+
+The main change to be made is used the tessellation versions of each function.
+
+* mesh.faces --> :class:`bpy.types.Mesh.tessfaces`
+* mesh.uv_textures --> :class:`bpy.types.Mesh.tessface_uv_textures`
+* mesh.vertex_colors --> :class:`bpy.types.Mesh.tessface_vertex_colors`
+
+Once the data is created call :class:`bpy.types.Mesh.update` to convert the tessfaces into polygons.
+
+
+Upgrading Exporters from 2.62
+-----------------------------
+
+For exporters the most direct way to upgrade is to use tessfaces as with importing however its important to know that tessfaces may **not** exist for a mesh, the array will be empty as if there are no faces.
+
+So before accessing tessface data call: :class:`bmesh.types.BMesh.update` ``(calc_tessface=True)``.
+
+
 EditBones, PoseBones, Bone... Bones
 ===================================
 
index e88c7f5e0749543e83f456f58bc2d84406883bf4..9ff82e8fd16fc210d39290605c14a425fb1d894c 100644 (file)
@@ -270,6 +270,9 @@ else:
     import fnmatch
     m = None
     EXCLUDE_MODULES = tuple([m for m in EXCLUDE_MODULES if not fnmatch.fnmatchcase(m, ARGS.partial)])
+
+    EXCLUDE_INFO_DOCS = (not fnmatch.fnmatchcase("info", ARGS.partial))
+
     del m
     del fnmatch
 
index eccc799775c7c7700f73a3324a22b37fb243fee6..01e4b248858e45f2dbe35a6dcf3c078fb734175f 100644 (file)
@@ -127,7 +127,7 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
     :arg mesh: the mesh used to get edge loops from.
     :type mesh: :class:`bpy.types.Mesh`
     :arg faces: optional face list to only use some of the meshes faces.
-    :type faces: :class:`bpy.types.MeshFaces`, sequence or or NoneType
+    :type faces: :class:`bpy.types.MeshTessFace`, sequence or or NoneType
     :return: return a list of edge vertex index lists.
     :rtype: list
     """
@@ -449,7 +449,7 @@ def face_random_points(num_points, faces):
     :arg num_points: the number of random points to generate on each face.
     :type int:
     :arg faces: list of the faces to generate points on.
-    :type faces: :class:`bpy.types.MeshFaces`, sequence
+    :type faces: :class:`bpy.types.MeshTessFace`, sequence
     :return: list of random points over all faces.
     :rtype: list
     """
index 8c02e845071f8fad41391f426a48062d38e76775..933e77ce2e35a92ee3334812d587e95eca05c65a 100644 (file)
@@ -411,7 +411,7 @@ class MeshEdge(StructRNA):
         return ord_ind(*tuple(self.vertices))
 
 
-class MeshFace(StructRNA):
+class MeshTessFace(StructRNA):
     __slots__ = ()
 
     @property
index 7d7629f8eefab7c514d226c5652ba0dd6ecc7bf2..84301c8000f6d0a7c473634668e62f2f06d310c5 100644 (file)
@@ -311,8 +311,8 @@ extern StructRNA RNA_MeshColorLayer;
 extern StructRNA RNA_MeshLoopColorLayer;
 extern StructRNA RNA_MeshDeformModifier;
 extern StructRNA RNA_MeshEdge;
-extern StructRNA RNA_MeshFace;
 extern StructRNA RNA_MeshPolygon;
+extern StructRNA RNA_MeshTessFace;
 extern StructRNA RNA_MeshLoop;
 extern StructRNA RNA_MeshFloatProperty;
 extern StructRNA RNA_MeshFloatPropertyLayer;
index 802f103d4171174734670aa9d2b25cb99d76fa8f..6aa77d8c8d7e0b6a5c9f7ebaeb4814b43f629297 100644 (file)
@@ -225,7 +225,7 @@ static float rna_MeshPolygon_area_get(PointerRNA *ptr)
        return mesh_calc_poly_area(mp, me->mloop+mp->loopstart, me->mvert, NULL);
 }
 
-static void rna_MeshFace_normal_get(PointerRNA *ptr, float *values)
+static void rna_MeshTessFace_normal_get(PointerRNA *ptr, float *values)
 {
        Mesh *me = rna_mesh(ptr);
        MFace *mface = (MFace*)ptr->data;
@@ -237,7 +237,7 @@ static void rna_MeshFace_normal_get(PointerRNA *ptr, float *values)
                normal_tri_v3(values, me->mvert[mface->v1].co, me->mvert[mface->v2].co, me->mvert[mface->v3].co);
 }
 
-static float rna_MeshFace_area_get(PointerRNA *ptr)
+static float rna_MeshTessFace_area_get(PointerRNA *ptr)
 {
        Mesh *me = rna_mesh(ptr);
        MFace *mface = (MFace*)ptr->data;
@@ -466,14 +466,6 @@ static void rna_MeshVertex_groups_begin(CollectionPropertyIterator *iter, Pointe
                rna_iterator_array_begin(iter, NULL, 0, 0, 0, NULL);
 }
 
-static void rna_MeshFace_material_index_range(PointerRNA *ptr, int *min, int *max)
-{
-       Mesh *me = rna_mesh(ptr);
-       *min = 0;
-       *max = me->totcol-1;
-       *max = MAX2(0, *max);
-}
-
 static int rna_CustomDataLayer_active_get(PointerRNA *ptr, CustomData *data, int type, int render)
 {
        int n = ((CustomDataLayer*)ptr->data) - data->layers;
@@ -884,7 +876,7 @@ static float rna_Mesh_auto_smooth_angle_get(PointerRNA *ptr)
        return DEG2RADF((float)me->smoothresh);
 }
 
-static int rna_MeshFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
+static int rna_MeshTessFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
 {
        MFace *face = (MFace*)ptr->data;
 
@@ -896,13 +888,13 @@ static int rna_MeshFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARR
        return length[0];
 }
 
-static void rna_MeshFace_verts_get(PointerRNA *ptr, int *values)
+static void rna_MeshTessFace_verts_get(PointerRNA *ptr, int *values)
 {
        MFace *face = (MFace*)ptr->data;
        memcpy(values, &face->v1, (face->v4 ? 4 : 3) * sizeof(int));
 }
 
-static void rna_MeshFace_verts_set(PointerRNA *ptr, const int *values)
+static void rna_MeshTessFace_verts_set(PointerRNA *ptr, const int *values)
 {
        MFace *face = (MFace*)ptr->data;
        memcpy(&face->v1, values, (face->v4 ? 4 : 3) * sizeof(int));
@@ -938,6 +930,13 @@ static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values)
        }
 }
 
+static void rna_MeshPoly_material_index_range(PointerRNA *ptr, int *min, int *max)
+{
+       Mesh *me = rna_mesh(ptr);
+       *min = 0;
+       *max = me->totcol-1;
+       *max = MAX2(0, *max);
+}
 
 static int rna_MeshVertex_index_get(PointerRNA *ptr)
 {
@@ -953,7 +952,7 @@ static int rna_MeshEdge_index_get(PointerRNA *ptr)
        return (int)(edge - me->medge);
 }
 
-static int rna_MeshFace_index_get(PointerRNA *ptr)
+static int rna_MeshTessFace_index_get(PointerRNA *ptr)
 {
        Mesh *me = rna_mesh(ptr);
        MFace *face = (MFace*)ptr->data;
@@ -996,9 +995,9 @@ static char *rna_MeshPolygon_path(PointerRNA *ptr)
        return BLI_sprintfN("polygons[%d]", (int)((MPoly*)ptr->data - rna_mesh(ptr)->mpoly));
 }
 
-static char *rna_MeshFace_path(PointerRNA *ptr)
+static char *rna_MeshTessFace_path(PointerRNA *ptr)
 {
-       return BLI_sprintfN("faces[%d]", (int)((MFace*)ptr->data - rna_mesh(ptr)->mface));
+       return BLI_sprintfN("tessfaces[%d]", (int)((MFace *)ptr->data - rna_mesh(ptr)->mface));
 }
 
 static char *rna_MeshEdge_path(PointerRNA *ptr)
@@ -1442,18 +1441,18 @@ static void rna_def_mface(BlenderRNA *brna)
        StructRNA *srna;
        PropertyRNA *prop;
 
-       srna = RNA_def_struct(brna, "MeshFace", NULL);
+       srna = RNA_def_struct(brna, "MeshTessFace", NULL);
        RNA_def_struct_sdna(srna, "MFace");
        RNA_def_struct_ui_text(srna, "Mesh Face", "Face in a Mesh datablock");
-       RNA_def_struct_path_func(srna, "rna_MeshFace_path");
+       RNA_def_struct_path_func(srna, "rna_MeshTessFace_path");
        RNA_def_struct_ui_icon(srna, ICON_FACESEL);
 
        /* XXX allows creating invalid meshes */
        prop = RNA_def_property(srna, "vertices", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_array(prop, 4);
        RNA_def_property_flag(prop, PROP_DYNAMIC);
-       RNA_def_property_dynamic_array_funcs(prop, "rna_MeshFace_verts_get_length");
-       RNA_def_property_int_funcs(prop, "rna_MeshFace_verts_get", "rna_MeshFace_verts_set", NULL);
+       RNA_def_property_dynamic_array_funcs(prop, "rna_MeshTessFace_verts_get_length");
+       RNA_def_property_int_funcs(prop, "rna_MeshTessFace_verts_get", "rna_MeshTessFace_verts_set", NULL);
        RNA_def_property_ui_text(prop, "Vertices", "Vertex indices");
 
        /* leaving this fixed size array for foreach_set used in import scripts */
@@ -1465,7 +1464,7 @@ static void rna_def_mface(BlenderRNA *brna)
        prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_int_sdna(prop, NULL, "mat_nr");
        RNA_def_property_ui_text(prop, "Material Index", "");
-       RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshFace_material_index_range");
+       RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); /* reuse for tessface is ok */
        RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
 
        prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -1487,17 +1486,17 @@ static void rna_def_mface(BlenderRNA *brna)
        RNA_def_property_array(prop, 3);
        RNA_def_property_range(prop, -1.0f, 1.0f);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_float_funcs(prop, "rna_MeshFace_normal_get", NULL, NULL);
+       RNA_def_property_float_funcs(prop, "rna_MeshTessFace_normal_get", NULL, NULL);
        RNA_def_property_ui_text(prop, "Face normal", "Local space unit length normal vector for this face");
 
        prop = RNA_def_property(srna, "area", PROP_FLOAT, PROP_UNSIGNED);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_float_funcs(prop, "rna_MeshFace_area_get", NULL, NULL);
+       RNA_def_property_float_funcs(prop, "rna_MeshTessFace_area_get", NULL, NULL);
        RNA_def_property_ui_text(prop, "Face area", "Read only area of the face");
 
        prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
-       RNA_def_property_int_funcs(prop, "rna_MeshFace_index_get", NULL, NULL);
+       RNA_def_property_int_funcs(prop, "rna_MeshTessFace_index_get", NULL, NULL);
        RNA_def_property_ui_text(prop, "Index", "Index number of the vertex");
 }
 
@@ -1562,7 +1561,7 @@ static void rna_def_mpolygon(BlenderRNA *brna)
        prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_int_sdna(prop, NULL, "mat_nr");
        RNA_def_property_ui_text(prop, "Material Index", "");
-       RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshFace_material_index_range");
+       RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range");
        RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
 
        prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -2492,9 +2491,9 @@ static void rna_def_mesh(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Edges", "Edges of the mesh");
        rna_def_mesh_edges(brna, prop);
 
-       prop = RNA_def_property(srna, "faces", PROP_COLLECTION, PROP_NONE);
+       prop = RNA_def_property(srna, "tessfaces", PROP_COLLECTION, PROP_NONE);
        RNA_def_property_collection_sdna(prop, NULL, "mface", "totface");
-       RNA_def_property_struct_type(prop, "MeshFace");
+       RNA_def_property_struct_type(prop, "MeshTessFace");
        RNA_def_property_ui_text(prop, "Faces", "Faces of the mesh");
        rna_def_mesh_faces(brna, prop);