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:
authorSergey Sharybin <sergey.vfx@gmail.com>2011-12-21 18:50:05 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2011-12-21 18:50:05 +0400
commit9774c93435700217549d9851f4d937dbeae5b4ba (patch)
tree75ae6ae34e6348c537017fbf7335dd420addc5e1 /source/blender/editors
parent921b2ee2d44ed87363198d7bfa89bb7116b0818b (diff)
parent2777ba097f5404a736333239bb6d61ab4b561e13 (diff)
Merging r42770 through r42799 from trunk into soc-2011-tomato
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/ED_mesh.h3
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c8
-rw-r--r--source/blender/editors/mesh/editface.c154
-rw-r--r--source/blender/editors/mesh/meshtools.c2
-rw-r--r--source/blender/editors/object/object_edit.c48
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c13
-rw-r--r--source/blender/editors/object/object_ops.c1
10 files changed, 154 insertions, 80 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 3a69db013c0..6b374274205 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -253,7 +253,8 @@ typedef struct MirrTopoStore_t {
} MirrTopoStore_t;
int ED_mesh_mirrtopo_recalc_check(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
-void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store);
+void ED_mesh_mirrtopo_init(struct Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
+ const short skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
#ifdef __cplusplus
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 1bad61be324..63e41082449 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1901,7 +1901,7 @@ void ui_set_but_soft_range(uiBut *but, double value)
if(softmin < (double)but->hardmin)
softmin= (double)but->hardmin;
}
- else if(value_max-1e-10 > softmax) {
+ if(value_max-1e-10 > softmax) {
if(value_max < 0.0)
softmax= -soft_range_round_down(-value_max, -softmax);
else
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6ebfddff5c1..900cbbd5cbf 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -5247,7 +5247,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
highlight when not in a popup menu, we remove because data used in
button below popup might have been removed by action of popup. Needs
a more reliable solution... */
- if(state != BUTTON_STATE_HIGHLIGHT || but->block->handle)
+ if(state != BUTTON_STATE_HIGHLIGHT || (but->block->flag & UI_BLOCK_LOOP))
ui_check_but(but);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 0da4d3895e0..d8a34262e81 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1795,7 +1795,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
{
/* gouraud triangle fan */
float radstep, ang= 0.0f;
- float centx, centy, radius;
+ float centx, centy, radius, cursor_radius;
float rgb[3], hsvo[3], hsv[3], col[3], colcent[3];
int a, tot= 32;
int color_profile = but->block->color_profile;
@@ -1864,12 +1864,12 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
ang= 2.0f*(float)M_PI*hsvo[0] + 0.5f*(float)M_PI;
if(but->flag & UI_BUT_COLOR_CUBIC)
- radius= (1.0f - powf(1.0f - hsvo[1], 3.0f)) *radius;
+ cursor_radius = (1.0f - powf(1.0f - hsvo[1], 3.0f));
else
- radius= hsvo[1] * radius;
+ cursor_radius = hsvo[1];
+ radius= CLAMPIS(cursor_radius, 0.0f, 1.0f) * radius;
ui_hsv_cursor(centx + cosf(-ang)*radius, centy + sinf(-ang)*radius);
-
}
/* ************ custom buttons, old stuff ************** */
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 95c71488d26..42a1b7e88f0 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -823,22 +823,22 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
typedef int MirrTopoHash_t;
-typedef struct MirrTopoPair_t {
+typedef struct MirrTopoVert_t {
MirrTopoHash_t hash;
int v_index;
-} MirrTopoPair_t;
+} MirrTopoVert_t;
-static int MirrTopo_long_sort(const void *l1, const void *l2)
+static int mirrtopo_hash_sort(const void *l1, const void *l2)
{
if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2 ) return 1;
else if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2 ) return -1;
return 0;
}
-static int MirrTopo_item_sort(const void *v1, const void *v2)
+static int mirrtopo_vert_sort(const void *v1, const void *v2)
{
- if (((MirrTopoPair_t *)v1)->hash > ((MirrTopoPair_t *)v2)->hash ) return 1;
- else if (((MirrTopoPair_t *)v1)->hash < ((MirrTopoPair_t *)v2)->hash ) return -1;
+ if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash ) return 1;
+ else if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash ) return -1;
return 0;
}
@@ -848,12 +848,12 @@ int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *
int totedge;
if (me->edit_mesh) {
- totvert= me->edit_mesh->totvert;
- totedge= me->edit_mesh->totedge;
+ totvert = me->edit_mesh->totvert;
+ totedge = me->edit_mesh->totedge;
}
else {
- totvert= me->totvert;
- totedge= me->totedge;
+ totvert = me->totvert;
+ totedge = me->totedge;
}
if( (mesh_topo_store->index_lookup==NULL) ||
@@ -869,33 +869,36 @@ int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *
}
-void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
+void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
+ const short skip_em_vert_array_init)
{
MEdge *medge;
- EditMesh *em= me->edit_mesh;
- void **eve_tmp_back= NULL; /* some of the callers are using eve->tmp so restore after */
+ EditMesh *em = me->edit_mesh;
+ void **eve_tmp_back = NULL; /* some of the callers are using eve->tmp so restore after */
/* editmode*/
EditEdge *eed;
int a, last;
int totvert, totedge;
- int totUnique= -1, totUniqueOld= -1;
+ int tot_unique = -1, tot_unique_prev = -1;
+
+ MirrTopoHash_t *topo_hash = NULL;
+ MirrTopoHash_t *topo_hash_prev = NULL;
+ MirrTopoVert_t *topo_pairs;
- MirrTopoHash_t *MirrTopoHash = NULL;
- MirrTopoHash_t *MirrTopoHash_Prev = NULL;
- MirrTopoPair_t *MirrTopoPairs;
+ intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
/* reallocate if needed */
ED_mesh_mirrtopo_free(mesh_topo_store);
- mesh_topo_store->prev_ob_mode= ob_mode;
+ mesh_topo_store->prev_ob_mode = ob_mode;
if(em) {
EditVert *eve;
- totvert= 0;
- eve_tmp_back= MEM_callocN( em->totvert * sizeof(void *), "TopoMirr" );
- for(eve= em->verts.first; eve; eve= eve->next) {
+ totvert = 0;
+ eve_tmp_back = MEM_mallocN(em->totvert * sizeof(void *), "TopoMirr");
+ for(eve = em->verts.first; eve; eve = eve->next) {
eve_tmp_back[totvert]= eve->tmp.p;
eve->tmp.l = totvert++;
}
@@ -904,130 +907,139 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
totvert = me->totvert;
}
- MirrTopoHash = MEM_callocN( totvert * sizeof(MirrTopoHash_t), "TopoMirr" );
+ topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
/* Initialize the vert-edge-user counts used to detect unique topology */
if(em) {
- totedge= 0;
+ totedge = 0;
- for(eed=em->edges.first; eed; eed= eed->next, totedge++) {
- MirrTopoHash[eed->v1->tmp.l]++;
- MirrTopoHash[eed->v2->tmp.l]++;
+ for(eed=em->edges.first; eed; eed = eed->next, totedge++) {
+ topo_hash[eed->v1->tmp.l]++;
+ topo_hash[eed->v2->tmp.l]++;
}
- } else {
- totedge= me->totedge;
+ }
+ else {
+ totedge = me->totedge;
for(a=0, medge=me->medge; a < me->totedge; a++, medge++) {
- MirrTopoHash[medge->v1]++;
- MirrTopoHash[medge->v2]++;
+ topo_hash[medge->v1]++;
+ topo_hash[medge->v2]++;
}
}
- MirrTopoHash_Prev = MEM_dupallocN( MirrTopoHash );
+ topo_hash_prev = MEM_dupallocN(topo_hash);
- totUniqueOld = -1;
+ tot_unique_prev = -1;
while(1) {
/* use the number of edges per vert to give verts unique topology IDs */
if(em) {
- for(eed=em->edges.first; eed; eed= eed->next) {
- MirrTopoHash[eed->v1->tmp.l] += MirrTopoHash_Prev[eed->v2->tmp.l];
- MirrTopoHash[eed->v2->tmp.l] += MirrTopoHash_Prev[eed->v1->tmp.l];
+ for(eed=em->edges.first; eed; eed = eed->next) {
+ topo_hash[eed->v1->tmp.l] += topo_hash_prev[eed->v2->tmp.l];
+ topo_hash[eed->v2->tmp.l] += topo_hash_prev[eed->v1->tmp.l];
}
- } else {
+ }
+ else {
for(a=0, medge=me->medge; a<me->totedge; a++, medge++) {
/* This can make really big numbers, wrapping around here is fine */
- MirrTopoHash[medge->v1] += MirrTopoHash_Prev[medge->v2];
- MirrTopoHash[medge->v2] += MirrTopoHash_Prev[medge->v1];
+ topo_hash[medge->v1] += topo_hash_prev[medge->v2];
+ topo_hash[medge->v2] += topo_hash_prev[medge->v1];
}
}
- memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MirrTopoHash_t) * totvert);
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
/* sort so we can count unique values */
- qsort(MirrTopoHash_Prev, totvert, sizeof(MirrTopoHash_t), MirrTopo_long_sort);
+ qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort);
- totUnique = 1; /* account for skiping the first value */
+ tot_unique = 1; /* account for skiping the first value */
for(a=1; a<totvert; a++) {
- if (MirrTopoHash_Prev[a-1] != MirrTopoHash_Prev[a]) {
- totUnique++;
+ if (topo_hash_prev[a-1] != topo_hash_prev[a]) {
+ tot_unique++;
}
}
- if (totUnique <= totUniqueOld) {
+ if (tot_unique <= tot_unique_prev) {
/* Finish searching for unique valus when 1 loop dosnt give a
* higher number of unique values compared to the previous loop */
break;
- } else {
- totUniqueOld = totUnique;
+ }
+ else {
+ tot_unique_prev = tot_unique;
}
/* Copy the hash calculated this iter, so we can use them next time */
- memcpy(MirrTopoHash_Prev, MirrTopoHash, sizeof(MirrTopoHash_t) * totvert);
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
}
/* restore eve->tmp.* */
if(eve_tmp_back) {
EditVert *eve;
- totvert= 0;
- for(eve= em->verts.first; eve; eve= eve->next) {
- eve->tmp.p= eve_tmp_back[totvert++];
+ totvert = 0;
+ for(eve = em->verts.first; eve; eve = eve->next) {
+ eve->tmp.p = eve_tmp_back[totvert++];
}
MEM_freeN(eve_tmp_back);
- eve_tmp_back= NULL;
+ eve_tmp_back = NULL;
}
/* Hash/Index pairs are needed for sorting to find index pairs */
- MirrTopoPairs= MEM_callocN( sizeof(MirrTopoPair_t) * totvert, "MirrTopoPairs");
+ topo_pairs = MEM_callocN( sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
/* since we are looping through verts, initialize these values here too */
- mesh_topo_store->index_lookup = MEM_mallocN( totvert * sizeof(long), "mesh_topo_lookup" );
+ index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
if(em) {
- EM_init_index_arrays(em,1,0,0);
+ if (skip_em_vert_array_init == FALSE) {
+ EM_init_index_arrays(em, 1, 0, 0);
+ }
}
for(a=0; a<totvert; a++) {
- MirrTopoPairs[a].hash= MirrTopoHash[a];
- MirrTopoPairs[a].v_index = a;
+ topo_pairs[a].hash = topo_hash[a];
+ topo_pairs[a].v_index = a;
/* initialize lookup */
- mesh_topo_store->index_lookup[a] = -1;
+ index_lookup[a] = -1;
}
- qsort(MirrTopoPairs, totvert, sizeof(MirrTopoPair_t), MirrTopo_item_sort);
+ qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
/* Since the loop starts at 2, we must define the last index where the hash's differ */
- last = ((totvert >= 2) && (MirrTopoPairs[0].hash == MirrTopoPairs[1].hash)) ? 0 : 1;
+ last = ((totvert >= 2) && (topo_pairs[0].hash == topo_pairs[1].hash)) ? 0 : 1;
/* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
* but you cant ever access the last 'a' index of MirrTopoPairs */
for(a=2; a <= totvert; a++) {
/* printf("I %d %ld %d\n", (a-last), MirrTopoPairs[a ].hash, MirrTopoPairs[a ].vIndex ); */
- if ((a==totvert) || (MirrTopoPairs[a-1].hash != MirrTopoPairs[a].hash)) {
+ if ((a==totvert) || (topo_pairs[a-1].hash != topo_pairs[a].hash)) {
if (a-last==2) {
if(em) {
- mesh_topo_store->index_lookup[MirrTopoPairs[a-1].v_index] = (intptr_t)EM_get_vert_for_index(MirrTopoPairs[a-2].v_index);
- mesh_topo_store->index_lookup[MirrTopoPairs[a-2].v_index] = (intptr_t)EM_get_vert_for_index(MirrTopoPairs[a-1].v_index);
- } else {
- mesh_topo_store->index_lookup[MirrTopoPairs[a-1].v_index] = MirrTopoPairs[a-2].v_index;
- mesh_topo_store->index_lookup[MirrTopoPairs[a-2].v_index] = MirrTopoPairs[a-1].v_index;
+ index_lookup[topo_pairs[a-1].v_index] = (intptr_t)EM_get_vert_for_index(topo_pairs[a-2].v_index);
+ index_lookup[topo_pairs[a-2].v_index] = (intptr_t)EM_get_vert_for_index(topo_pairs[a-1].v_index);
+ }
+ else {
+ index_lookup[topo_pairs[a-1].v_index] = topo_pairs[a-2].v_index;
+ index_lookup[topo_pairs[a-2].v_index] = topo_pairs[a-1].v_index;
}
}
- last= a;
+ last = a;
}
}
if(em) {
- EM_free_index_arrays();
+ if (skip_em_vert_array_init == FALSE) {
+ EM_free_index_arrays();
+ }
}
- MEM_freeN( MirrTopoPairs );
- MirrTopoPairs = NULL;
+ MEM_freeN(topo_pairs);
+ topo_pairs = NULL;
- MEM_freeN( MirrTopoHash );
- MEM_freeN( MirrTopoHash_Prev );
+ MEM_freeN(topo_hash);
+ MEM_freeN(topo_hash_prev);
+ mesh_topo_store->index_lookup = index_lookup;
mesh_topo_store->prev_vert_tot = totvert;
mesh_topo_store->prev_edge_tot = totedge;
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 77daf21affa..f3722e81246 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -861,7 +861,7 @@ int mesh_mirrtopo_table(Object *ob, char mode)
}
}
else if(mode=='s') { /* start table */
- ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store);
+ ED_mesh_mirrtopo_init(ob->data, ob->mode, &mesh_topo_store, FALSE);
}
else if(mode=='e') { /* end table */
ED_mesh_mirrtopo_free(&mesh_topo_store);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 07ab80f6d15..fa308624454 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -2178,3 +2178,51 @@ void OBJECT_OT_logic_bricks_copy(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+
+static int game_physics_copy_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob=ED_object_active_context(C);
+
+ CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) {
+ if(ob != ob_iter) {
+ ob_iter->gameflag = ob->gameflag;
+ ob_iter->gameflag2 = ob->gameflag2;
+ ob_iter->inertia = ob->inertia;
+ ob_iter->formfactor = ob->formfactor;;
+ ob_iter->damping = ob->damping;
+ ob_iter->rdamping = ob->rdamping;
+ ob_iter->min_vel = ob->min_vel;
+ ob_iter->max_vel = ob->max_vel;
+ ob_iter->obstacleRad = ob->obstacleRad;
+ ob_iter->mass = ob->mass;
+ ob_iter->anisotropicFriction[0] = ob->anisotropicFriction[0];
+ ob_iter->anisotropicFriction[1] = ob->anisotropicFriction[1];
+ ob_iter->anisotropicFriction[2] = ob->anisotropicFriction[2];
+ ob_iter->collision_boundtype = ob->collision_boundtype;
+ ob_iter->margin = ob->margin;
+ ob_iter->bsoft = copy_bulletsoftbody(ob->bsoft);
+ if(ob->restrictflag & OB_RESTRICT_RENDER)
+ ob_iter->restrictflag |= OB_RESTRICT_RENDER;
+ else
+ ob_iter->restrictflag &= ~OB_RESTRICT_RENDER;
+ }
+ }
+ CTX_DATA_END;
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Copy Game Physics Properties to Selected";
+ ot->description = "Copy game physics properties to other selected objects";
+ ot->idname= "OBJECT_OT_game_physics_copy";
+
+ /* api callbacks */
+ ot->exec= game_physics_copy_exec;
+ ot->poll= ED_operator_object_active_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index d4f68b8816e..8973fb88c85 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -92,6 +92,7 @@ void OBJECT_OT_game_property_remove(struct wmOperatorType *ot);
void OBJECT_OT_game_property_copy(struct wmOperatorType *ot);
void OBJECT_OT_game_property_clear(struct wmOperatorType *ot);
void OBJECT_OT_logic_bricks_copy(struct wmOperatorType *ot);
+void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot);
/* object_select.c */
void OBJECT_OT_select_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 913e5893a77..9a592bc9324 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -643,7 +643,7 @@ static int modifier_add_exec(bContext *C, wmOperator *op)
static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
Object *ob= ED_object_active_context(C);
- EnumPropertyItem *item= NULL, *md_item;
+ EnumPropertyItem *item= NULL, *md_item, *group_item= NULL;
ModifierTypeInfo *mti;
int totitem= 0, a;
@@ -663,6 +663,17 @@ static EnumPropertyItem *modifier_add_itemf(bContext *C, PointerRNA *UNUSED(ptr)
(ob->type==OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
continue;
}
+ else {
+ group_item= md_item;
+ md_item= NULL;
+
+ continue;
+ }
+
+ if(group_item) {
+ RNA_enum_item_add(&item, &totitem, group_item);
+ group_item= NULL;
+ }
RNA_enum_item_add(&item, &totitem, md_item);
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 4f598ce4417..acc318723d8 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -191,6 +191,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_game_property_copy);
WM_operatortype_append(OBJECT_OT_game_property_clear);
WM_operatortype_append(OBJECT_OT_logic_bricks_copy);
+ WM_operatortype_append(OBJECT_OT_game_physics_copy);
WM_operatortype_append(OBJECT_OT_shape_key_add);
WM_operatortype_append(OBJECT_OT_shape_key_remove);