[Bf-blender-cvs] [643afc347b6] greasepencil-object: WIP: Operator to create vertex groups

Antonioya noreply at git.blender.org
Thu Aug 23 10:34:02 CEST 2018


Commit: 643afc347b691d8f0802e981f84f5b886890c3d1
Author: Antonioya
Date:   Sun Aug 19 13:04:21 2018 +0200
Branches: greasepencil-object
https://developer.blender.org/rB643afc347b691d8f0802e981f84f5b886890c3d1

WIP: Operator to create vertex groups

Only works with the Empty mode.

===================================================================

M	source/blender/editors/gpencil/CMakeLists.txt
A	source/blender/editors/gpencil/gpencil_armature.c
M	source/blender/editors/gpencil/gpencil_intern.h
M	source/blender/editors/gpencil/gpencil_ops.c
M	source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c

===================================================================

diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 114e55c5704..cea2e5d4269 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -58,6 +58,7 @@ set(SRC
 	gpencil_undo.c
 	gpencil_utils.c
 	gpencil_old.c
+	gpencil_armature.c
 
 	gpencil_intern.h
 )
diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c
new file mode 100644
index 00000000000..0ee25c58603
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_armature.c
@@ -0,0 +1,481 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2018, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators for dealing with armatures and GP datablocks
+ */
+
+/** \file blender/editors/gpencil/gpencil_armature.c
+ *  \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string_utils.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_deform.h"
+#include "BKE_gpencil.h"
+#include "BKE_gpencil_modifier.h"
+#include "BKE_object_deform.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "ED_gpencil.h"
+#include "ED_mesh.h"
+
+#include "DEG_depsgraph.h"
+
+#include "gpencil_intern.h"
+
+enum {
+	GP_ARMATURE_NAME = 0,
+	GP_ARMATURE_AUTO = 1
+};
+
+static int gpencil_bone_looper(Object *ob, Bone *bone, void *data,
+	int(*bone_func)(Object *, Bone *, void *))
+{
+	/* We want to apply the function bone_func to every bone
+	 * in an armature -- feed bone_looper the first bone and
+	 * a pointer to the bone_func and watch it go!. The int count
+	 * can be useful for counting bones with a certain property
+	 * (e.g. skinnable)
+	 */
+	int count = 0;
+
+	if (bone) {
+		/* only do bone_func if the bone is non null */
+		count += bone_func(ob, bone, data);
+
+		/* try to execute bone_func for the first child */
+		count += gpencil_bone_looper(ob, bone->childbase.first, data, bone_func);
+
+		/* try to execute bone_func for the next bone at this
+		 * depth of the recursion.
+		 */
+		count += gpencil_bone_looper(ob, bone->next, data, bone_func);
+	}
+
+	return count;
+}
+
+static int bone_skinnable_cb(Object *UNUSED(ob), Bone *bone, void *datap)
+{
+	/* Bones that are deforming
+	 * are regarded to be "skinnable" and are eligible for
+	 * auto-skinning.
+	 *
+	 * This function performs 2 functions:
+	 *
+	 *   a) It returns 1 if the bone is skinnable.
+	 *      If we loop over all bones with this
+	 *      function, we can count the number of
+	 *      skinnable bones.
+	 *   b) If the pointer data is non null,
+	 *      it is treated like a handle to a
+	 *      bone pointer -- the bone pointer
+	 *      is set to point at this bone, and
+	 *      the pointer the handle points to
+	 *      is incremented to point to the
+	 *      next member of an array of pointers
+	 *      to bones. This way we can loop using
+	 *      this function to construct an array of
+	 *      pointers to bones that point to all
+	 *      skinnable bones.
+	 */
+	Bone ***hbone;
+	int a, segments;
+	struct { Object *armob; void *list; int heat;} *data = datap;
+
+	if (!(bone->flag & BONE_HIDDEN_P)) {
+		if (!(bone->flag & BONE_NO_DEFORM)) {
+			if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
+				segments = bone->segments;
+			else
+				segments = 1;
+
+			if (data->list != NULL) {
+				hbone = (Bone ***)&data->list;
+
+				for (a = 0; a < segments; a++) {
+					**hbone = bone;
+					++*hbone;
+				}
+			}
+			return segments;
+		}
+	}
+	return 0;
+}
+
+static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
+{
+	/* This group creates a vertex group to ob that has the
+	 * same name as bone (provided the bone is skinnable).
+	 * If such a vertex group already exist the routine exits.
+	 */
+	if (!(bone->flag & BONE_NO_DEFORM)) {
+		if (!defgroup_find_name(ob, bone->name)) {
+			BKE_object_defgroup_add_name(ob, bone->name);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
+{
+	/* Bones that are deforming
+	 * are regarded to be "skinnable" and are eligible for
+	 * auto-skinning.
+	 *
+	 * This function performs 2 functions:
+	 *
+	 *   a) If the bone is skinnable, it creates
+	 *      a vertex group for ob that has
+	 *      the name of the skinnable bone
+	 *      (if one doesn't exist already).
+	 *   b) If the pointer data is non null,
+	 *      it is treated like a handle to a
+	 *      bDeformGroup pointer -- the
+	 *      bDeformGroup pointer is set to point
+	 *      to the deform group with the bone's
+	 *      name, and the pointer the handle
+	 *      points to is incremented to point to the
+	 *      next member of an array of pointers
+	 *      to bDeformGroups. This way we can loop using
+	 *      this function to construct an array of
+	 *      pointers to bDeformGroups, all with names
+	 *      of skinnable bones.
+	 */
+	bDeformGroup ***hgroup, *defgroup = NULL;
+	int a, segments;
+	struct { Object *armob; void *list; int heat; bool is_weight_paint; } *data = datap;
+	bArmature *arm = data->armob->data;
+
+	if (!data->is_weight_paint || !(bone->flag & BONE_HIDDEN_P)) {
+		if (!(bone->flag & BONE_NO_DEFORM)) {
+			if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name))
+				segments = bone->segments;
+			else
+				segments = 1;
+
+			if (!data->is_weight_paint || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) {
+				if (!(defgroup = defgroup_find_name(ob, bone->name))) {
+					defgroup = BKE_object_defgroup_add_name(ob, bone->name);
+				}
+				else if (defgroup->flag & DG_LOCK_WEIGHT) {
+					/* In case vgroup already exists and is locked, do not modify it here. See T43814. */
+					defgroup = NULL;
+				}
+			}
+
+			if (data->list != NULL) {
+				hgroup = (bDeformGroup ***)&data->list;
+
+				for (a = 0; a < segments; a++) {
+					**hgroup = defgroup;
+					++*hgroup;
+				}
+			}
+			return segments;
+		}
+	}
+	return 0;
+}
+
+static void add_verts_to_dgroups(
+	ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, Object *par,
+	int heat, const bool mirror)
+{
+	/* This functions implements the automatic computation of vertex group
+	 * weights, either through envelopes or using a heat equilibrium.
+	 *
+	 * This function can be called both when parenting a mesh to an armature,
+	 * or in weightpaint + posemode. In the latter case selection is taken
+	 * into account and vertex weights can be mirrored.
+	 *
+	 * The mesh vertex positions used are either the final deformed coords
+	 * from the evaluated mesh in weightpaint mode, the final subsurf coords
+	 * when parenting, or simply the original mesh coords.
+	 */
+
+	bArmature *arm = par->data;
+	Bone **bonelist, *bone;
+	bDeformGroup **dgrouplist, **dgroupflip;
+	bDeformGroup *dgroup;
+	bPoseChannel *pchan;
+	bGPdata *gpd;
+	Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL;
+	float(*root)[3], (*tip)[3], (*verts)[3];
+	int *selected;
+	int numbones, vertsfilled = 0, i, j, segments = 0;
+	struct { Object *armob; void *list; int heat; } looper_data;
+
+	looper_data.armob = par;
+	looper_data.heat = heat;
+	looper_data.list = NULL;
+
+	/* count the number of skinnable bones */
+	numbones = gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
+
+	if (numbones == 0)
+		return;
+
+	if (BKE_object_defgroup_data_create(ob->data) == NULL)
+		return;
+
+	/* create an array of pointer to bones that are skinnable
+	 * and fill it with all of the skinnable bones */
+	bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist");
+	looper_data.list = bonelist;
+	gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
+
+	/* create an array of pointers to the deform groups that
+	 * correspond to the skinnable bones (creating them
+	 * as necessary. */
+	dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist");
+	dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip");
+
+	looper_data.list = dgrouplist;
+	gpencil_bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
+
+	/* create an array of root and tip positions transformed into
+	 * global coords */
+	root = MEM_callocN(numbones * sizeof(float) * 3, "root");
+	tip = MEM_callocN(numbones * sizeof(float) * 3, "tip");
+	selected = MEM_callocN(numbones * sizeof(int), "selected");
+
+	for (j = 0; j < numbones; j++) {
+		bone = bonelist[j];
+		dgroup = dgrouplist[j];
+
+		/* handle bbone */
+		if (heat) {
+			if (segments == 0) {
+				segments = 1;
+				bbone = NULL;
+
+				if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) {
+					if (bone->segments > 1) {
+						segments = bone->segments;
+						b_bone_spline_setup(pchan, 1, bbone_array);
+						bbone = bbone_array;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list