2008-12-23 19:47:33 +00:00
|
|
|
/**
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation, 2002-2008 full recode
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_constraint_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_effect_types.h"
|
|
|
|
#include "DNA_group_types.h"
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
#include "DNA_ipo_types.h"
|
|
|
|
#include "DNA_key_types.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
|
|
#include "DNA_lattice_types.h"
|
|
|
|
#include "DNA_material_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
#include "DNA_nla_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_object_fluidsim.h"
|
|
|
|
#include "DNA_object_force.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_texture_types.h"
|
|
|
|
#include "DNA_particle_types.h"
|
|
|
|
#include "DNA_property_types.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "DNA_vfont_types.h"
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
#include "DNA_modifier_types.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_arithb.h"
|
|
|
|
#include "BLI_editVert.h"
|
|
|
|
#include "BLI_ghash.h"
|
|
|
|
#include "BLI_rand.h"
|
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_anim.h"
|
|
|
|
#include "BKE_armature.h"
|
|
|
|
#include "BKE_booleanops.h"
|
|
|
|
#include "BKE_constraint.h"
|
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_customdata.h"
|
|
|
|
#include "BKE_blender.h"
|
|
|
|
#include "BKE_booleanops.h"
|
|
|
|
#include "BKE_cloth.h"
|
|
|
|
#include "BKE_curve.h"
|
|
|
|
#include "BKE_displist.h"
|
|
|
|
#include "BKE_depsgraph.h"
|
|
|
|
#include "BKE_DerivedMesh.h"
|
|
|
|
#include "BKE_effect.h"
|
|
|
|
#include "BKE_font.h"
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_group.h"
|
|
|
|
#include "BKE_ipo.h"
|
|
|
|
#include "BKE_image.h"
|
|
|
|
#include "BKE_key.h"
|
|
|
|
#include "BKE_lattice.h"
|
|
|
|
#include "BKE_library.h"
|
|
|
|
#include "BKE_main.h"
|
|
|
|
#include "BKE_material.h"
|
|
|
|
#include "BKE_mball.h"
|
|
|
|
#include "BKE_mesh.h"
|
|
|
|
#include "BKE_nla.h"
|
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_particle.h"
|
|
|
|
#include "BKE_property.h"
|
|
|
|
#include "BKE_sca.h"
|
|
|
|
#include "BKE_scene.h"
|
|
|
|
#include "BKE_softbody.h"
|
|
|
|
#include "BKE_subsurf.h"
|
|
|
|
#include "BKE_texture.h"
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
#include "BKE_modifier.h"
|
|
|
|
|
|
|
|
#include "ED_anim_api.h"
|
2009-01-05 19:32:04 +00:00
|
|
|
#include "ED_armature.h"
|
2008-12-31 17:11:42 +00:00
|
|
|
#include "ED_mesh.h"
|
2009-01-01 18:05:12 +00:00
|
|
|
#include "ED_object.h"
|
2008-12-23 19:47:33 +00:00
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "ED_types.h"
|
|
|
|
#include "ED_util.h"
|
|
|
|
#include "ED_view3d.h"
|
|
|
|
|
|
|
|
#include "BMF_Api.h"
|
|
|
|
|
|
|
|
#include "UI_interface.h"
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
/* for menu/popup icons etc etc*/
|
|
|
|
#include "UI_interface.h"
|
|
|
|
#include "UI_resources.h"
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "object_intern.h" // own include
|
|
|
|
|
|
|
|
/* ************* XXX **************** */
|
|
|
|
static void allqueue() {}
|
|
|
|
static void BIF_undo_push() {}
|
|
|
|
static void error() {}
|
|
|
|
static void waitcursor() {}
|
|
|
|
static int pupmenu() {return 0;}
|
|
|
|
static int pupmenu_col() {return 0;}
|
|
|
|
static int okee() {return 0;}
|
|
|
|
static void EM_select_flush() {}
|
|
|
|
|
|
|
|
/* port over here */
|
|
|
|
static bContext *C;
|
|
|
|
static void error_libdata() {}
|
|
|
|
|
|
|
|
/* ********************************** */
|
|
|
|
|
|
|
|
/* --------------------------------- */
|
|
|
|
|
2008-12-29 12:15:42 +00:00
|
|
|
/* simple API for object selection, rather than just using the flag
|
|
|
|
* this takes into account the 'restrict selection in 3d view' flag.
|
|
|
|
* deselect works always, the restriction just prevents selection */
|
|
|
|
|
|
|
|
/* Note: send a NC_SCENE|ND_OB_SELECT notifier yourself! */
|
|
|
|
|
|
|
|
void ED_base_object_select(Base *base, short mode)
|
|
|
|
{
|
|
|
|
if (base) {
|
|
|
|
if (mode==BA_SELECT) {
|
|
|
|
if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
|
|
|
|
if (mode==BA_SELECT) base->flag |= SELECT;
|
|
|
|
}
|
|
|
|
else if (mode==BA_DESELECT) {
|
|
|
|
base->flag &= ~SELECT;
|
|
|
|
}
|
|
|
|
base->object->flag= base->flag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* also to set active NULL */
|
|
|
|
void ED_base_object_activate(bContext *C, Base *base)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
Base *tbase;
|
|
|
|
|
|
|
|
/* activating a non-mesh, should end a couple of modes... */
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
if(base && base->object->type!=OB_MESH)
|
|
|
|
ED_view3d_exit_paint_modes(C);
|
2008-12-29 12:15:42 +00:00
|
|
|
|
|
|
|
/* sets scene->basact */
|
|
|
|
BASACT= base;
|
|
|
|
|
|
|
|
if(base) {
|
|
|
|
|
|
|
|
/* XXX old signals, remember to handle notifiers now! */
|
|
|
|
// allqueue(REDRAWIPO, base->object->ipowin);
|
|
|
|
// select_actionchannel_by_name(base->object->action, "Object", 1);
|
|
|
|
|
|
|
|
/* disable temporal locks */
|
|
|
|
for(tbase=FIRSTBASE; tbase; tbase= tbase->next) {
|
|
|
|
if(base!=tbase && (tbase->object->shapeflag & OB_SHAPE_TEMPLOCK)) {
|
|
|
|
tbase->object->shapeflag &= ~OB_SHAPE_TEMPLOCK;
|
|
|
|
DAG_object_flush_update(scene, tbase->object, OB_RECALC_DATA);
|
|
|
|
}
|
|
|
|
}
|
2008-12-31 17:11:42 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
|
2008-12-29 12:15:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
/*
|
|
|
|
* Returns true if the Object is a from an external blend file (libdata)
|
|
|
|
*/
|
|
|
|
int object_is_libdata(Object *ob)
|
|
|
|
{
|
|
|
|
if (!ob) return 0;
|
|
|
|
if (ob->proxy) return 0;
|
|
|
|
if (ob->id.lib) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns true if the Object data is a from an external blend file (libdata)
|
|
|
|
*/
|
|
|
|
int object_data_is_libdata(Object *ob)
|
|
|
|
{
|
|
|
|
if (!ob) return 0;
|
|
|
|
if (ob->proxy) return 0;
|
|
|
|
if (ob->id.lib) return 1;
|
|
|
|
if (!ob->data) return 0;
|
|
|
|
if (((ID *)ob->data)->lib) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-01-05 15:19:31 +00:00
|
|
|
/* exported */
|
|
|
|
void ED_object_base_init_from_view(Scene *scene, View3D *v3d, Base *base)
|
|
|
|
{
|
|
|
|
Object *ob= base->object;
|
|
|
|
|
|
|
|
if (scene==NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (v3d==NULL) {
|
|
|
|
base->lay = scene->lay;
|
|
|
|
VECCOPY(ob->loc, scene->cursor);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (v3d->localview) {
|
|
|
|
base->lay= ob->lay= v3d->layact | v3d->lay;
|
|
|
|
VECCOPY(ob->loc, v3d->cursor);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
base->lay= ob->lay= v3d->layact;
|
|
|
|
VECCOPY(ob->loc, scene->cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (U.flag & USER_ADD_VIEWALIGNED) {
|
|
|
|
v3d->viewquat[0]= -v3d->viewquat[0];
|
|
|
|
|
|
|
|
QuatToEul(v3d->viewquat, ob->rot);
|
|
|
|
v3d->viewquat[0]= -v3d->viewquat[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
void add_object_draw(Scene *scene, View3D *v3d, int type) /* for toolbox or menus, only non-editmode stuff */
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
// ED_view3d_exit_paint_modes(C);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
// XXX if (obedit) ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
|
2009-01-04 14:14:06 +00:00
|
|
|
ob= add_object(scene, type);
|
2008-12-29 12:15:42 +00:00
|
|
|
// ED_base_object_activate(C, BASACT);
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_base_init_from_view(scene, v3d, BASACT);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* only undo pushes on objects without editmode... */
|
|
|
|
if(type==OB_EMPTY) BIF_undo_push("Add Empty");
|
|
|
|
else if(type==OB_LAMP) {
|
|
|
|
BIF_undo_push("Add Lamp");
|
2009-01-04 14:14:06 +00:00
|
|
|
reshadeall_displist(scene); /* only frees */
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
else if(type==OB_LATTICE) BIF_undo_push("Add Lattice");
|
|
|
|
else if(type==OB_CAMERA) BIF_undo_push("Add Camera");
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
|
|
|
|
// XXX redraw_test_buttons(OBACT);
|
|
|
|
|
|
|
|
allqueue(REDRAWALL, 0);
|
|
|
|
|
|
|
|
// XXX deselect_all_area_oops();
|
|
|
|
// XXX set_select_flag_oops();
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
allqueue(REDRAWINFO, 1); /* 1, because header->win==0! */
|
|
|
|
}
|
|
|
|
|
|
|
|
void add_objectLamp(Scene *scene, View3D *v3d, short type)
|
|
|
|
{
|
|
|
|
Lamp *la;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit==NULL) { // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
add_object_draw(scene, v3d, OB_LAMP);
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_base_init_from_view(scene, v3d, BASACT);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
la = BASACT->object->data;
|
|
|
|
la->type = type;
|
|
|
|
|
|
|
|
allqueue(REDRAWALL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove base from a specific scene */
|
|
|
|
/* note: now unlinks constraints as well */
|
2008-12-30 13:16:14 +00:00
|
|
|
void ED_base_object_free_and_unlink(Scene *scene, Base *base)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
BLI_remlink(&scene->base, base);
|
|
|
|
free_libblock_us(&G.main->object, base->object);
|
2008-12-30 13:16:14 +00:00
|
|
|
if(scene->basact==base) scene->basact= NULL;
|
2008-12-23 19:47:33 +00:00
|
|
|
MEM_freeN(base);
|
|
|
|
}
|
|
|
|
|
|
|
|
void delete_obj(Scene *scene, View3D *v3d, int ok)
|
|
|
|
{
|
|
|
|
Base *base, *nbase;
|
|
|
|
int islamp= 0;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) return; // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= nbase) {
|
|
|
|
nbase= base->next;
|
|
|
|
|
|
|
|
if(TESTBASE(v3d, base)) {
|
|
|
|
if(ok==0) {
|
|
|
|
int shift= 0; // XXX
|
|
|
|
/* Shift Del is global delete */
|
|
|
|
if (shift) {
|
|
|
|
if(!okee("Erase selected Object(s) Globally")) return;
|
|
|
|
ok= 2;
|
|
|
|
} else {
|
|
|
|
if(!okee("Erase selected Object(s)")) return;
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
// ED_view3d_exit_paint_modes(C);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(base->object->type==OB_LAMP) islamp= 1;
|
|
|
|
|
|
|
|
if (ok==2) {
|
|
|
|
Scene *scene;
|
|
|
|
Base *base_other;
|
|
|
|
|
|
|
|
for (scene= G.main->scene.first; scene; scene= scene->id.next) {
|
|
|
|
if (scene != scene && !(scene->id.lib)) {
|
|
|
|
base_other= object_in_scene( base->object, scene );
|
|
|
|
if (base_other) {
|
2008-12-30 13:16:14 +00:00
|
|
|
ED_base_object_free_and_unlink( scene, base_other );
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove from current scene only */
|
2008-12-30 13:16:14 +00:00
|
|
|
ED_base_object_free_and_unlink(scene, base);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
if(islamp) reshadeall_displist(scene); /* only frees displist */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
// XXX redraw_test_buttons(OBACT);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue (REDRAWACTION, 0);
|
|
|
|
allqueue(REDRAWIPO, 0);
|
|
|
|
allqueue(REDRAWDATASELECT, 0);
|
|
|
|
// allspace(OOPS_TEST, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
allqueue(REDRAWACTION, 0);
|
|
|
|
allqueue(REDRAWNLA, 0);
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
|
|
|
BIF_undo_push("Delete object(s)");
|
|
|
|
}
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
EditVert *eve;
|
|
|
|
int *index, nr, totvert=0;
|
|
|
|
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
|
|
if(eve->f & SELECT) totvert++;
|
|
|
|
}
|
|
|
|
if(totvert==0) return 0;
|
|
|
|
|
|
|
|
*indexar= index= MEM_mallocN(4*totvert, "hook indexar");
|
|
|
|
*tot= totvert;
|
|
|
|
nr= 0;
|
|
|
|
cent[0]= cent[1]= cent[2]= 0.0;
|
|
|
|
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
|
|
if(eve->f & SELECT) {
|
|
|
|
*index= nr; index++;
|
|
|
|
VecAddf(cent, cent, eve->co);
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VecMulf(cent, 1.0f/(float)totvert);
|
|
|
|
|
|
|
|
return totvert;
|
|
|
|
}
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
MDeformVert *dvert;
|
|
|
|
EditVert *eve;
|
|
|
|
int i, totvert=0;
|
|
|
|
|
|
|
|
cent[0]= cent[1]= cent[2]= 0.0;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit->actdef) {
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* find the vertices */
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next) {
|
|
|
|
dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
|
|
|
|
|
|
|
|
if(dvert) {
|
|
|
|
for(i=0; i<dvert->totweight; i++){
|
2009-01-02 19:10:35 +00:00
|
|
|
if(dvert->dw[i].def_nr == (obedit->actdef-1)) {
|
2008-12-23 19:47:33 +00:00
|
|
|
totvert++;
|
|
|
|
VecAddf(cent, cent, eve->co);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(totvert) {
|
2009-01-02 19:10:35 +00:00
|
|
|
bDeformGroup *defGroup = BLI_findlink(&obedit->defbase, obedit->actdef-1);
|
2008-12-23 19:47:33 +00:00
|
|
|
strcpy(name, defGroup->name);
|
|
|
|
VecMulf(cent, 1.0f/(float)totvert);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
2008-12-31 17:11:42 +00:00
|
|
|
Mesh *me= ob->data;
|
|
|
|
EditMesh *em= me->edit_mesh;
|
2008-12-23 19:47:33 +00:00
|
|
|
EditVert *eve;
|
|
|
|
int index=0, nr=0;
|
|
|
|
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next, nr++) {
|
|
|
|
if(nr==hmd->indexar[index]) {
|
|
|
|
eve->f |= SELECT;
|
|
|
|
if(index < hmd->totindex-1) index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EM_select_flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
static int return_editlattice_indexar(int *tot, int **indexar, float *cent)
|
|
|
|
{
|
|
|
|
BPoint *bp;
|
|
|
|
int *index, nr, totvert=0, a;
|
|
|
|
|
|
|
|
/* count */
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
bp= editLatt->def;
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT) {
|
|
|
|
if(bp->hide==0) totvert++;
|
|
|
|
}
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(totvert==0) return 0;
|
|
|
|
|
|
|
|
*indexar= index= MEM_mallocN(4*totvert, "hook indexar");
|
|
|
|
*tot= totvert;
|
|
|
|
nr= 0;
|
|
|
|
cent[0]= cent[1]= cent[2]= 0.0;
|
|
|
|
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
bp= editLatt->def;
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT) {
|
|
|
|
if(bp->hide==0) {
|
|
|
|
*index= nr; index++;
|
|
|
|
VecAddf(cent, cent, bp->vec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bp++;
|
|
|
|
nr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
VecMulf(cent, 1.0f/(float)totvert);
|
|
|
|
|
|
|
|
return totvert;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void select_editlattice_hook(HookModifierData *hmd)
|
|
|
|
{
|
|
|
|
BPoint *bp;
|
|
|
|
int index=0, nr=0, a;
|
|
|
|
|
|
|
|
/* count */
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
bp= editLatt->def;
|
|
|
|
while(a--) {
|
|
|
|
if(hmd->indexar[index]==nr) {
|
|
|
|
bp->f1 |= SELECT;
|
|
|
|
if(index < hmd->totindex-1) index++;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int return_editcurve_indexar(int *tot, int **indexar, float *cent)
|
|
|
|
{
|
|
|
|
extern ListBase editNurb;
|
|
|
|
Nurb *nu;
|
|
|
|
BPoint *bp;
|
|
|
|
BezTriple *bezt;
|
|
|
|
int *index, a, nr, totvert=0;
|
|
|
|
|
|
|
|
for(nu= editNurb.first; nu; nu= nu->next) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
|
|
bezt= nu->bezt;
|
|
|
|
a= nu->pntsu;
|
|
|
|
while(a--) {
|
|
|
|
if(bezt->f1 & SELECT) totvert++;
|
|
|
|
if(bezt->f2 & SELECT) totvert++;
|
|
|
|
if(bezt->f3 & SELECT) totvert++;
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bp= nu->bp;
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT) totvert++;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(totvert==0) return 0;
|
|
|
|
|
|
|
|
*indexar= index= MEM_mallocN(4*totvert, "hook indexar");
|
|
|
|
*tot= totvert;
|
|
|
|
nr= 0;
|
|
|
|
cent[0]= cent[1]= cent[2]= 0.0;
|
|
|
|
|
|
|
|
for(nu= editNurb.first; nu; nu= nu->next) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
|
|
bezt= nu->bezt;
|
|
|
|
a= nu->pntsu;
|
|
|
|
while(a--) {
|
|
|
|
if(bezt->f1 & SELECT) {
|
|
|
|
*index= nr; index++;
|
|
|
|
VecAddf(cent, cent, bezt->vec[0]);
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
if(bezt->f2 & SELECT) {
|
|
|
|
*index= nr; index++;
|
|
|
|
VecAddf(cent, cent, bezt->vec[1]);
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
if(bezt->f3 & SELECT) {
|
|
|
|
*index= nr; index++;
|
|
|
|
VecAddf(cent, cent, bezt->vec[2]);
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bp= nu->bp;
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT) {
|
|
|
|
*index= nr; index++;
|
|
|
|
VecAddf(cent, cent, bp->vec);
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VecMulf(cent, 1.0f/(float)totvert);
|
|
|
|
|
|
|
|
return totvert;
|
|
|
|
}
|
|
|
|
|
2009-01-05 15:19:31 +00:00
|
|
|
void ED_object_apply_obmat(Object *ob)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
float mat[3][3], imat[3][3], tmat[3][3];
|
|
|
|
|
|
|
|
/* from obmat to loc rot size */
|
|
|
|
|
|
|
|
if(ob==NULL) return;
|
|
|
|
Mat3CpyMat4(mat, ob->obmat);
|
|
|
|
|
|
|
|
VECCOPY(ob->loc, ob->obmat[3]);
|
|
|
|
|
|
|
|
Mat3ToEul(mat, ob->rot);
|
|
|
|
EulToMat3(ob->rot, tmat);
|
|
|
|
|
|
|
|
Mat3Inv(imat, tmat);
|
|
|
|
|
|
|
|
Mat3MulMat3(tmat, imat, mat);
|
|
|
|
|
|
|
|
ob->size[0]= tmat[0][0];
|
|
|
|
ob->size[1]= tmat[1][1];
|
|
|
|
ob->size[2]= tmat[2][2];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
int hook_getIndexArray(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
*indexar= NULL;
|
|
|
|
*tot= 0;
|
|
|
|
name[0]= 0;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
switch(obedit->type) {
|
2008-12-23 19:47:33 +00:00
|
|
|
case OB_MESH:
|
2008-12-31 17:11:42 +00:00
|
|
|
{
|
2009-01-02 19:10:35 +00:00
|
|
|
Mesh *me= obedit->data;
|
2008-12-23 19:47:33 +00:00
|
|
|
/* check selected vertices first */
|
2008-12-31 17:11:42 +00:00
|
|
|
if( return_editmesh_indexar(me->edit_mesh, tot, indexar, cent_r)) return 1;
|
2009-01-02 19:10:35 +00:00
|
|
|
else return return_editmesh_vgroup(obedit, me->edit_mesh, name, cent_r);
|
2008-12-31 17:11:42 +00:00
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
|
|
|
return return_editcurve_indexar(tot, indexar, cent_r);
|
|
|
|
case OB_LATTICE:
|
|
|
|
return return_editlattice_indexar(tot, indexar, cent_r);
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void select_editcurve_hook(HookModifierData *hmd)
|
|
|
|
{
|
|
|
|
extern ListBase editNurb;
|
|
|
|
Nurb *nu;
|
|
|
|
BPoint *bp;
|
|
|
|
BezTriple *bezt;
|
|
|
|
int index=0, a, nr=0;
|
|
|
|
|
|
|
|
for(nu= editNurb.first; nu; nu= nu->next) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
|
|
bezt= nu->bezt;
|
|
|
|
a= nu->pntsu;
|
|
|
|
while(a--) {
|
|
|
|
if(nr == hmd->indexar[index]) {
|
|
|
|
bezt->f1 |= SELECT;
|
|
|
|
if(index<hmd->totindex-1) index++;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
if(nr == hmd->indexar[index]) {
|
|
|
|
bezt->f2 |= SELECT;
|
|
|
|
if(index<hmd->totindex-1) index++;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
if(nr == hmd->indexar[index]) {
|
|
|
|
bezt->f3 |= SELECT;
|
|
|
|
if(index<hmd->totindex-1) index++;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bp= nu->bp;
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while(a--) {
|
|
|
|
if(nr == hmd->indexar[index]) {
|
|
|
|
bp->f1 |= SELECT;
|
|
|
|
if(index<hmd->totindex-1) index++;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
void obedit_hook_select(Object *ob, HookModifierData *hmd)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
|
|
|
|
else if(ob->type==OB_LATTICE) select_editlattice_hook(hmd);
|
|
|
|
else if(ob->type==OB_CURVE) select_editcurve_hook(hmd);
|
|
|
|
else if(ob->type==OB_SURF) select_editcurve_hook(hmd);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void add_hook(Scene *scene, View3D *v3d, int mode)
|
|
|
|
{
|
|
|
|
ModifierData *md = NULL;
|
|
|
|
HookModifierData *hmd = NULL;
|
|
|
|
Object *ob=NULL;
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= scene->obedit; // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit==NULL) return;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* preconditions */
|
|
|
|
if(mode==2) { /* selected object */
|
|
|
|
Base *base;
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
ob= base->object;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ob==NULL) {
|
|
|
|
error("Requires selected Object");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(mode!=1) {
|
|
|
|
int maxlen=0, a, nr;
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
/* make pupmenu with hooks */
|
2009-01-02 19:10:35 +00:00
|
|
|
for(md=obedit->modifiers.first; md; md= md->next) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if (md->type==eModifierType_Hook)
|
|
|
|
maxlen+=32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(maxlen==0) {
|
|
|
|
error("Object has no hooks yet");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp= MEM_callocN(maxlen+32, "temp string");
|
|
|
|
if(mode==3) strcpy(cp, "Remove %t|");
|
|
|
|
else if(mode==4) strcpy(cp, "Reassign %t|");
|
|
|
|
else if(mode==5) strcpy(cp, "Select %t|");
|
|
|
|
else if(mode==6) strcpy(cp, "Clear Offset %t|");
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
for(md=obedit->modifiers.first; md; md= md->next) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if (md->type==eModifierType_Hook) {
|
|
|
|
strcat(cp, md->name);
|
|
|
|
strcat(cp, " |");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nr= pupmenu(cp);
|
|
|
|
MEM_freeN(cp);
|
|
|
|
|
|
|
|
if(nr<1) return;
|
|
|
|
|
|
|
|
a= 1;
|
2009-01-02 19:10:35 +00:00
|
|
|
for(md=obedit->modifiers.first; md; md=md->next) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if (md->type==eModifierType_Hook) {
|
|
|
|
if(a==nr) break;
|
|
|
|
a++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hmd = (HookModifierData*) md;
|
|
|
|
ob= hmd->object;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do it, new hooks or reassign */
|
|
|
|
if(mode==1 || mode==2 || mode==4) {
|
|
|
|
float cent[3];
|
|
|
|
int tot, ok, *indexar;
|
|
|
|
char name[32];
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
ok = hook_getIndexArray(obedit, &tot, &indexar, name, cent);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(ok==0) {
|
|
|
|
error("Requires selected vertices or active Vertex Group");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
if(mode==1) {
|
|
|
|
Base *base= BASACT, *newbase;
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
ob= add_object(scene, OB_EMPTY);
|
2008-12-23 19:47:33 +00:00
|
|
|
/* set layers OK */
|
|
|
|
newbase= BASACT;
|
|
|
|
newbase->lay= base->lay;
|
|
|
|
ob->lay= newbase->lay;
|
|
|
|
|
|
|
|
/* transform cent to global coords for loc */
|
2009-01-02 19:10:35 +00:00
|
|
|
VecMat4MulVecfl(ob->loc, obedit->obmat, cent);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* restore, add_object sets active */
|
|
|
|
BASACT= base;
|
|
|
|
}
|
|
|
|
/* if mode is 2 or 4, ob has been set */
|
|
|
|
|
|
|
|
/* new hook */
|
|
|
|
if(mode==1 || mode==2) {
|
2009-01-02 19:10:35 +00:00
|
|
|
ModifierData *md = obedit->modifiers.first;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
|
|
|
|
md = md->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
|
2009-01-02 19:10:35 +00:00
|
|
|
BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
|
2008-12-23 19:47:33 +00:00
|
|
|
sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
|
|
|
|
}
|
|
|
|
else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
|
|
|
|
|
|
|
|
hmd->object= ob;
|
|
|
|
hmd->indexar= indexar;
|
|
|
|
VECCOPY(hmd->cent, cent);
|
|
|
|
hmd->totindex= tot;
|
|
|
|
BLI_strncpy(hmd->name, name, 32);
|
|
|
|
|
|
|
|
if(mode==1 || mode==2) {
|
|
|
|
/* matrix calculus */
|
|
|
|
/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
|
|
|
|
/* (parentinv ) */
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
/* apparently this call goes from right to left... */
|
2009-01-02 19:10:35 +00:00
|
|
|
Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
|
2008-12-23 19:47:33 +00:00
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(mode==3) { /* remove */
|
2009-01-02 19:10:35 +00:00
|
|
|
BLI_remlink(&obedit->modifiers, md);
|
2008-12-23 19:47:33 +00:00
|
|
|
modifier_free(md);
|
|
|
|
}
|
|
|
|
else if(mode==5) { /* select */
|
2009-01-02 19:10:35 +00:00
|
|
|
obedit_hook_select(obedit, hmd);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
else if(mode==6) { /* clear offset */
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob); /* ob is hook->parent */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
/* this call goes from right to left... */
|
2009-01-02 19:10:35 +00:00
|
|
|
Mat4MulSerie(hmd->parentinv, ob->imat, obedit->obmat, NULL,
|
2008-12-23 19:47:33 +00:00
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* use this when the loc/size/rot of the parent has changed but the children should stay in the same place
|
|
|
|
* apply-size-rot or object center for eg */
|
2009-01-04 14:14:06 +00:00
|
|
|
static void ignore_parent_tx(Scene *scene, Object *ob )
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
2008-12-24 11:08:15 +00:00
|
|
|
Object workob;
|
2008-12-23 19:47:33 +00:00
|
|
|
Object *ob_child;
|
|
|
|
|
|
|
|
/* a change was made, adjust the children to compensate */
|
|
|
|
for (ob_child=G.main->object.first; ob_child; ob_child=ob_child->id.next) {
|
|
|
|
if (ob_child->parent == ob) {
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_apply_obmat(ob_child);
|
2009-01-04 14:14:06 +00:00
|
|
|
what_does_parent(scene, ob_child, &workob);
|
2008-12-23 19:47:33 +00:00
|
|
|
Mat4Invert(ob_child->parentinv, workob.obmat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void add_hook_menu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= scene->obedit; // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
int mode;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit==NULL) return;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(modifiers_findByType(obedit, eModifierType_Hook))
|
2008-12-23 19:47:33 +00:00
|
|
|
mode= pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
|
|
|
|
else
|
|
|
|
mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
|
|
|
|
|
|
|
|
if(mode<1) return;
|
|
|
|
|
|
|
|
/* do operations */
|
|
|
|
add_hook(scene, v3d, mode);
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("Add hook");
|
|
|
|
}
|
|
|
|
|
2008-12-30 10:37:52 +00:00
|
|
|
void make_track(Scene *scene, View3D *v3d, short mode)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
Base *base;
|
2008-12-30 10:37:52 +00:00
|
|
|
/*short mode=0;*/
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
2009-01-02 19:10:35 +00:00
|
|
|
// XXX if(obedit) {
|
|
|
|
// return;
|
|
|
|
// }
|
2008-12-23 19:47:33 +00:00
|
|
|
if(BASACT==0) return;
|
|
|
|
|
|
|
|
mode= pupmenu("Make Track %t|TrackTo Constraint %x1|LockTrack Constraint %x2|Old Track %x3");
|
|
|
|
if (mode == 0){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (mode == 1){
|
|
|
|
bConstraint *con;
|
|
|
|
bTrackToConstraint *data;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
// XXX con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
|
|
|
|
strcpy (con->name, "AutoTrack");
|
|
|
|
|
|
|
|
data = con->data;
|
|
|
|
data->tar = BASACT->object;
|
|
|
|
base->object->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
/* Lamp and Camera track differently by default */
|
|
|
|
if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
|
|
|
|
data->reserved1 = TRACK_nZ;
|
|
|
|
data->reserved2 = UP_Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX add_constraint_to_object(con, base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (mode == 2){
|
|
|
|
bConstraint *con;
|
|
|
|
bLockTrackConstraint *data;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
// XXX con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
|
|
|
|
strcpy (con->name, "AutoTrack");
|
|
|
|
|
|
|
|
data = con->data;
|
|
|
|
data->tar = BASACT->object;
|
|
|
|
base->object->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
/* Lamp and Camera track differently by default */
|
|
|
|
if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
|
|
|
|
data->trackflag = TRACK_nZ;
|
|
|
|
data->lockflag = LOCK_Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX add_constraint_to_object(con, base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (mode == 3){
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
base->object->track= BASACT->object;
|
|
|
|
base->object->recalc |= OB_RECALC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
BIF_undo_push("Make Track");
|
|
|
|
}
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
/* ******************** clear parent operator ******************* */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
static EnumPropertyItem prop_clear_parent_types[] = {
|
|
|
|
{0, "CLEAR", "Clear Parent", ""},
|
|
|
|
{1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
|
|
|
|
{2, "CLEAR_INVERSE", "Clear Parent Inverse", ""},
|
|
|
|
{0, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* note, poll should check for editable scene */
|
|
|
|
static int clear_parent_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR")) {
|
|
|
|
ob->parent= NULL;
|
|
|
|
}
|
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
|
|
|
|
ob->parent= NULL;
|
|
|
|
ob->track= NULL;
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_apply_obmat(ob);
|
2008-12-24 18:06:51 +00:00
|
|
|
}
|
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_INVERSE")) {
|
|
|
|
Mat4One(ob->parentinv);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2008-12-24 18:06:51 +00:00
|
|
|
ob->recalc |= OB_RECALC;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2008-12-24 18:06:51 +00:00
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
DAG_scene_sort(CTX_data_scene(C));
|
|
|
|
ED_anim_dag_flush_update(C);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-04 02:34:34 +00:00
|
|
|
ED_undo_push(C,"Clear Parent");
|
2008-12-24 18:06:51 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2008-12-26 11:11:21 +00:00
|
|
|
void OBJECT_OT_clear_parent(wmOperatorType *ot)
|
2008-12-24 18:06:51 +00:00
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear parent";
|
2008-12-26 11:11:21 +00:00
|
|
|
ot->idname= "OBJECT_OT_clear_parent";
|
2008-12-24 18:06:51 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->exec= clear_parent_exec;
|
|
|
|
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_object_active;
|
2008-12-24 18:06:51 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
|
|
|
RNA_def_property_enum_items(prop, prop_clear_parent_types);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
2008-12-30 10:37:52 +00:00
|
|
|
/* ******************** clear track operator ******************* */
|
|
|
|
|
|
|
|
|
|
|
|
static EnumPropertyItem prop_clear_track_types[] = {
|
|
|
|
{0, "CLEAR", "Clear Track", ""},
|
|
|
|
{1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
|
|
|
|
{0, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* note, poll should check for editable scene */
|
|
|
|
static int object_clear_track_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2009-01-02 19:10:35 +00:00
|
|
|
if(CTX_data_edit_object(C)) return OPERATOR_CANCELLED;
|
2008-12-30 10:37:52 +00:00
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
|
|
|
/*if(TESTBASELIB(v3d, base)) {*/
|
|
|
|
ob->track= NULL;
|
|
|
|
ob->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_apply_obmat(ob);
|
2008-12-30 10:37:52 +00:00
|
|
|
}
|
|
|
|
/*}*/
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
DAG_scene_sort(CTX_data_scene(C));
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
2009-01-04 02:34:34 +00:00
|
|
|
ED_undo_push(C,"Clear Track");
|
2008-12-30 10:37:52 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_clear_track(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear track";
|
|
|
|
ot->idname= "OBJECT_OT_clear_track";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->exec= object_clear_track_exec;
|
|
|
|
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 10:37:52 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
|
|
|
RNA_def_property_enum_items(prop, prop_clear_track_types);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
/* ***************************** */
|
2008-12-30 03:38:18 +00:00
|
|
|
/* ****** Select by Type ****** */
|
|
|
|
static EnumPropertyItem prop_select_object_types[] = {
|
|
|
|
{OB_EMPTY, "EMPTY", "Empty", ""},
|
|
|
|
{OB_MESH, "MESH", "Mesh", ""},
|
|
|
|
{OB_CURVE, "CURVE", "Curve", ""},
|
|
|
|
{OB_SURF, "SURFACE", "Surface", ""},
|
|
|
|
{OB_FONT, "TEXT", "Text", ""},
|
|
|
|
{OB_MBALL, "META", "Meta", ""},
|
|
|
|
{OB_LAMP, "LAMP", "Lamp", ""},
|
|
|
|
{OB_CAMERA, "CAMERA", "Camera", ""},
|
|
|
|
{OB_LATTICE, "LATTICE", "Lattice", ""},
|
|
|
|
{0, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int object_select_by_type_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
short obtype;
|
|
|
|
|
|
|
|
obtype = RNA_enum_get(op->ptr, "type");
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if(base->object->type==obtype) {
|
|
|
|
ED_base_object_select(base, BA_SELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
/* undo? */
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_select_by_type(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Select By Type";
|
|
|
|
ot->idname= "OBJECT_OT_select_by_type";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->exec= object_select_by_type_exec;
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 03:38:18 +00:00
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
|
|
|
RNA_def_property_enum_items(prop, prop_select_object_types);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ****** selection by layer *******/
|
2008-12-24 18:06:51 +00:00
|
|
|
|
2008-12-30 03:38:18 +00:00
|
|
|
static int object_select_by_layer_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
unsigned int layernum;
|
|
|
|
|
|
|
|
layernum = RNA_int_get(op->ptr, "layer");
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if(base->lay == (1<< (layernum -1)))
|
|
|
|
ED_base_object_select(base, BA_SELECT);
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
/* undo? */
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_select_by_layer(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Selection by layer";
|
|
|
|
ot->idname= "OBJECT_OT_select_by_layer";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
/*ot->invoke = XXX - need a int grid popup*/
|
|
|
|
ot->exec= object_select_by_layer_exec;
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 03:38:18 +00:00
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "layer", PROP_INT, PROP_UNSIGNED);
|
|
|
|
RNA_def_property_ui_range(prop, 1, 20,1, 1);
|
|
|
|
RNA_def_property_ui_text(prop, "layer", "The layer to select objects in");
|
|
|
|
RNA_def_property_int_default(prop, 2);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ****** invert selection *******/
|
|
|
|
static int object_select_invert_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if (base->flag & SELECT)
|
|
|
|
ED_base_object_select(base, BA_DESELECT);
|
|
|
|
else
|
|
|
|
ED_base_object_select(base, BA_SELECT);
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
/* undo? */
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_select_invert(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Invert selection";
|
|
|
|
ot->idname= "OBJECT_OT_select_invert";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= object_select_invert_exec;
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 03:38:18 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
/* ****** (de)select All *******/
|
|
|
|
|
|
|
|
static int object_de_select_all_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2009-01-02 03:16:38 +00:00
|
|
|
|
2008-12-30 03:38:18 +00:00
|
|
|
int a=0, ok=0;
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if (base->flag & SELECT) {
|
|
|
|
ok= a= 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else ok=1;
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
if (!ok) return OPERATOR_PASS_THROUGH;
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if (a) ED_base_object_select(base, BA_DESELECT);
|
|
|
|
else ED_base_object_select(base, BA_SELECT);
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
/* undo? */
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_de_select_all(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "deselect all";
|
|
|
|
ot->idname= "OBJECT_OT_de_select_all";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= object_de_select_all_exec;
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 03:38:18 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
/* ****** random selection *******/
|
|
|
|
|
|
|
|
static int object_select_random_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
int percent;
|
|
|
|
|
|
|
|
percent = RNA_int_get(op->ptr, "percent");
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if ((!base->flag & SELECT && (BLI_frand() * 100) < percent)) {
|
|
|
|
ED_base_object_select(base, BA_SELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
/* undo? */
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_select_random(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Random selection";
|
|
|
|
ot->idname= "OBJECT_OT_select_random";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
/*ot->invoke= object_select_random_invoke XXX - need a number popup ;*/
|
|
|
|
ot->exec = object_select_random_exec;
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 03:38:18 +00:00
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "percent", PROP_INT, PROP_NONE);
|
|
|
|
RNA_def_property_ui_range(prop, 1, 100,1, 1);
|
|
|
|
RNA_def_property_ui_text(prop, "Percent", "Max persentage that will be selected");
|
|
|
|
RNA_def_property_int_default(prop, 50);
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
/* ******** Clear object Translation *********** */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
static int object_clear_location_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
int armature_clear= 0;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
|
|
|
if ((ob->flag & OB_POSEMODE)) {
|
|
|
|
/* only clear pose transforms if:
|
|
|
|
* - with a mesh in weightpaint mode, it's related armature needs to be cleared
|
|
|
|
* - with clearing transform of object being edited at the time
|
|
|
|
*/
|
|
|
|
if ((G.f & G_WEIGHTPAINT) || (ob==OBACT)) {
|
|
|
|
// XXX clear_armature(ob, mode);
|
|
|
|
armature_clear= 1; /* silly system to prevent another dag update, so no action applied */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if((G.f & G_WEIGHTPAINT)==0) {
|
|
|
|
if ((ob->protectflag & OB_LOCK_LOCX)==0)
|
|
|
|
ob->loc[0]= ob->dloc[0]= 0.0f;
|
|
|
|
if ((ob->protectflag & OB_LOCK_LOCY)==0)
|
|
|
|
ob->loc[1]= ob->dloc[1]= 0.0f;
|
|
|
|
if ((ob->protectflag & OB_LOCK_LOCZ)==0)
|
|
|
|
ob->loc[2]= ob->dloc[2]= 0.0f;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-02 09:57:05 +00:00
|
|
|
ob->recalc |= OB_RECALC_OB;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-02 03:16:38 +00:00
|
|
|
CTX_DATA_END;
|
2009-01-02 09:57:05 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
if(armature_clear==0) /* in this case flush was done */
|
|
|
|
ED_anim_dag_flush_update(C);
|
2009-01-04 02:34:34 +00:00
|
|
|
ED_undo_push(C,"Clear Location");
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 09:57:05 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
void OBJECT_OT_clear_location(wmOperatorType *ot)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear Object Location";
|
|
|
|
ot->idname= "OBJECT_OT_clear_location";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_operator_confirm;
|
|
|
|
ot->exec= object_clear_location_exec;
|
|
|
|
ot->poll= ED_operator_object_active;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int object_clear_rotation_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
2008-12-23 19:47:33 +00:00
|
|
|
int armature_clear= 0;
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
|
|
|
if ((ob->flag & OB_POSEMODE)) {
|
|
|
|
/* only clear pose transforms if:
|
|
|
|
* - with a mesh in weightpaint mode, it's related armature needs to be cleared
|
|
|
|
* - with clearing transform of object being edited at the time
|
|
|
|
*/
|
|
|
|
if ((G.f & G_WEIGHTPAINT) || (ob==OBACT)) {
|
|
|
|
// XXX clear_armature(ob, mode);
|
|
|
|
armature_clear= 1; /* silly system to prevent another dag update, so no action applied */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if((G.f & G_WEIGHTPAINT)==0) {
|
2009-01-02 09:57:05 +00:00
|
|
|
/* eulers can only get cleared if they are not protected */
|
|
|
|
if ((ob->protectflag & OB_LOCK_ROTX)==0)
|
|
|
|
ob->rot[0]= ob->drot[0]= 0.0f;
|
|
|
|
if ((ob->protectflag & OB_LOCK_ROTY)==0)
|
|
|
|
ob->rot[1]= ob->drot[1]= 0.0f;
|
|
|
|
if ((ob->protectflag & OB_LOCK_ROTZ)==0)
|
|
|
|
ob->rot[2]= ob->drot[2]= 0.0f;
|
2009-01-02 03:16:38 +00:00
|
|
|
}
|
2009-01-02 09:57:05 +00:00
|
|
|
ob->recalc |= OB_RECALC_OB;
|
2009-01-02 03:16:38 +00:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2009-01-02 09:57:05 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
if(armature_clear==0) /* in this case flush was done */
|
|
|
|
ED_anim_dag_flush_update(C);
|
2009-01-04 02:34:34 +00:00
|
|
|
ED_undo_push(C,"Clear Rotation");
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 09:57:05 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
void OBJECT_OT_clear_rotation(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear Object Rotation";
|
|
|
|
ot->idname= "OBJECT_OT_clear_rotation";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_operator_confirm;
|
|
|
|
ot->exec= object_clear_rotation_exec;
|
|
|
|
ot->poll= ED_operator_object_active;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int object_clear_scale_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
int armature_clear= 0;
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
|
|
|
if ((ob->flag & OB_POSEMODE)) {
|
|
|
|
/* only clear pose transforms if:
|
|
|
|
* - with a mesh in weightpaint mode, it's related armature needs to be cleared
|
|
|
|
* - with clearing transform of object being edited at the time
|
|
|
|
*/
|
|
|
|
if ((G.f & G_WEIGHTPAINT) || (ob==OBACT)) {
|
|
|
|
// XXX clear_armature(ob, mode);
|
|
|
|
armature_clear= 1; /* silly system to prevent another dag update, so no action applied */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if((G.f & G_WEIGHTPAINT)==0) {
|
2009-01-02 09:57:05 +00:00
|
|
|
if ((ob->protectflag & OB_LOCK_SCALEX)==0) {
|
|
|
|
ob->dsize[0]= 0.0f;
|
|
|
|
ob->size[0]= 1.0f;
|
|
|
|
}
|
|
|
|
if ((ob->protectflag & OB_LOCK_SCALEY)==0) {
|
|
|
|
ob->dsize[1]= 0.0f;
|
|
|
|
ob->size[1]= 1.0f;
|
|
|
|
}
|
|
|
|
if ((ob->protectflag & OB_LOCK_SCALEZ)==0) {
|
|
|
|
ob->dsize[2]= 0.0f;
|
|
|
|
ob->size[2]= 1.0f;
|
|
|
|
}
|
2009-01-02 03:16:38 +00:00
|
|
|
}
|
2009-01-02 09:57:05 +00:00
|
|
|
ob->recalc |= OB_RECALC_OB;
|
2009-01-02 03:16:38 +00:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
if(armature_clear==0) /* in this case flush was done */
|
|
|
|
ED_anim_dag_flush_update(C);
|
2009-01-04 02:34:34 +00:00
|
|
|
ED_undo_push(C,"Clear Scale");
|
2009-01-02 03:16:38 +00:00
|
|
|
|
2009-01-02 09:57:05 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, CTX_data_scene(C));
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_clear_scale(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear Object Scale";
|
|
|
|
ot->idname= "OBJECT_OT_clear_scale";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_operator_confirm;
|
|
|
|
ot->exec= object_clear_scale_exec;
|
|
|
|
ot->poll= ED_operator_object_active;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int object_clear_origin_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
float *v1, *v3, mat[3][3];
|
|
|
|
int armature_clear= 0;
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
|
|
|
if ((ob->flag & OB_POSEMODE)) {
|
|
|
|
/* only clear pose transforms if:
|
|
|
|
* - with a mesh in weightpaint mode, it's related armature needs to be cleared
|
|
|
|
* - with clearing transform of object being edited at the time
|
|
|
|
*/
|
|
|
|
if ((G.f & G_WEIGHTPAINT) || (ob==OBACT)) {
|
|
|
|
// XXX clear_armature(ob, mode);
|
|
|
|
armature_clear= 1; /* silly system to prevent another dag update, so no action applied */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if((G.f & G_WEIGHTPAINT)==0) {
|
|
|
|
if(ob->parent) {
|
|
|
|
v1= ob->loc;
|
|
|
|
v3= ob->parentinv[3];
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 03:16:38 +00:00
|
|
|
Mat3CpyMat4(mat, ob->parentinv);
|
|
|
|
VECCOPY(v3, v1);
|
|
|
|
v3[0]= -v3[0];
|
|
|
|
v3[1]= -v3[1];
|
|
|
|
v3[2]= -v3[2];
|
|
|
|
Mat3MulVecfl(mat, v3);
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-02 09:57:05 +00:00
|
|
|
ob->recalc |= OB_RECALC_OB;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-02 03:16:38 +00:00
|
|
|
CTX_DATA_END;
|
2009-01-02 09:57:05 +00:00
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
if(armature_clear==0) /* in this case flush was done */
|
|
|
|
ED_anim_dag_flush_update(C);
|
2009-01-04 02:34:34 +00:00
|
|
|
ED_undo_push(C,"Clear origin");
|
2009-01-02 03:16:38 +00:00
|
|
|
|
2009-01-02 09:57:05 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM, CTX_data_scene(C));
|
2009-01-02 03:16:38 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_clear_origin(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear Object Origin";
|
|
|
|
ot->idname= "OBJECT_OT_clear_origin";
|
|
|
|
|
|
|
|
/* api callbacks */
|
2009-01-04 02:39:22 +00:00
|
|
|
ot->invoke= WM_operator_confirm;
|
2009-01-02 03:16:38 +00:00
|
|
|
ot->exec= object_clear_origin_exec;
|
|
|
|
ot->poll= ED_operator_object_active;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-04 02:34:34 +00:00
|
|
|
|
|
|
|
/* ********* clear/set restrict view *********/
|
|
|
|
static int object_clear_restrictview_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
ScrArea *sa= CTX_wm_area(C);
|
|
|
|
View3D *v3d= sa->spacedata.first;
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
Base *base;
|
|
|
|
int changed = 0;
|
|
|
|
|
|
|
|
/* XXX need a context loop to handle such cases */
|
|
|
|
for(base = FIRSTBASE; base; base=base->next){
|
|
|
|
if((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
|
|
|
|
base->flag |= SELECT;
|
|
|
|
base->object->flag = base->flag;
|
|
|
|
base->object->restrictflag &= ~OB_RESTRICT_VIEW;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (changed) {
|
|
|
|
ED_undo_push(C,"Unhide Objects");
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_clear_restrictview(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear restrict view";
|
|
|
|
ot->idname= "OBJECT_OT_clear_restrictview";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_operator_confirm;
|
|
|
|
ot->exec= object_clear_restrictview_exec;
|
|
|
|
ot->poll= ED_operator_view3d_active;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EnumPropertyItem prop_set_restrictview_types[] = {
|
|
|
|
{0, "SELECTED", "Selected", ""},
|
|
|
|
{1, "UNSELECTED", "Unselected ", ""},
|
|
|
|
{0, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int object_set_restrictview_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
|
|
|
|
short changed = 0, changed_act = 0;
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "SELECTED")){
|
|
|
|
if (base->flag & SELECT){
|
|
|
|
base->flag &= ~SELECT;
|
|
|
|
base->object->flag = base->flag;
|
|
|
|
base->object->restrictflag |= OB_RESTRICT_VIEW;
|
|
|
|
changed = 1;
|
|
|
|
if (base==BASACT) {
|
|
|
|
BASACT= NULL;
|
|
|
|
changed_act = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (RNA_enum_is_equal(op->ptr, "type", "UNSELECTED")){
|
|
|
|
if (!(base->flag & SELECT)){
|
|
|
|
base->object->restrictflag |= OB_RESTRICT_VIEW;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "SELECTED")) ED_undo_push(C,"Hide Selected Objects");
|
|
|
|
else if(RNA_enum_is_equal(op->ptr, "type", "UNSELECTED")) ED_undo_push(C,"Hide Unselected Objects");
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
|
|
|
|
|
|
|
if (changed_act) { /* these spaces depend on the active object */
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, CTX_data_scene(C));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_set_restrictview(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Set restrict view";
|
|
|
|
ot->idname= "OBJECT_OT_set_restrictview";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->exec= object_set_restrictview_exec;
|
|
|
|
ot->poll= ED_operator_view3d_active;
|
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
|
|
|
RNA_def_property_enum_items(prop, prop_set_restrictview_types);
|
|
|
|
|
|
|
|
}
|
2009-01-08 02:50:37 +00:00
|
|
|
/* ************* Slow Parent ******************* */
|
|
|
|
static int object_set_slowparent_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
|
|
|
|
|
|
|
if(base->object->parent) base->object->partype |= PARSLOW;
|
|
|
|
base->object->recalc |= OB_RECALC_OB;
|
|
|
|
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
ED_undo_push(C,"Set Slow Parent");
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-08 02:50:37 +00:00
|
|
|
void OBJECT_OT_set_slowparent(wmOperatorType *ot)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
2009-01-08 02:50:37 +00:00
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Set Slow Parent";
|
|
|
|
ot->idname= "OBJECT_OT_set_slow_parent";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_operator_confirm;
|
|
|
|
ot->exec= object_set_slowparent_exec;
|
|
|
|
ot->poll= ED_operator_view3d_active;
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-08 02:50:37 +00:00
|
|
|
static int object_clear_slowparent_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, visible_bases) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if(base->object->parent) {
|
|
|
|
if(base->object->partype & PARSLOW) {
|
|
|
|
base->object->partype -= PARSLOW;
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, base->object);
|
2008-12-23 19:47:33 +00:00
|
|
|
base->object->partype |= PARSLOW;
|
2009-01-08 02:50:37 +00:00
|
|
|
base->object->recalc |= OB_RECALC_OB;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-08 02:50:37 +00:00
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-08 02:50:37 +00:00
|
|
|
CTX_DATA_END;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-08 02:50:37 +00:00
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
ED_undo_push(C,"Clear Slow Parent");
|
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE, CTX_data_scene(C));
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-08 02:50:37 +00:00
|
|
|
void OBJECT_OT_clear_slowparent(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Clear Slow Parent";
|
|
|
|
ot->idname= "OBJECT_OT_clear_slow_parent";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_operator_confirm;
|
|
|
|
ot->exec= object_clear_slowparent_exec;
|
|
|
|
ot->poll= ED_operator_view3d_active;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-08 02:50:37 +00:00
|
|
|
/* ******************** **************** */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
// XXX
|
|
|
|
#define BEZSELECTED_HIDDENHANDLES(bezt) ((G.f & G_HIDDENHANDLES) ? (bezt)->f2 & SELECT : BEZSELECTED(bezt))
|
2008-12-31 17:11:42 +00:00
|
|
|
/* only in edit mode */
|
2009-01-02 19:10:35 +00:00
|
|
|
void make_vertex_parent(Scene *scene, Object *obedit, View3D *v3d)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
EditVert *eve;
|
|
|
|
Base *base;
|
|
|
|
Nurb *nu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
BPoint *bp;
|
|
|
|
Object *par, *ob;
|
|
|
|
int a, v1=0, v2=0, v3=0, v4=0, nr=1;
|
|
|
|
|
|
|
|
/* we need 1 to 3 selected vertices */
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit->type==OB_MESH) {
|
|
|
|
Mesh *me= obedit->data;
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
eve= me->edit_mesh->verts.first;
|
2008-12-23 19:47:33 +00:00
|
|
|
while(eve) {
|
|
|
|
if(eve->f & 1) {
|
|
|
|
if(v1==0) v1= nr;
|
|
|
|
else if(v2==0) v2= nr;
|
|
|
|
else if(v3==0) v3= nr;
|
|
|
|
else if(v4==0) v4= nr;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
eve= eve->next;
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) {
|
2008-12-23 19:47:33 +00:00
|
|
|
extern ListBase editNurb;
|
|
|
|
nu= editNurb.first;
|
|
|
|
while(nu) {
|
|
|
|
if((nu->type & 7)==CU_BEZIER) {
|
|
|
|
bezt= nu->bezt;
|
|
|
|
a= nu->pntsu;
|
|
|
|
while(a--) {
|
|
|
|
if(BEZSELECTED_HIDDENHANDLES(bezt)) {
|
|
|
|
if(v1==0) v1= nr;
|
|
|
|
else if(v2==0) v2= nr;
|
|
|
|
else if(v3==0) v3= nr;
|
|
|
|
else if(v4==0) v4= nr;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bp= nu->bp;
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT) {
|
|
|
|
if(v1==0) v1= nr;
|
|
|
|
else if(v2==0) v2= nr;
|
|
|
|
else if(v3==0) v3= nr;
|
|
|
|
else if(v4==0) v4= nr;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_LATTICE) {
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
bp= editLatt->def;
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT) {
|
|
|
|
if(v1==0) v1= nr;
|
|
|
|
else if(v2==0) v2= nr;
|
|
|
|
else if(v3==0) v3= nr;
|
|
|
|
else if(v4==0) v4= nr;
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
nr++;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(v4 || !((v1 && v2==0 && v3==0) || (v1 && v2 && v3)) ) {
|
|
|
|
error("Select either 1 or 3 vertices to parent to");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(okee("Make vertex parent")==0) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
|
|
|
|
ob= base->object;
|
|
|
|
ob->recalc |= OB_RECALC;
|
|
|
|
par= BASACT->object->parent;
|
|
|
|
|
|
|
|
while(par) {
|
|
|
|
if(par==ob) break;
|
|
|
|
par= par->parent;
|
|
|
|
}
|
|
|
|
if(par) {
|
|
|
|
error("Loop in parents");
|
|
|
|
}
|
|
|
|
else {
|
2008-12-24 11:08:15 +00:00
|
|
|
Object workob;
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
ob->parent= BASACT->object;
|
|
|
|
if(v3) {
|
|
|
|
ob->partype= PARVERT3;
|
|
|
|
ob->par1= v1-1;
|
|
|
|
ob->par2= v2-1;
|
|
|
|
ob->par3= v3-1;
|
|
|
|
|
|
|
|
/* inverse parent matrix */
|
2009-01-04 14:14:06 +00:00
|
|
|
what_does_parent(scene, ob, &workob);
|
2008-12-23 19:47:33 +00:00
|
|
|
Mat4Invert(ob->parentinv, workob.obmat);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ob->partype= PARVERT1;
|
|
|
|
ob->par1= v1-1;
|
|
|
|
|
|
|
|
/* inverse parent matrix */
|
2009-01-04 14:14:06 +00:00
|
|
|
what_does_parent(scene, ob, &workob);
|
2008-12-23 19:47:33 +00:00
|
|
|
Mat4Invert(ob->parentinv, workob.obmat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
/* BIF_undo_push(str); not, conflicts with editmode undo... */
|
|
|
|
}
|
|
|
|
|
|
|
|
static Object *group_objects_menu(Group *group)
|
|
|
|
{
|
|
|
|
GroupObject *go;
|
|
|
|
int len= 0;
|
|
|
|
short a, nr;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
for(go= group->gobject.first; go; go= go->next) {
|
|
|
|
if(go->ob)
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
if(len==0) return NULL;
|
|
|
|
|
|
|
|
str= MEM_callocN(40+32*len, "menu");
|
|
|
|
|
|
|
|
strcpy(str, "Make Proxy for: %t");
|
|
|
|
a= strlen(str);
|
|
|
|
for(nr=1, go= group->gobject.first; go; go= go->next, nr++) {
|
|
|
|
a+= sprintf(str+a, "|%s %%x%d", go->ob->id.name+2, nr);
|
|
|
|
}
|
|
|
|
|
|
|
|
a= pupmenu_col(str, 20);
|
|
|
|
MEM_freeN(str);
|
|
|
|
if(a>0) {
|
|
|
|
go= BLI_findlink(&group->gobject, a-1);
|
|
|
|
return go->ob;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* adds empty object to become local replacement data of a library-linked object */
|
|
|
|
void make_proxy(Scene *scene)
|
|
|
|
{
|
|
|
|
Object *ob= OBACT;
|
|
|
|
Object *gob= NULL;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
if(ob==NULL) return;
|
|
|
|
|
|
|
|
|
|
|
|
if(ob->dup_group && ob->dup_group->id.lib) {
|
|
|
|
gob= ob;
|
|
|
|
/* gives menu with list of objects in group */
|
|
|
|
ob= group_objects_menu(ob->dup_group);
|
|
|
|
}
|
|
|
|
else if(ob->id.lib) {
|
|
|
|
if(okee("Make Proxy Object")==0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
error("Can only make proxy for a referenced object or group");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ob) {
|
|
|
|
Object *newob;
|
|
|
|
Base *newbase, *oldbase= BASACT;
|
|
|
|
char name[32];
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
newob= add_object(scene, OB_EMPTY);
|
2008-12-23 19:47:33 +00:00
|
|
|
if(gob)
|
|
|
|
strcpy(name, gob->id.name+2);
|
|
|
|
else
|
|
|
|
strcpy(name, ob->id.name+2);
|
|
|
|
strcat(name, "_proxy");
|
|
|
|
rename_id(&newob->id, name);
|
|
|
|
|
|
|
|
/* set layers OK */
|
|
|
|
newbase= BASACT; /* add_object sets active... */
|
|
|
|
newbase->lay= oldbase->lay;
|
|
|
|
newob->lay= newbase->lay;
|
|
|
|
|
|
|
|
/* remove base, leave user count of object, it gets linked in object_make_proxy */
|
|
|
|
if(gob==NULL) {
|
|
|
|
BLI_remlink(&scene->base, oldbase);
|
|
|
|
MEM_freeN(oldbase);
|
|
|
|
}
|
|
|
|
object_make_proxy(newob, ob, gob);
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
DAG_object_flush_update(scene, newob, OB_RECALC);
|
|
|
|
allqueue(REDRAWALL, 0);
|
|
|
|
BIF_undo_push("Make Proxy Object");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************** make parent operator *********************** */
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
oldcode()
|
|
|
|
{
|
|
|
|
else if(mode==4) {
|
2008-12-24 18:06:51 +00:00
|
|
|
bConstraint *con;
|
|
|
|
bFollowPathConstraint *data;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
float cmat[4][4], vec[3];
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
|
2008-12-24 18:06:51 +00:00
|
|
|
strcpy (con->name, "AutoPath");
|
|
|
|
|
|
|
|
data = con->data;
|
|
|
|
data->tar = BASACT->object;
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX add_constraint_to_object(con, base->object);
|
2008-12-24 18:06:51 +00:00
|
|
|
|
|
|
|
get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(base->object));
|
|
|
|
VecSubf(vec, base->object->obmat[3], cmat[3]);
|
|
|
|
|
|
|
|
base->object->loc[0] = vec[0];
|
|
|
|
base->object->loc[1] = vec[1];
|
|
|
|
base->object->loc[2] = vec[2];
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
2008-12-24 18:06:51 +00:00
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
if(mode==PARSKEL && base->object->type==OB_MESH && par->type == OB_ARMATURE) {
|
|
|
|
/* Prompt the user as to whether he wants to
|
|
|
|
* add some vertex groups based on the bones
|
|
|
|
* in the parent armature.
|
|
|
|
*/
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX create_vgroups_from_armature(base->object, par);
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
base->object->partype= PAROBJECT;
|
2009-01-04 14:14:06 +00:00
|
|
|
what_does_parent(scene, base->object);
|
2008-12-24 18:06:51 +00:00
|
|
|
Mat4One (base->object->parentinv);
|
|
|
|
base->object->partype= mode;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2008-12-24 18:06:51 +00:00
|
|
|
else
|
2009-01-04 14:14:06 +00:00
|
|
|
what_does_parent(scene, base->object, &workob);
|
2008-12-24 18:06:51 +00:00
|
|
|
Mat4Invert(base->object->parentinv, workob.obmat);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define PAR_OBJECT 0
|
|
|
|
#define PAR_ARMATURE 1
|
|
|
|
#define PAR_BONE 2
|
|
|
|
#define PAR_CURVE 3
|
|
|
|
#define PAR_FOLLOW 4
|
|
|
|
#define PAR_PATH_CONST 5
|
|
|
|
#define PAR_LATTICE 6
|
|
|
|
#define PAR_VERTEX 7
|
|
|
|
#define PAR_TRIA 8
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
static EnumPropertyItem prop_make_parent_types[] = {
|
2008-12-23 19:47:33 +00:00
|
|
|
{PAR_OBJECT, "OBJECT", "Object", ""},
|
|
|
|
{PAR_ARMATURE, "ARMATURE", "Armature Deform", ""},
|
|
|
|
{PAR_BONE, "BONE", "Bone", ""},
|
|
|
|
{PAR_CURVE, "CURVE", "Curve Deform", ""},
|
|
|
|
{PAR_FOLLOW, "FOLLOW", "Follow Path", ""},
|
|
|
|
{PAR_PATH_CONST, "PATH_CONST", "Path Constraint", ""},
|
|
|
|
{PAR_LATTICE, "LATTICE", "Lattice Deform", ""},
|
|
|
|
{PAR_VERTEX, "VERTEX", "Vertex", ""},
|
|
|
|
{PAR_TRIA, "TRIA", "Triangle", ""},
|
|
|
|
{0, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int test_parent_loop(Object *par, Object *ob)
|
|
|
|
{
|
|
|
|
/* test if 'ob' is a parent somewhere in par's parents */
|
|
|
|
|
|
|
|
if(par == NULL) return 0;
|
|
|
|
if(ob == par) return 1;
|
|
|
|
|
|
|
|
return test_parent_loop(par->parent, ob);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int make_parent_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2009-01-04 14:14:06 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2008-12-23 19:47:33 +00:00
|
|
|
Object *par= CTX_data_active_object(C);
|
|
|
|
bPoseChannel *pchan= NULL;
|
2008-12-24 18:06:51 +00:00
|
|
|
int partype= RNA_enum_get(op->ptr, "type");
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
par->recalc |= OB_RECALC_OB;
|
|
|
|
|
|
|
|
/* preconditions */
|
|
|
|
if(partype==PAR_FOLLOW || partype==PAR_PATH_CONST) {
|
|
|
|
if(par->type!=OB_CURVE)
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
else {
|
|
|
|
Curve *cu= par->data;
|
|
|
|
|
|
|
|
if((cu->flag & CU_PATH)==0) {
|
|
|
|
cu->flag |= CU_PATH|CU_FOLLOW;
|
2009-01-04 14:14:06 +00:00
|
|
|
makeDispListCurveTypes(scene, par, 0); /* force creation of path data */
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
else cu->flag |= CU_FOLLOW;
|
|
|
|
|
|
|
|
/* fall back on regular parenting now */
|
|
|
|
partype= PAR_OBJECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(partype==PAR_BONE) {
|
|
|
|
pchan= get_active_posechannel(par);
|
|
|
|
|
|
|
|
if(pchan==NULL) {
|
|
|
|
error("No active Bone");
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* context itterator */
|
|
|
|
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
|
|
|
|
|
|
|
if(ob!=par) {
|
|
|
|
|
|
|
|
if( test_parent_loop(par, ob) ) {
|
|
|
|
error("Loop in parents");
|
|
|
|
}
|
|
|
|
else {
|
2008-12-24 11:08:15 +00:00
|
|
|
Object workob;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* apply transformation of previous parenting */
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_apply_obmat(ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
ob->parent= par;
|
|
|
|
|
|
|
|
/* handle types */
|
|
|
|
if (pchan)
|
|
|
|
strcpy (ob->parsubstr, pchan->name);
|
|
|
|
else
|
|
|
|
ob->parsubstr[0]= 0;
|
|
|
|
|
|
|
|
/* constraint XXX */
|
|
|
|
if(partype==PAR_PATH_CONST) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate inverse parent matrix */
|
2009-01-04 14:14:06 +00:00
|
|
|
what_does_parent(scene, ob, &workob);
|
2008-12-23 19:47:33 +00:00
|
|
|
Mat4Invert(ob->parentinv, workob.obmat);
|
|
|
|
|
|
|
|
ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
|
|
|
|
|
|
|
|
if( ELEM3(partype, PAR_CURVE, PAR_ARMATURE, PAR_LATTICE) )
|
|
|
|
ob->partype= PARSKEL; /* note, dna define, not operator property */
|
|
|
|
else
|
|
|
|
ob->partype= PAROBJECT; /* note, dna define, not operator property */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
DAG_scene_sort(CTX_data_scene(C));
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
|
|
|
BIF_undo_push("make Parent");
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int make_parent_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
{
|
|
|
|
Object *ob= CTX_data_active_object(C);
|
|
|
|
char *str, string[256];
|
|
|
|
char formatstr[] = "|%s %%x%d";
|
|
|
|
|
|
|
|
str= string + sprintf(string, "Make Parent To %%t");
|
|
|
|
|
|
|
|
/* ob becomes parent, make the associated menus */
|
|
|
|
if(ob->type==OB_ARMATURE) {
|
|
|
|
str += sprintf(str, formatstr, "Object", PAR_OBJECT);
|
|
|
|
str += sprintf(str, formatstr, "Armature Deform", PAR_ARMATURE);
|
|
|
|
str += sprintf(str, formatstr, "Bone", PAR_BONE);
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_CURVE) {
|
|
|
|
str += sprintf(str, formatstr, "Object", PAR_OBJECT);
|
|
|
|
str += sprintf(str, formatstr, "Curve Deform", PAR_CURVE);
|
|
|
|
str += sprintf(str, formatstr, "Follow Path", PAR_FOLLOW);
|
|
|
|
str += sprintf(str, formatstr, "Path Constraint", PAR_PATH_CONST);
|
|
|
|
}
|
|
|
|
else if(ob->type == OB_LATTICE) {
|
|
|
|
str += sprintf(str, formatstr, "Object", PAR_OBJECT);
|
|
|
|
str += sprintf(str, formatstr, "Lattice Deform", PAR_LATTICE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
str += sprintf(str, formatstr, "Object", PAR_OBJECT);
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
uiPupmenuOperator(C, 0, op, "type", string);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-26 11:11:21 +00:00
|
|
|
void OBJECT_OT_make_parent(wmOperatorType *ot)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Make parent";
|
2008-12-26 11:11:21 +00:00
|
|
|
ot->idname= "OBJECT_OT_make_parent";
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= make_parent_invoke;
|
|
|
|
ot->exec= make_parent_exec;
|
|
|
|
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_object_active;
|
2008-12-23 19:47:33 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER;
|
|
|
|
|
2008-12-24 18:06:51 +00:00
|
|
|
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
|
|
|
RNA_def_property_enum_items(prop, prop_make_parent_types);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
2008-12-30 10:37:52 +00:00
|
|
|
/* *** make track ***** */
|
|
|
|
static EnumPropertyItem prop_make_track_types[] = {
|
|
|
|
{1, "TRACKTO", "TrackTo Constraint", ""},
|
|
|
|
{2, "LOCKTRACK", "LockTrack Constraint", ""},
|
|
|
|
{3, "OLDTRACK", "Old Track", ""},
|
|
|
|
{0, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static int make_track_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
ScrArea *sa= CTX_wm_area(C);
|
|
|
|
View3D *v3d= sa->spacedata.first;
|
|
|
|
Base *base;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
if(scene->id.lib) return OPERATOR_CANCELLED;
|
2008-12-30 10:37:52 +00:00
|
|
|
|
|
|
|
if(RNA_enum_is_equal(op->ptr, "type", "TRACKTO")){
|
|
|
|
bConstraint *con;
|
|
|
|
bTrackToConstraint *data;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
// XXX con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
|
|
|
|
strcpy (con->name, "AutoTrack");
|
|
|
|
|
|
|
|
data = con->data;
|
|
|
|
data->tar = BASACT->object;
|
|
|
|
base->object->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
/* Lamp and Camera track differently by default */
|
|
|
|
if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
|
|
|
|
data->reserved1 = TRACK_nZ;
|
|
|
|
data->reserved2 = UP_Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX add_constraint_to_object(con, base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(RNA_enum_is_equal(op->ptr, "type", "LOCKTRACK")){
|
|
|
|
bConstraint *con;
|
|
|
|
bLockTrackConstraint *data;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
// XXX con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
|
|
|
|
strcpy (con->name, "AutoTrack");
|
|
|
|
|
|
|
|
data = con->data;
|
|
|
|
data->tar = BASACT->object;
|
|
|
|
base->object->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
/* Lamp and Camera track differently by default */
|
|
|
|
if (base->object->type == OB_LAMP || base->object->type == OB_CAMERA) {
|
|
|
|
data->trackflag = TRACK_nZ;
|
|
|
|
data->lockflag = LOCK_Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX add_constraint_to_object(con, base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(RNA_enum_is_equal(op->ptr, "type", "OLDTRACK")){
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base!=BASACT) {
|
|
|
|
base->object->track= BASACT->object;
|
|
|
|
base->object->recalc |= OB_RECALC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DAG_scene_sort(CTX_data_scene(C));
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
|
|
|
BIF_undo_push("make track");
|
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OBJECT_OT_make_track(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Make Track";
|
|
|
|
ot->idname= "OBJECT_OT_make_track";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_menu_invoke;
|
|
|
|
ot->exec= make_track_exec;
|
|
|
|
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_scene_editable;
|
2008-12-30 10:37:52 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER;
|
|
|
|
|
|
|
|
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
|
|
|
RNA_def_property_enum_items(prop, prop_make_track_types);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
/* ******************* toggle editmode operator ***************** */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
void ED_object_exit_editmode(bContext *C, int flag)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
2008-12-31 17:11:42 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2008-12-23 19:47:33 +00:00
|
|
|
Object *ob;
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= CTX_data_edit_object(C);
|
2009-01-01 18:05:12 +00:00
|
|
|
int freedata = flag & EM_FREEDATA;
|
2008-12-31 17:11:42 +00:00
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit==NULL) return;
|
2008-12-31 17:11:42 +00:00
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
if(flag & EM_WAITCURSOR) waitcursor(1);
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit->type==OB_MESH) {
|
|
|
|
Mesh *me= obedit->data;
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
// if(EM_texFaceCheck())
|
|
|
|
|
|
|
|
// if(retopo_mesh_paint_check())
|
|
|
|
// retopo_end_okee();
|
|
|
|
|
|
|
|
if(G.totvert>MESH_MAX_VERTS) {
|
|
|
|
error("Too many vertices");
|
|
|
|
return;
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
load_editMesh(scene, obedit);
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
if(freedata) free_editMesh(me->edit_mesh);
|
|
|
|
|
|
|
|
if(G.f & G_WEIGHTPAINT)
|
2009-01-02 19:10:35 +00:00
|
|
|
mesh_octree_table(obedit, NULL, NULL, 'e');
|
2008-12-31 17:11:42 +00:00
|
|
|
}
|
2009-01-05 19:32:04 +00:00
|
|
|
else if (obedit->type==OB_ARMATURE) {
|
|
|
|
ED_armature_from_edit(scene, obedit);
|
|
|
|
if(freedata)
|
|
|
|
ED_armature_edit_free(obedit);
|
2008-12-31 17:11:42 +00:00
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
|
2008-12-31 17:11:42 +00:00
|
|
|
// extern ListBase editNurb;
|
|
|
|
// load_editNurb();
|
|
|
|
// if(freedata) freeNurblist(&editNurb);
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_FONT && freedata) {
|
2008-12-31 17:11:42 +00:00
|
|
|
// load_editText();
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_LATTICE) {
|
2008-12-31 17:11:42 +00:00
|
|
|
// load_editLatt();
|
|
|
|
// if(freedata) free_editLatt();
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_MBALL) {
|
2008-12-31 17:11:42 +00:00
|
|
|
// extern ListBase editelems;
|
|
|
|
// load_editMball();
|
|
|
|
// if(freedata) BLI_freelistN(&editelems);
|
|
|
|
}
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
ob= obedit;
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
/* for example; displist make is different in editmode */
|
2009-01-02 19:10:35 +00:00
|
|
|
if(freedata) obedit= NULL;
|
|
|
|
scene->obedit= obedit; // XXX for context
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
/* also flush ob recalc, doesn't take much overhead, but used for particles */
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit==NULL) // XXX && (flag & EM_FREEUNDO))
|
2008-12-31 17:11:42 +00:00
|
|
|
ED_undo_push(C, "Editmode");
|
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
if(flag & EM_WAITCURSOR) waitcursor(0);
|
2008-12-31 17:11:42 +00:00
|
|
|
|
2009-01-01 13:15:35 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, ob);
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
void ED_object_enter_editmode(bContext *C, int flag)
|
2008-12-31 17:11:42 +00:00
|
|
|
{
|
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
Base *base= CTX_data_active_base(C);
|
|
|
|
Object *ob= base->object;
|
2009-01-05 19:32:04 +00:00
|
|
|
ScrArea *sa= CTX_wm_area(C);
|
|
|
|
View3D *v3d= NULL;
|
2008-12-23 19:47:33 +00:00
|
|
|
int ok= 0;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
2008-12-31 17:11:42 +00:00
|
|
|
if(base==NULL) return;
|
2009-01-05 19:32:04 +00:00
|
|
|
|
|
|
|
if(sa->spacetype==SPACE_VIEW3D)
|
|
|
|
v3d= sa->spacedata.first;
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
if((v3d==NULL || (base->lay & v3d->lay))==0) return;
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
if(ob->data==NULL) return;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if (object_data_is_libdata(ob)) {
|
|
|
|
error_libdata();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
if(flag & EM_WAITCURSOR) waitcursor(1);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(ob->type==OB_MESH) {
|
2008-12-31 17:11:42 +00:00
|
|
|
Mesh *me= ob->data;
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
if(me->pv) mesh_pmv_off(ob, me);
|
|
|
|
ok= 1;
|
2008-12-31 17:11:42 +00:00
|
|
|
scene->obedit= ob; // context sees this
|
|
|
|
|
|
|
|
make_editMesh(scene, ob);
|
|
|
|
|
2009-01-01 13:15:35 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_MESH, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-05 19:32:04 +00:00
|
|
|
else if (ob->type==OB_ARMATURE){
|
2008-12-31 17:11:42 +00:00
|
|
|
bArmature *arm= base->object->data;
|
2008-12-23 19:47:33 +00:00
|
|
|
if (!arm) return;
|
|
|
|
/*
|
|
|
|
* The function object_data_is_libdata make a problem here, the
|
|
|
|
* check for ob->proxy return 0 and let blender enter to edit mode
|
|
|
|
* this causa a crash when you try leave the edit mode.
|
|
|
|
* The problem is that i can't remove the ob->proxy check from
|
|
|
|
* object_data_is_libdata that prevent the bugfix #6614, so
|
|
|
|
* i add this little hack here.
|
|
|
|
*/
|
|
|
|
if(arm->id.lib) {
|
|
|
|
error_libdata();
|
|
|
|
return;
|
|
|
|
}
|
2009-01-05 19:32:04 +00:00
|
|
|
ok=1;
|
2009-01-02 19:10:35 +00:00
|
|
|
scene->obedit= ob;
|
2009-01-05 19:32:04 +00:00
|
|
|
ED_armature_to_edit(ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
/* to ensure all goes in restposition and without striding */
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-01 13:15:35 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_EDITMODE_ARMATURE, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
else if(ob->type==OB_FONT) {
|
2009-01-02 19:10:35 +00:00
|
|
|
scene->obedit= ob; // XXX for context
|
|
|
|
// ok= 1;
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX make_editText();
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_MBALL) {
|
2009-01-02 19:10:35 +00:00
|
|
|
scene->obedit= ob; // XXX for context
|
|
|
|
// ok= 1;
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX make_editMball();
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_LATTICE) {
|
2009-01-02 19:10:35 +00:00
|
|
|
scene->obedit= ob; // XXX for context
|
|
|
|
// ok= 1;
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX make_editLatt();
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_SURF || ob->type==OB_CURVE) {
|
2009-01-02 19:10:35 +00:00
|
|
|
// ok= 1;
|
|
|
|
scene->obedit= ob; // XXX for context
|
2008-12-23 19:47:33 +00:00
|
|
|
// XXX make_editNurb();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ok) {
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-01 13:15:35 +00:00
|
|
|
else {
|
2009-01-02 19:10:35 +00:00
|
|
|
scene->obedit= NULL; // XXX for context
|
2009-01-01 13:15:35 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, ob);
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
if(flag & EM_WAITCURSOR) waitcursor(0);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
static int toggle_editmode_exec(bContext *C, wmOperator *op)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
if(!CTX_data_edit_object(C))
|
2009-01-01 18:05:12 +00:00
|
|
|
ED_object_enter_editmode(C, EM_WAITCURSOR);
|
2008-12-31 17:11:42 +00:00
|
|
|
else
|
2009-01-01 18:05:12 +00:00
|
|
|
ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
void OBJECT_OT_toggle_editmode(wmOperatorType *ot)
|
|
|
|
{
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Toggle Editmode";
|
|
|
|
ot->idname= "OBJECT_OT_toggle_editmode";
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
/* api callbacks */
|
|
|
|
ot->exec= toggle_editmode_exec;
|
|
|
|
|
2009-01-01 14:57:04 +00:00
|
|
|
ot->poll= ED_operator_object_active;
|
2008-12-31 17:11:42 +00:00
|
|
|
ot->flag= OPTYPE_REGISTER;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
/* *************************** */
|
|
|
|
|
|
|
|
|
2008-12-23 19:47:33 +00:00
|
|
|
void check_editmode(int type)
|
|
|
|
{
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= NULL; // XXX
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if (obedit==NULL || obedit->type==type) return;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_FREEUNDO|EM_WAITCURSOR); /* freedata, and undo */
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 0 == do center, 1 == center new, 2 == center cursor */
|
|
|
|
|
|
|
|
void docenter(Scene *scene, View3D *v3d, int centermode)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me, *tme;
|
|
|
|
Curve *cu;
|
|
|
|
/* BezTriple *bezt;
|
|
|
|
BPoint *bp; */
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= NULL; // XXX
|
2008-12-23 19:47:33 +00:00
|
|
|
Nurb *nu, *nu1;
|
|
|
|
EditVert *eve;
|
|
|
|
float cent[3], centn[3], min[3], max[3], omat[3][3];
|
|
|
|
int a, total= 0;
|
|
|
|
|
|
|
|
/* keep track of what is changed */
|
|
|
|
int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0;
|
|
|
|
MVert *mvert;
|
|
|
|
|
|
|
|
if(scene->id.lib || v3d==NULL) return;
|
|
|
|
|
|
|
|
cent[0]= cent[1]= cent[2]= 0.0;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit) {
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit->type==OB_MESH) {
|
|
|
|
Mesh *me= obedit->data;
|
2008-12-31 17:11:42 +00:00
|
|
|
|
|
|
|
for(eve= me->edit_mesh->verts.first; eve; eve= eve->next) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if(v3d->around==V3D_CENTROID) {
|
|
|
|
total++;
|
|
|
|
VECADD(cent, cent, eve->co);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DO_MINMAX(eve->co, min, max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(v3d->around==V3D_CENTROID) {
|
|
|
|
VecMulf(cent, 1.0f/(float)total);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cent[0]= (min[0]+max[0])/2.0f;
|
|
|
|
cent[1]= (min[1]+max[1])/2.0f;
|
|
|
|
cent[2]= (min[2]+max[2])/2.0f;
|
|
|
|
}
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
for(eve= me->edit_mesh->verts.first; eve; eve= eve->next) {
|
2008-12-23 19:47:33 +00:00
|
|
|
VecSubf(eve->co, eve->co, cent);
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX recalc_editnormals();
|
|
|
|
tot_change++;
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* reset flags */
|
|
|
|
for (base=FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base))
|
|
|
|
base->object->flag &= ~OB_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (me= G.main->mesh.first; me; me= me->id.next) {
|
|
|
|
me->flag &= ~ME_ISDONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if((base->object->flag & OB_DONE)==0) {
|
|
|
|
base->object->flag |= OB_DONE;
|
|
|
|
|
|
|
|
if(base->object->id.lib) {
|
|
|
|
tot_lib_error++;
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit==0 && (me=get_mesh(base->object)) ) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if (me->id.lib) {
|
|
|
|
tot_lib_error++;
|
|
|
|
} else {
|
|
|
|
if(centermode==2) {
|
|
|
|
VECCOPY(cent, give_cursor(scene, v3d));
|
|
|
|
Mat4Invert(base->object->imat, base->object->obmat);
|
|
|
|
Mat4MulVecfl(base->object->imat, cent);
|
|
|
|
} else {
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
mvert= me->mvert;
|
|
|
|
for(a=0; a<me->totvert; a++, mvert++) {
|
|
|
|
DO_MINMAX(mvert->co, min, max);
|
|
|
|
}
|
|
|
|
|
|
|
|
cent[0]= (min[0]+max[0])/2.0f;
|
|
|
|
cent[1]= (min[1]+max[1])/2.0f;
|
|
|
|
cent[2]= (min[2]+max[2])/2.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
mvert= me->mvert;
|
|
|
|
for(a=0; a<me->totvert; a++, mvert++) {
|
|
|
|
VecSubf(mvert->co, mvert->co, cent);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (me->key) {
|
|
|
|
KeyBlock *kb;
|
|
|
|
for (kb=me->key->block.first; kb; kb=kb->next) {
|
|
|
|
float *fp= kb->data;
|
|
|
|
|
|
|
|
for (a=0; a<kb->totelem; a++, fp+=3) {
|
|
|
|
VecSubf(fp, fp, cent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
me->flag |= ME_ISDONE;
|
|
|
|
|
|
|
|
if(centermode) {
|
|
|
|
Mat3CpyMat4(omat, base->object->obmat);
|
|
|
|
|
|
|
|
VECCOPY(centn, cent);
|
|
|
|
Mat3MulVecfl(omat, centn);
|
|
|
|
base->object->loc[0]+= centn[0];
|
|
|
|
base->object->loc[1]+= centn[1];
|
|
|
|
base->object->loc[2]+= centn[2];
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, base->object);
|
|
|
|
ignore_parent_tx(scene, base->object);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* other users? */
|
|
|
|
ob= G.main->object.first;
|
|
|
|
while(ob) {
|
|
|
|
if((ob->flag & OB_DONE)==0) {
|
|
|
|
tme= get_mesh(ob);
|
|
|
|
|
|
|
|
if(tme==me) {
|
|
|
|
|
|
|
|
ob->flag |= OB_DONE;
|
|
|
|
ob->recalc= OB_RECALC_OB|OB_RECALC_DATA;
|
|
|
|
|
|
|
|
Mat3CpyMat4(omat, ob->obmat);
|
|
|
|
VECCOPY(centn, cent);
|
|
|
|
Mat3MulVecfl(omat, centn);
|
|
|
|
ob->loc[0]+= centn[0];
|
|
|
|
ob->loc[1]+= centn[1];
|
|
|
|
ob->loc[2]+= centn[2];
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
|
|
|
ignore_parent_tx(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(tme && (tme->flag & ME_ISDONE)==0) {
|
|
|
|
mvert= tme->mvert;
|
|
|
|
for(a=0; a<tme->totvert; a++, mvert++) {
|
|
|
|
VecSubf(mvert->co, mvert->co, cent);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tme->key) {
|
|
|
|
KeyBlock *kb;
|
|
|
|
for (kb=tme->key->block.first; kb; kb=kb->next) {
|
|
|
|
float *fp= kb->data;
|
|
|
|
|
|
|
|
for (a=0; a<kb->totelem; a++, fp+=3) {
|
|
|
|
VecSubf(fp, fp, cent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tme->flag |= ME_ISDONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ob= ob->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tot_change++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ELEM(base->object->type, OB_CURVE, OB_SURF)) {
|
|
|
|
|
|
|
|
/* totally weak code here... (ton) */
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit==base->object) {
|
2008-12-23 19:47:33 +00:00
|
|
|
extern ListBase editNurb;
|
|
|
|
nu1= editNurb.first;
|
2009-01-02 19:10:35 +00:00
|
|
|
cu= obedit->data;
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
cu= base->object->data;
|
|
|
|
nu1= cu->nurb.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cu->id.lib) {
|
|
|
|
tot_lib_error++;
|
|
|
|
} else {
|
|
|
|
if(centermode==2) {
|
|
|
|
VECCOPY(cent, give_cursor(scene, v3d));
|
|
|
|
Mat4Invert(base->object->imat, base->object->obmat);
|
|
|
|
Mat4MulVecfl(base->object->imat, cent);
|
|
|
|
|
|
|
|
/* don't allow Z change if curve is 2D */
|
|
|
|
if( !( cu->flag & CU_3D ) )
|
|
|
|
cent[2] = 0.0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
|
|
|
|
nu= nu1;
|
|
|
|
while(nu) {
|
|
|
|
minmaxNurb(nu, min, max);
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
cent[0]= (min[0]+max[0])/2.0f;
|
|
|
|
cent[1]= (min[1]+max[1])/2.0f;
|
|
|
|
cent[2]= (min[2]+max[2])/2.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
nu= nu1;
|
|
|
|
while(nu) {
|
|
|
|
if( (nu->type & 7)==1) {
|
|
|
|
a= nu->pntsu;
|
|
|
|
while (a--) {
|
|
|
|
VecSubf(nu->bezt[a].vec[0], nu->bezt[a].vec[0], cent);
|
|
|
|
VecSubf(nu->bezt[a].vec[1], nu->bezt[a].vec[1], cent);
|
|
|
|
VecSubf(nu->bezt[a].vec[2], nu->bezt[a].vec[2], cent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
while (a--)
|
|
|
|
VecSubf(nu->bp[a].vec, nu->bp[a].vec, cent);
|
|
|
|
}
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(centermode && obedit==0) {
|
2008-12-23 19:47:33 +00:00
|
|
|
Mat3CpyMat4(omat, base->object->obmat);
|
|
|
|
|
|
|
|
Mat3MulVecfl(omat, cent);
|
|
|
|
base->object->loc[0]+= cent[0];
|
|
|
|
base->object->loc[1]+= cent[1];
|
|
|
|
base->object->loc[2]+= cent[2];
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, base->object);
|
|
|
|
ignore_parent_tx(scene, base->object);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tot_change++;
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit) {
|
2008-12-23 19:47:33 +00:00
|
|
|
if (centermode==0) {
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(base->object->type==OB_FONT) {
|
|
|
|
/* get from bb */
|
|
|
|
|
|
|
|
cu= base->object->data;
|
|
|
|
|
|
|
|
if(cu->bb==0) {
|
|
|
|
/* do nothing*/
|
|
|
|
} else if (cu->id.lib) {
|
|
|
|
tot_lib_error++;
|
|
|
|
} else {
|
|
|
|
cu->xof= -0.5f*( cu->bb->vec[4][0] - cu->bb->vec[0][0]);
|
|
|
|
cu->yof= -0.5f -0.5f*( cu->bb->vec[0][1] - cu->bb->vec[2][1]); /* extra 0.5 is the height of above line */
|
|
|
|
|
|
|
|
/* not really ok, do this better once! */
|
|
|
|
cu->xof /= cu->fsize;
|
|
|
|
cu->yof /= cu->fsize;
|
|
|
|
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
tot_change++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(base->object->type==OB_ARMATURE) {
|
|
|
|
bArmature *arm = base->object->data;
|
|
|
|
|
|
|
|
if (arm->id.lib) {
|
|
|
|
tot_lib_error++;
|
|
|
|
} else if(arm->id.us>1) {
|
|
|
|
/*error("Can't apply to a multi user armature");
|
|
|
|
return;*/
|
|
|
|
tot_multiuser_arm_error++;
|
|
|
|
} else {
|
|
|
|
/* Function to recenter armatures in editarmature.c
|
|
|
|
* Bone + object locations are handled there.
|
|
|
|
*/
|
|
|
|
// XXX docenter_armature(base->object, centermode);
|
|
|
|
tot_change++;
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, base->object);
|
|
|
|
ignore_parent_tx(scene, base->object);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit)
|
2008-12-23 19:47:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base->object->recalc= OB_RECALC_OB|OB_RECALC_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tot_change) {
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
BIF_undo_push("Do Center");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Warn if any errors occured */
|
|
|
|
if (tot_lib_error+tot_multiuser_arm_error) {
|
|
|
|
char err[512];
|
|
|
|
sprintf(err, "Warning %i Object(s) Not Centered, %i Changed:", tot_lib_error+tot_multiuser_arm_error, tot_change);
|
|
|
|
|
|
|
|
if (tot_lib_error)
|
|
|
|
sprintf(err+strlen(err), "|%i linked library objects", tot_lib_error);
|
|
|
|
if (tot_multiuser_arm_error)
|
|
|
|
sprintf(err+strlen(err), "|%i multiuser armature object(s)", tot_multiuser_arm_error);
|
|
|
|
|
|
|
|
error(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void docenter_new(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) { // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
error("Unable to center new in Edit Mode");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
docenter(scene, v3d, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void docenter_cursor(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) { // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
error("Unable to center cursor in Edit Mode");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
docenter(scene, v3d, 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void movetolayer(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
unsigned int lay= 0, local;
|
|
|
|
int islamp= 0;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if (TESTBASE(v3d, base)) lay |= base->lay;
|
|
|
|
}
|
|
|
|
if(lay==0) return;
|
|
|
|
lay &= 0xFFFFFF;
|
|
|
|
|
|
|
|
if(lay==0) return;
|
|
|
|
|
|
|
|
if(v3d->localview) {
|
|
|
|
/* now we can move out of localview. */
|
|
|
|
if (!okee("Move from localview")) return;
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if (TESTBASE(v3d, base)) {
|
|
|
|
lay= base->lay & ~v3d->lay;
|
|
|
|
base->lay= lay;
|
|
|
|
base->object->lay= lay;
|
|
|
|
base->object->flag &= ~SELECT;
|
|
|
|
base->flag &= ~SELECT;
|
|
|
|
if(base->object->type==OB_LAMP) islamp= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// XXX if( movetolayer_buts(&lay, NULL)==0 ) return;
|
|
|
|
|
|
|
|
/* normal non localview operation */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if (TESTBASE(v3d, base)) {
|
|
|
|
/* upper byte is used for local view */
|
|
|
|
local= base->lay & 0xFF000000;
|
|
|
|
base->lay= lay + local;
|
|
|
|
base->object->lay= lay;
|
|
|
|
if(base->object->type==OB_LAMP) islamp= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-04 14:14:06 +00:00
|
|
|
if(islamp) reshadeall_displist(scene); /* only frees */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* warning, active object may be hidden now */
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
allqueue(REDRAWINFO, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("Move to layer");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// XXX should be in view3d?
|
|
|
|
|
|
|
|
/* context: ob = lamp */
|
|
|
|
/* code should be replaced with proper (custom) transform handles for lamp properties */
|
|
|
|
static void spot_interactive(Object *ob, int mode)
|
|
|
|
{
|
|
|
|
Lamp *la= ob->data;
|
|
|
|
float transfac, dx, dy, ratio, origval;
|
|
|
|
int keep_running= 1, center2d[2];
|
|
|
|
short mval[2], mvalo[2];
|
|
|
|
|
|
|
|
// getmouseco_areawin(mval);
|
|
|
|
// getmouseco_areawin(mvalo);
|
|
|
|
|
|
|
|
project_int(ob->obmat[3], center2d);
|
|
|
|
if( center2d[0] > 100000 ) { /* behind camera */
|
|
|
|
// center2d[0]= curarea->winx/2;
|
|
|
|
// center2d[1]= curarea->winy/2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// helpline(mval, center2d);
|
|
|
|
|
|
|
|
/* ratio is like scaling */
|
|
|
|
dx = (float)(center2d[0] - mval[0]);
|
|
|
|
dy = (float)(center2d[1] - mval[1]);
|
|
|
|
transfac = (float)sqrt( dx*dx + dy*dy);
|
|
|
|
if(transfac==0.0f) transfac= 1.0f;
|
|
|
|
|
|
|
|
if(mode==1)
|
|
|
|
origval= la->spotsize;
|
|
|
|
else if(mode==2)
|
|
|
|
origval= la->dist;
|
|
|
|
else if(mode==3)
|
|
|
|
origval= la->clipsta;
|
|
|
|
else
|
|
|
|
origval= la->clipend;
|
|
|
|
|
|
|
|
while (keep_running>0) {
|
|
|
|
|
|
|
|
// getmouseco_areawin(mval);
|
|
|
|
|
|
|
|
/* essential for idling subloop */
|
|
|
|
if(mval[0]==mvalo[0] && mval[1]==mvalo[1]) {
|
|
|
|
PIL_sleep_ms(2);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char str[32];
|
|
|
|
|
|
|
|
dx = (float)(center2d[0] - mval[0]);
|
|
|
|
dy = (float)(center2d[1] - mval[1]);
|
|
|
|
ratio = (float)(sqrt( dx*dx + dy*dy))/transfac;
|
|
|
|
|
|
|
|
/* do the trick */
|
|
|
|
|
|
|
|
if(mode==1) { /* spot */
|
|
|
|
la->spotsize = ratio*origval;
|
|
|
|
CLAMP(la->spotsize, 1.0f, 180.0f);
|
|
|
|
sprintf(str, "Spot size %.2f\n", la->spotsize);
|
|
|
|
}
|
|
|
|
else if(mode==2) { /* dist */
|
|
|
|
la->dist = ratio*origval;
|
|
|
|
CLAMP(la->dist, 0.01f, 5000.0f);
|
|
|
|
sprintf(str, "Distance %.2f\n", la->dist);
|
|
|
|
}
|
|
|
|
else if(mode==3) { /* sta */
|
|
|
|
la->clipsta = ratio*origval;
|
|
|
|
CLAMP(la->clipsta, 0.001f, 5000.0f);
|
|
|
|
sprintf(str, "Distance %.2f\n", la->clipsta);
|
|
|
|
}
|
|
|
|
else if(mode==4) { /* end */
|
|
|
|
la->clipend = ratio*origval;
|
|
|
|
CLAMP(la->clipend, 0.1f, 5000.0f);
|
|
|
|
sprintf(str, "Clip End %.2f\n", la->clipend);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* cleanup */
|
|
|
|
mvalo[0]= mval[0];
|
|
|
|
mvalo[1]= mval[1];
|
|
|
|
|
|
|
|
/* handle shaded mode */
|
|
|
|
// XXX shade_buttons_change_3d();
|
|
|
|
|
|
|
|
/* DRAW */
|
|
|
|
headerprint(str);
|
|
|
|
force_draw_plus(SPACE_BUTS, 0);
|
|
|
|
|
|
|
|
// helpline(mval, center2d);
|
|
|
|
}
|
|
|
|
|
|
|
|
while( qtest() ) {
|
|
|
|
short val;
|
|
|
|
unsigned short event= extern_qread(&val);
|
|
|
|
|
|
|
|
switch (event){
|
|
|
|
case ESCKEY:
|
|
|
|
case RIGHTMOUSE:
|
|
|
|
keep_running= 0;
|
|
|
|
break;
|
|
|
|
case LEFTMOUSE:
|
|
|
|
case SPACEKEY:
|
|
|
|
case PADENTER:
|
|
|
|
case RETKEY:
|
|
|
|
if(val)
|
|
|
|
keep_running= -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(keep_running==0) {
|
|
|
|
if(mode==1)
|
|
|
|
la->spotsize= origval;
|
|
|
|
else if(mode==2)
|
|
|
|
la->dist= origval;
|
|
|
|
else if(mode==3)
|
|
|
|
la->clipsta= origval;
|
|
|
|
else
|
|
|
|
la->clipend= origval;
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSSHADING, 0);
|
|
|
|
BIF_preview_changed(ID_LA);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void special_editmenu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
// XXX static short numcuts= 2;
|
|
|
|
Object *ob= OBACT;
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= NULL; // XXX
|
2008-12-23 19:47:33 +00:00
|
|
|
float fac;
|
|
|
|
int nr,ret;
|
|
|
|
short randfac;
|
|
|
|
|
|
|
|
if(ob==NULL) return;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit==NULL) {
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(ob->flag & OB_POSEMODE) {
|
|
|
|
// XXX pose_special_editmenu();
|
|
|
|
}
|
|
|
|
else if(FACESEL_PAINT_TEST) {
|
|
|
|
Mesh *me= get_mesh(ob);
|
|
|
|
MTFace *tface;
|
|
|
|
MFace *mface;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
if(me==0 || me->mtface==0) return;
|
|
|
|
|
|
|
|
nr= pupmenu("Specials%t|Set Tex%x1| Shared%x2| Light%x3| Invisible%x4| Collision%x5| TwoSide%x6|Clr Tex%x7| Shared%x8| Light%x9| Invisible%x10| Collision%x11| TwoSide%x12");
|
|
|
|
|
|
|
|
tface= me->mtface;
|
|
|
|
mface= me->mface;
|
|
|
|
for(a=me->totface; a>0; a--, tface++, mface++) {
|
|
|
|
if(mface->flag & ME_FACE_SEL) {
|
|
|
|
switch(nr) {
|
|
|
|
case 1:
|
|
|
|
tface->mode |= TF_TEX; break;
|
|
|
|
case 2:
|
|
|
|
tface->mode |= TF_SHAREDCOL; break;
|
|
|
|
case 3:
|
|
|
|
tface->mode |= TF_LIGHT; break;
|
|
|
|
case 4:
|
|
|
|
tface->mode |= TF_INVISIBLE; break;
|
|
|
|
case 5:
|
|
|
|
tface->mode |= TF_DYNAMIC; break;
|
|
|
|
case 6:
|
|
|
|
tface->mode |= TF_TWOSIDE; break;
|
|
|
|
case 7:
|
|
|
|
tface->mode &= ~TF_TEX;
|
|
|
|
tface->tpage= 0;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
tface->mode &= ~TF_SHAREDCOL; break;
|
|
|
|
case 9:
|
|
|
|
tface->mode &= ~TF_LIGHT; break;
|
|
|
|
case 10:
|
|
|
|
tface->mode &= ~TF_INVISIBLE; break;
|
|
|
|
case 11:
|
|
|
|
tface->mode &= ~TF_DYNAMIC; break;
|
|
|
|
case 12:
|
|
|
|
tface->mode &= ~TF_TWOSIDE; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
BIF_undo_push("Change texture face");
|
|
|
|
}
|
|
|
|
else if(G.f & G_VERTEXPAINT) {
|
|
|
|
Mesh *me= get_mesh(ob);
|
|
|
|
|
|
|
|
if(me==0 || (me->mcol==NULL && me->mtface==NULL) ) return;
|
|
|
|
|
|
|
|
nr= pupmenu("Specials%t|Shared VertexCol%x1");
|
|
|
|
if(nr==1) {
|
|
|
|
|
|
|
|
// XXX do_shared_vertexcol(me);
|
|
|
|
|
|
|
|
BIF_undo_push("Shared VertexCol");
|
|
|
|
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(G.f & G_WEIGHTPAINT) {
|
|
|
|
Object *par= modifiers_isDeformedByArmature(ob);
|
|
|
|
|
|
|
|
if(par && (par->flag & OB_POSEMODE)) {
|
|
|
|
nr= pupmenu("Specials%t|Apply Bone Envelopes to Vertex Groups %x1|Apply Bone Heat Weights to Vertex Groups %x2");
|
|
|
|
|
|
|
|
// XXX if(nr==1 || nr==2)
|
|
|
|
// XXX pose_adds_vgroups(ob, (nr == 2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(G.f & G_PARTICLEEDIT) {
|
|
|
|
#if 0
|
|
|
|
// XXX
|
|
|
|
ParticleSystem *psys = PE_get_current(ob);
|
|
|
|
ParticleEditSettings *pset = PE_settings();
|
|
|
|
|
|
|
|
if(!psys)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(scene->selectmode & SCE_SELECT_POINT)
|
|
|
|
nr= pupmenu("Specials%t|Rekey%x1|Subdivide%x2|Select First%x3|Select Last%x4|Remove Doubles%x5");
|
|
|
|
else
|
|
|
|
nr= pupmenu("Specials%t|Rekey%x1|Remove Doubles%x5");
|
|
|
|
|
|
|
|
switch(nr) {
|
|
|
|
case 1:
|
|
|
|
// XXX if(button(&pset->totrekey, 2, 100, "Number of Keys:")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
PE_rekey();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
PE_subdivide();
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
PE_select_root();
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
PE_select_tip();
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
PE_remove_doubles();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(nr>0) waitcursor(0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Base *base, *base_select= NULL;
|
|
|
|
|
|
|
|
/* Get the active object mesh. */
|
|
|
|
Mesh *me= get_mesh(ob);
|
|
|
|
|
|
|
|
/* Booleans, if the active object is a mesh... */
|
|
|
|
if (me && ob->id.lib==NULL) {
|
|
|
|
|
|
|
|
/* Bring up a little menu with the boolean operation choices on. */
|
|
|
|
nr= pupmenu("Boolean Tools%t|Intersect%x1|Union%x2|Difference%x3|Add Intersect Modifier%x4|Add Union Modifier%x5|Add Difference Modifier%x6");
|
|
|
|
|
|
|
|
if (nr > 0) {
|
|
|
|
/* user has made a choice of a menu element.
|
|
|
|
All of the boolean functions require 2 mesh objects
|
|
|
|
we search through the object list to find the other
|
|
|
|
selected item and make sure it is distinct and a mesh. */
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base->object != ob) base_select= base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base_select) {
|
|
|
|
if (get_mesh(base_select->object)) {
|
|
|
|
if(nr <= 3){
|
|
|
|
waitcursor(1);
|
|
|
|
// XXX ret = NewBooleanMesh(BASACT,base_select,nr);
|
|
|
|
if (ret==0) {
|
|
|
|
error("An internal error occurred");
|
|
|
|
} else if(ret==-1) {
|
|
|
|
error("Selected meshes must have faces to perform boolean operations");
|
|
|
|
} else if (ret==-2) {
|
|
|
|
error("Both meshes must be a closed mesh");
|
|
|
|
}
|
|
|
|
else BIF_undo_push("Boolean");
|
|
|
|
waitcursor(0);
|
|
|
|
} else {
|
|
|
|
BooleanModifierData *bmd = NULL;
|
|
|
|
bmd = (BooleanModifierData *)modifier_new(eModifierType_Boolean);
|
|
|
|
BLI_addtail(&ob->modifiers, bmd);
|
|
|
|
bmd->object = base_select->object;
|
|
|
|
bmd->modifier.mode |= eModifierMode_Realtime;
|
|
|
|
switch(nr){
|
|
|
|
case 4: bmd->operation = eBooleanModifierOp_Intersect; break;
|
|
|
|
case 5: bmd->operation = eBooleanModifierOp_Union; break;
|
|
|
|
case 6: bmd->operation = eBooleanModifierOp_Difference; break;
|
|
|
|
}
|
|
|
|
// XXX do_common_editbuts(B_CHANGEDEP);
|
|
|
|
BIF_undo_push("Add Boolean modifier");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
error("Please select 2 meshes");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
error("Please select 2 meshes");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
}
|
|
|
|
else if (ob->type == OB_FONT) {
|
|
|
|
/* removed until this gets a decent implementation (ton) */
|
|
|
|
/* nr= pupmenu("Split %t|Characters%x1");
|
|
|
|
if (nr > 0) {
|
|
|
|
switch(nr) {
|
|
|
|
case 1: split_font();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_MESH) {
|
2008-12-23 19:47:33 +00:00
|
|
|
/* This is all that is needed, since all other functionality is in Ctrl+ V/E/F but some users didnt like, so for now have the old/big menu */
|
|
|
|
/*
|
|
|
|
nr= pupmenu("Subdivide Mesh%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Smooth%x4");
|
|
|
|
switch(nr) {
|
|
|
|
case 1:
|
|
|
|
waitcursor(1);
|
|
|
|
esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, 1, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("ESubdivide Single");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, numcuts, 0);
|
|
|
|
BIF_undo_push("ESubdivide");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
|
|
|
|
randfac= 10;
|
|
|
|
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
fac= -( (float)randfac )/100;
|
|
|
|
esubdivideflag(1, fac, scene->toolsettings->editbutflag, numcuts, 0);
|
|
|
|
BIF_undo_push("Subdivide Fractal");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
fac= 1.0f;
|
|
|
|
if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
|
|
|
|
fac= 0.292f*fac;
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
esubdivideflag(1, fac, scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
|
|
|
|
BIF_undo_push("Subdivide Smooth");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Smooth%x12|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11|Set Smooth %x14|Set Solid %x15|Blend From Shape%x16|Propagate To All Shapes%x17|Select Vertex Path%x18");
|
|
|
|
|
|
|
|
switch(nr) {
|
|
|
|
case 1:
|
|
|
|
waitcursor(1);
|
|
|
|
// XXX esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, 1, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("ESubdivide Single");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// XXX if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
// XXX esubdivideflag(1, 0.0, scene->toolsettings->editbutflag, numcuts, 0);
|
|
|
|
BIF_undo_push("ESubdivide");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// XXX if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
|
|
|
|
randfac= 10;
|
|
|
|
// XXX if(button(&randfac, 1, 100, "Rand fac:")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
fac= -( (float)randfac )/100;
|
|
|
|
// XXX esubdivideflag(1, fac, scene->toolsettings->editbutflag, numcuts, 0);
|
|
|
|
BIF_undo_push("Subdivide Fractal");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 12: /* smooth */
|
|
|
|
/* if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return; */
|
|
|
|
fac= 1.0f;
|
|
|
|
// XXX if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return;
|
|
|
|
// XXX fac= 0.292f*fac;
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
// XXX esubdivideflag(1, fac, scene->toolsettings->editbutflag | B_SMOOTH, 1, 0);
|
|
|
|
BIF_undo_push("Subdivide Smooth");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
// XXX mergemenu();
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
// XXX notice("Removed %d Vertices", removedoublesflag(1, 0, scene->toolsettings->doublimit));
|
|
|
|
BIF_undo_push("Remove Doubles");
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
// XXX hide_mesh(0);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
// XXX reveal_mesh();
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
// XXX selectswap_mesh();
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
// XXX flip_editnormals();
|
|
|
|
BIF_undo_push("Flip Normals");
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
// XXX vertexsmooth();
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
// XXX bevel_menu();
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
// XXX mesh_set_smooth_faces(1);
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
// XXX mesh_set_smooth_faces(0);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
// XXX shape_copy_select_from();
|
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
// XXX shape_propagate();
|
|
|
|
break;
|
|
|
|
case 18:
|
|
|
|
// XXX pathselect();
|
|
|
|
BIF_undo_push("Select Vertex Path");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(nr>0) waitcursor(0);
|
|
|
|
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
nr= pupmenu("Specials%t|Subdivide%x1|Switch Direction%x2|Set Goal Weight%x3|Set Radius%x4|Smooth%x5|Smooth Radius%x6");
|
|
|
|
|
|
|
|
switch(nr) {
|
|
|
|
case 1:
|
|
|
|
// XXX subdivideNurb();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// XXX switchdirectionNurb2();
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// XXX setweightNurb();
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
// XXX setradiusNurb();
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
// XXX smoothNurb();
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
// XXX smoothradiusNurb();
|
|
|
|
break;
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_ARMATURE) {
|
2008-12-23 19:47:33 +00:00
|
|
|
nr= pupmenu("Specials%t|Subdivide %x1|Subdivide Multi%x2|Switch Direction%x7|Flip Left-Right Names%x3|%l|AutoName Left-Right%x4|AutoName Front-Back%x5|AutoName Top-Bottom%x6");
|
|
|
|
// if(nr==1)
|
|
|
|
// XXX subdivide_armature(1);
|
|
|
|
if(nr==2) {
|
|
|
|
// XXX if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
|
|
|
|
waitcursor(1);
|
|
|
|
// XXX subdivide_armature(numcuts);
|
|
|
|
}
|
|
|
|
// else if(nr==3)
|
|
|
|
// XXX armature_flip_names();
|
|
|
|
else if(ELEM3(nr, 4, 5, 6)) {
|
|
|
|
// XXX armature_autoside_names(nr-4);
|
|
|
|
}
|
|
|
|
// else if(nr == 7)
|
|
|
|
// XXX switch_direction_armature();
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_LATTICE) {
|
2008-12-23 19:47:33 +00:00
|
|
|
static float weight= 1.0f;
|
|
|
|
{ // XXX
|
|
|
|
// XXX if(fbutton(&weight, 0.0f, 1.0f, 10, 10, "Set Weight")) {
|
|
|
|
int a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
|
|
|
|
BPoint *bp= editLatt->def;
|
|
|
|
|
|
|
|
while(a--) {
|
|
|
|
if(bp->f1 & SELECT)
|
|
|
|
bp->weight= weight;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
static void curvetomesh(Scene *scene, Object *ob)
|
2008-12-23 19:47:33 +00:00
|
|
|
{
|
|
|
|
Curve *cu;
|
|
|
|
DispList *dl;
|
|
|
|
|
|
|
|
ob->flag |= OB_DONE;
|
|
|
|
cu= ob->data;
|
|
|
|
|
|
|
|
dl= cu->disp.first;
|
2009-01-04 14:14:06 +00:00
|
|
|
if(dl==0) makeDispListCurveTypes(scene, ob, 0); /* force creation */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
nurbs_to_mesh(ob); /* also does users */
|
|
|
|
if (ob->type != OB_MESH) {
|
|
|
|
error("can't convert curve to mesh");
|
|
|
|
} else {
|
|
|
|
object_free_modifiers(ob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void convertmenu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base, *basen=NULL, *basact, *basedel=NULL;
|
|
|
|
Object *obact, *ob, *ob1;
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= NULL; // XXX
|
2008-12-23 19:47:33 +00:00
|
|
|
Curve *cu;
|
|
|
|
Nurb *nu;
|
|
|
|
MetaBall *mb;
|
|
|
|
Mesh *me;
|
|
|
|
int ok=0, nr = 0, a;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
obact= OBACT;
|
|
|
|
if (obact == NULL) return;
|
|
|
|
if(!obact->flag & SELECT) return;
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit) return;
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
basact= BASACT; /* will be restored */
|
|
|
|
|
|
|
|
if(obact->type==OB_FONT) {
|
|
|
|
nr= pupmenu("Convert Font to%t|Curve%x1|Curve (Single filling group)%x2|Mesh%x3");
|
|
|
|
if(nr>0) ok= 1;
|
|
|
|
}
|
|
|
|
else if(obact->type==OB_MBALL) {
|
|
|
|
nr= pupmenu("Convert Metaball to%t|Mesh (keep original)%x1|Mesh (Delete Original)%x2");
|
|
|
|
if(nr>0) ok= 1;
|
|
|
|
}
|
|
|
|
else if(obact->type==OB_CURVE) {
|
|
|
|
nr= pupmenu("Convert Curve to%t|Mesh");
|
|
|
|
if(nr>0) ok= 1;
|
|
|
|
}
|
|
|
|
else if(obact->type==OB_SURF) {
|
|
|
|
nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
|
|
|
|
if(nr>0) ok= 1;
|
|
|
|
}
|
|
|
|
else if(obact->type==OB_MESH) {
|
|
|
|
nr= pupmenu("Convert Modifiers to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
|
|
|
|
if(nr>0) ok= 1;
|
|
|
|
}
|
|
|
|
if(ok==0) return;
|
|
|
|
|
|
|
|
/* don't forget multiple users! */
|
|
|
|
|
|
|
|
/* reset flags */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
base->object->flag &= ~OB_DONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
|
|
|
|
ob= base->object;
|
|
|
|
|
|
|
|
if(ob->flag & OB_DONE);
|
|
|
|
else if(ob->type==OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
|
|
|
|
DerivedMesh *dm;
|
|
|
|
|
|
|
|
basedel = base;
|
|
|
|
|
|
|
|
ob->flag |= OB_DONE;
|
|
|
|
|
|
|
|
ob1= copy_object(ob);
|
|
|
|
ob1->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
basen= MEM_mallocN(sizeof(Base), "duplibase");
|
|
|
|
*basen= *base;
|
|
|
|
BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
|
|
|
|
basen->object= ob1;
|
|
|
|
basen->flag |= SELECT;
|
|
|
|
base->flag &= ~SELECT;
|
|
|
|
ob->flag &= ~SELECT;
|
|
|
|
|
|
|
|
/* decrement original mesh's usage count */
|
|
|
|
me= ob1->data;
|
|
|
|
me->id.us--;
|
|
|
|
|
|
|
|
/* make a new copy of the mesh */
|
|
|
|
ob1->data= copy_mesh(me);
|
|
|
|
G.totmesh++;
|
|
|
|
|
|
|
|
/* make new mesh data from the original copy */
|
2009-01-04 14:14:06 +00:00
|
|
|
dm= mesh_get_derived_final(scene, ob1, CD_MASK_MESH);
|
2008-12-23 19:47:33 +00:00
|
|
|
/* dm= mesh_create_derived_no_deform(ob1, NULL); this was called original (instead of get_derived). man o man why! (ton) */
|
|
|
|
|
|
|
|
DM_to_mesh(dm, ob1->data);
|
|
|
|
|
|
|
|
dm->release(dm);
|
|
|
|
object_free_modifiers(ob1); /* after derivedmesh calls! */
|
|
|
|
|
|
|
|
/* If the original object is active then make this object active */
|
|
|
|
if (ob == obact) {
|
2008-12-29 12:15:42 +00:00
|
|
|
// XXX ED_base_object_activate(C, basen);
|
2008-12-23 19:47:33 +00:00
|
|
|
basact = basen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_FONT) {
|
|
|
|
ob->flag |= OB_DONE;
|
|
|
|
|
|
|
|
ob->type= OB_CURVE;
|
|
|
|
cu= ob->data;
|
|
|
|
|
|
|
|
if(cu->vfont) {
|
|
|
|
cu->vfont->id.us--;
|
|
|
|
cu->vfont= 0;
|
|
|
|
}
|
|
|
|
if(cu->vfontb) {
|
|
|
|
cu->vfontb->id.us--;
|
|
|
|
cu->vfontb= 0;
|
|
|
|
}
|
|
|
|
if(cu->vfonti) {
|
|
|
|
cu->vfonti->id.us--;
|
|
|
|
cu->vfonti= 0;
|
|
|
|
}
|
|
|
|
if(cu->vfontbi) {
|
|
|
|
cu->vfontbi->id.us--;
|
|
|
|
cu->vfontbi= 0;
|
|
|
|
}
|
|
|
|
/* other users */
|
|
|
|
if(cu->id.us>1) {
|
|
|
|
ob1= G.main->object.first;
|
|
|
|
while(ob1) {
|
|
|
|
if(ob1->data==cu) {
|
|
|
|
ob1->type= OB_CURVE;
|
|
|
|
ob1->recalc |= OB_RECALC;
|
|
|
|
}
|
|
|
|
ob1= ob1->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nr==2 || nr==3) {
|
|
|
|
nu= cu->nurb.first;
|
|
|
|
while(nu) {
|
|
|
|
nu->charidx= 0;
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nr==3) {
|
2009-01-04 14:14:06 +00:00
|
|
|
curvetomesh(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
|
|
|
|
if(nr==1) {
|
2009-01-04 14:14:06 +00:00
|
|
|
curvetomesh(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_MBALL) {
|
|
|
|
|
|
|
|
if(nr==1 || nr == 2) {
|
2009-01-04 14:14:06 +00:00
|
|
|
ob= find_basis_mball(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(ob->disp.first && !(ob->flag&OB_DONE)) {
|
|
|
|
basedel = base;
|
|
|
|
|
|
|
|
ob->flag |= OB_DONE;
|
|
|
|
|
|
|
|
ob1= copy_object(ob);
|
|
|
|
ob1->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
basen= MEM_mallocN(sizeof(Base), "duplibase");
|
|
|
|
*basen= *base;
|
|
|
|
BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
|
|
|
|
basen->object= ob1;
|
|
|
|
basen->flag |= SELECT;
|
|
|
|
basedel->flag &= ~SELECT;
|
|
|
|
ob->flag &= ~SELECT;
|
|
|
|
|
|
|
|
mb= ob1->data;
|
|
|
|
mb->id.us--;
|
|
|
|
|
|
|
|
ob1->data= add_mesh("Mesh");
|
|
|
|
G.totmesh++;
|
|
|
|
ob1->type= OB_MESH;
|
|
|
|
|
|
|
|
me= ob1->data;
|
|
|
|
me->totcol= mb->totcol;
|
|
|
|
if(ob1->totcol) {
|
|
|
|
me->mat= MEM_dupallocN(mb->mat);
|
|
|
|
for(a=0; a<ob1->totcol; a++) id_us_plus((ID *)me->mat[a]);
|
|
|
|
}
|
|
|
|
|
|
|
|
mball_to_mesh(&ob->disp, ob1->data);
|
|
|
|
|
|
|
|
/* So we can see the wireframe */
|
|
|
|
BASACT= basen;
|
|
|
|
|
|
|
|
/* If the original object is active then make this object active */
|
|
|
|
if (ob == obact) {
|
2008-12-29 12:15:42 +00:00
|
|
|
// XXX ED_base_object_activate(C, basen);
|
2008-12-23 19:47:33 +00:00
|
|
|
basact = basen;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(basedel != NULL && nr == 2) {
|
2008-12-30 13:16:14 +00:00
|
|
|
ED_base_object_free_and_unlink(scene, basedel);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
basedel = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* delete object should renew depsgraph */
|
|
|
|
if(nr==2)
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
/* texspace and normals */
|
|
|
|
if(!basen) BASACT= base;
|
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
// XXX ED_object_enter_editmode(C, 0);
|
|
|
|
// XXX exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
|
2008-12-23 19:47:33 +00:00
|
|
|
BASACT= basact;
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
// allspace(OOPS_TEST, 0);
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
BIF_undo_push("Convert Object");
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Change subdivision or particle properties of mesh object ob, if level==-1
|
|
|
|
* then toggle subsurf, else set to level set allows to toggle multiple
|
|
|
|
* selections */
|
|
|
|
|
|
|
|
static void object_has_subdivision_particles(Object *ob, int *havesubdiv, int *havepart, int depth)
|
|
|
|
{
|
|
|
|
if(ob->type==OB_MESH) {
|
|
|
|
if(modifiers_findByType(ob, eModifierType_Subsurf))
|
|
|
|
*havesubdiv= 1;
|
|
|
|
if(modifiers_findByType(ob, eModifierType_ParticleSystem))
|
|
|
|
*havepart= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ob->dup_group && depth <= 4) {
|
|
|
|
GroupObject *go;
|
|
|
|
|
|
|
|
for(go= ob->dup_group->gobject.first; go; go= go->next)
|
|
|
|
object_has_subdivision_particles(go->ob, havesubdiv, havepart, depth+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void object_flip_subdivison_particles(Scene *scene, Object *ob, int *set, int level, int mode, int particles, int depth)
|
|
|
|
{
|
|
|
|
ModifierData *md;
|
|
|
|
|
|
|
|
if(ob->type==OB_MESH) {
|
|
|
|
if(particles) {
|
|
|
|
for(md=ob->modifiers.first; md; md=md->next) {
|
|
|
|
if(md->type == eModifierType_ParticleSystem) {
|
|
|
|
ParticleSystemModifierData *psmd = (ParticleSystemModifierData*)md;
|
|
|
|
|
|
|
|
if(*set == -1)
|
|
|
|
*set= psmd->modifier.mode&(mode);
|
|
|
|
|
|
|
|
if (*set)
|
|
|
|
psmd->modifier.mode &= ~(mode);
|
|
|
|
else
|
|
|
|
psmd->modifier.mode |= (mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
md = modifiers_findByType(ob, eModifierType_Subsurf);
|
|
|
|
|
|
|
|
if (md) {
|
|
|
|
SubsurfModifierData *smd = (SubsurfModifierData*) md;
|
|
|
|
|
|
|
|
if (level == -1) {
|
|
|
|
if(*set == -1)
|
|
|
|
*set= smd->modifier.mode&(mode);
|
|
|
|
|
|
|
|
if (*set)
|
|
|
|
smd->modifier.mode &= ~(mode);
|
|
|
|
else
|
|
|
|
smd->modifier.mode |= (mode);
|
|
|
|
} else {
|
|
|
|
smd->levels = level;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(depth == 0 && *set != 0) {
|
|
|
|
SubsurfModifierData *smd = (SubsurfModifierData*) modifier_new(eModifierType_Subsurf);
|
|
|
|
|
|
|
|
BLI_addtail(&ob->modifiers, smd);
|
|
|
|
|
|
|
|
if (level!=-1) {
|
|
|
|
smd->levels = level;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(*set == -1)
|
|
|
|
*set= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ob->dup_group && depth<=4) {
|
|
|
|
GroupObject *go;
|
|
|
|
|
|
|
|
for(go= ob->dup_group->gobject.first; go; go= go->next)
|
|
|
|
object_flip_subdivison_particles(scene, go->ob, set, level, mode, particles, depth+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Change subdivision properties of mesh object ob, if
|
|
|
|
* level==-1 then toggle subsurf, else set to level.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void flip_subdivison(Scene *scene, View3D *v3d, int level)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
int set= -1;
|
|
|
|
int mode, pupmode, particles= 0, havesubdiv= 0, havepart= 0;
|
|
|
|
int alt= 0; // XXX
|
|
|
|
|
|
|
|
if(alt)
|
|
|
|
mode= eModifierMode_Realtime;
|
|
|
|
else
|
|
|
|
mode= eModifierMode_Render|eModifierMode_Realtime;
|
|
|
|
|
|
|
|
if(level == -1) {
|
2009-01-02 19:10:35 +00:00
|
|
|
if (scene->obedit) { // XXX get from context
|
|
|
|
object_has_subdivision_particles(scene->obedit, &havesubdiv, &havepart, 0);
|
2008-12-23 19:47:33 +00:00
|
|
|
} else {
|
|
|
|
for(base= scene->base.first; base; base= base->next) {
|
|
|
|
if(((level==-1) && (TESTBASE(v3d, base))) || (TESTBASELIB(v3d, base))) {
|
|
|
|
object_has_subdivision_particles(base->object, &havesubdiv, &havepart, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
havesubdiv= 1;
|
|
|
|
|
|
|
|
if(havesubdiv && havepart) {
|
|
|
|
pupmode= pupmenu("Switch%t|Subsurf %x1|Particle Systems %x2");
|
|
|
|
if(pupmode <= 0)
|
|
|
|
return;
|
|
|
|
else if(pupmode == 2)
|
|
|
|
particles= 1;
|
|
|
|
}
|
|
|
|
else if(havepart)
|
|
|
|
particles= 1;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if (scene->obedit) { // XXX get from context
|
|
|
|
object_flip_subdivison_particles(scene, scene->obedit, &set, level, mode, particles, 0);
|
2008-12-23 19:47:33 +00:00
|
|
|
} else {
|
|
|
|
for(base= scene->base.first; base; base= base->next) {
|
|
|
|
if(((level==-1) && (TESTBASE(v3d, base))) || (TESTBASELIB(v3d, base))) {
|
|
|
|
object_flip_subdivison_particles(scene, base->object, &set, level, mode, particles, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
if(particles)
|
|
|
|
BIF_undo_push("Switch particles on/off");
|
|
|
|
else
|
|
|
|
BIF_undo_push("Switch subsurf on/off");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
|
|
|
|
{
|
|
|
|
bProperty *prop;
|
|
|
|
Base *base;
|
|
|
|
int nr, tot=0;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
prop= ob->prop.first;
|
|
|
|
while(prop) {
|
|
|
|
tot++;
|
|
|
|
prop= prop->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(tot==0) {
|
|
|
|
error("No properties in the active object to copy");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
str= MEM_callocN(50 + 33*tot, "copymenu prop");
|
|
|
|
|
|
|
|
strcpy(str, "Copy Property %t|Replace All|Merge All|%l");
|
|
|
|
|
|
|
|
tot= 0;
|
|
|
|
prop= ob->prop.first;
|
|
|
|
while(prop) {
|
|
|
|
tot++;
|
|
|
|
strcat(str, "|");
|
|
|
|
strcat(str, prop->name);
|
|
|
|
prop= prop->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
nr= pupmenu(str);
|
|
|
|
|
|
|
|
if ( nr==1 || nr==2 ) {
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
|
|
|
|
if (nr==1) { /* replace */
|
|
|
|
copy_properties( &base->object->prop, &ob->prop );
|
|
|
|
} else {
|
|
|
|
for(prop = ob->prop.first; prop; prop= prop->next ) {
|
|
|
|
set_ob_property(base->object, prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if(nr>0) {
|
|
|
|
prop = BLI_findlink(&ob->prop, nr-4); /* account for first 3 menu items & menu index starting at 1*/
|
|
|
|
|
|
|
|
if(prop) {
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if((base != BASACT) &&(TESTBASELIB(v3d, base))) {
|
|
|
|
set_ob_property(base->object, prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MEM_freeN(str);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("Copy properties");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(base->object != ob) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
|
|
|
|
/* first: free all logic */
|
|
|
|
free_sensors(&base->object->sensors);
|
|
|
|
unlink_controllers(&base->object->controllers);
|
|
|
|
free_controllers(&base->object->controllers);
|
|
|
|
unlink_actuators(&base->object->actuators);
|
|
|
|
free_actuators(&base->object->actuators);
|
|
|
|
|
|
|
|
/* now copy it, this also works without logicbricks! */
|
|
|
|
clear_sca_new_poins_ob(ob);
|
|
|
|
copy_sensors(&base->object->sensors, &ob->sensors);
|
|
|
|
copy_controllers(&base->object->controllers, &ob->controllers);
|
|
|
|
copy_actuators(&base->object->actuators, &ob->actuators);
|
|
|
|
set_sca_new_poins_ob(base->object);
|
|
|
|
|
|
|
|
/* some menu settings */
|
|
|
|
base->object->scavisflag= ob->scavisflag;
|
|
|
|
base->object->scaflag= ob->scaflag;
|
|
|
|
|
|
|
|
/* set the initial state */
|
|
|
|
base->object->state= ob->state;
|
|
|
|
base->object->init_state= ob->init_state;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BIF_undo_push("Copy logic");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void copymenu_modifiers(Scene *scene, View3D *v3d, Object *ob)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
int i, event;
|
|
|
|
char str[512];
|
|
|
|
char *errorstr= NULL;
|
|
|
|
|
|
|
|
strcpy(str, "Copy Modifiers %t");
|
|
|
|
|
|
|
|
sprintf(str+strlen(str), "|All%%x%d|%%l", NUM_MODIFIER_TYPES);
|
|
|
|
|
|
|
|
for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
|
|
|
|
ModifierTypeInfo *mti = modifierType_getInfo(i);
|
|
|
|
|
|
|
|
if(ELEM3(i, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance)) continue;
|
|
|
|
|
|
|
|
if(i == eModifierType_Collision)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( (mti->flags&eModifierTypeFlag_AcceptsCVs) ||
|
|
|
|
(ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
|
|
|
|
sprintf(str+strlen(str), "|%s%%x%d", mti->name, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
event = pupmenu(str);
|
|
|
|
if(event<=0) return;
|
|
|
|
|
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(base->object != ob) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
ModifierData *md;
|
|
|
|
|
|
|
|
base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA;
|
|
|
|
|
|
|
|
if (base->object->type==ob->type) {
|
|
|
|
/* copy all */
|
|
|
|
if (event==NUM_MODIFIER_TYPES) {
|
|
|
|
object_free_modifiers(base->object);
|
|
|
|
|
|
|
|
for (md=ob->modifiers.first; md; md=md->next) {
|
|
|
|
ModifierData *nmd = NULL;
|
|
|
|
|
|
|
|
if(ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance)) continue;
|
|
|
|
|
|
|
|
if(md->type == eModifierType_Collision)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
nmd = modifier_new(md->type);
|
|
|
|
modifier_copyData(md, nmd);
|
|
|
|
BLI_addtail(&base->object->modifiers, nmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
copy_object_particlesystems(base->object, ob);
|
|
|
|
copy_object_softbody(base->object, ob);
|
|
|
|
} else {
|
|
|
|
/* copy specific types */
|
|
|
|
ModifierData *md, *mdn;
|
|
|
|
|
|
|
|
/* remove all with type 'event' */
|
|
|
|
for (md=base->object->modifiers.first; md; md=mdn) {
|
|
|
|
mdn= md->next;
|
|
|
|
if(md->type==event) {
|
|
|
|
BLI_remlink(&base->object->modifiers, md);
|
|
|
|
modifier_free(md);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy all with type 'event' */
|
|
|
|
for (md=ob->modifiers.first; md; md=md->next) {
|
|
|
|
if (md->type==event) {
|
|
|
|
|
|
|
|
mdn = modifier_new(event);
|
|
|
|
BLI_addtail(&base->object->modifiers, mdn);
|
|
|
|
|
|
|
|
modifier_copyData(md, mdn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(event == eModifierType_ParticleSystem) {
|
|
|
|
object_free_particlesystems(base->object);
|
|
|
|
copy_object_particlesystems(base->object, ob);
|
|
|
|
}
|
|
|
|
else if(event == eModifierType_Softbody) {
|
|
|
|
object_free_softbody(base->object);
|
|
|
|
copy_object_softbody(base->object, ob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
errorstr= "Did not copy modifiers to other Object types";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if(errorstr) notice(errorstr);
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
BIF_undo_push("Copy modifiers");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* both pointers should exist */
|
|
|
|
static void copy_texture_space(Object *to, Object *ob)
|
|
|
|
{
|
|
|
|
float *poin1= NULL, *poin2= NULL;
|
|
|
|
int texflag= 0;
|
|
|
|
|
|
|
|
if(ob->type==OB_MESH) {
|
|
|
|
texflag= ((Mesh *)ob->data)->texflag;
|
|
|
|
poin2= ((Mesh *)ob->data)->loc;
|
|
|
|
}
|
|
|
|
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
|
|
|
|
texflag= ((Curve *)ob->data)->texflag;
|
|
|
|
poin2= ((Curve *)ob->data)->loc;
|
|
|
|
}
|
|
|
|
else if(ob->type==OB_MBALL) {
|
|
|
|
texflag= ((MetaBall *)ob->data)->texflag;
|
|
|
|
poin2= ((MetaBall *)ob->data)->loc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(to->type==OB_MESH) {
|
|
|
|
((Mesh *)to->data)->texflag= texflag;
|
|
|
|
poin1= ((Mesh *)to->data)->loc;
|
|
|
|
}
|
|
|
|
else if (ELEM3(to->type, OB_CURVE, OB_SURF, OB_FONT)) {
|
|
|
|
((Curve *)to->data)->texflag= texflag;
|
|
|
|
poin1= ((Curve *)to->data)->loc;
|
|
|
|
}
|
|
|
|
else if(to->type==OB_MBALL) {
|
|
|
|
((MetaBall *)to->data)->texflag= texflag;
|
|
|
|
poin1= ((MetaBall *)to->data)->loc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
memcpy(poin1, poin2, 9*sizeof(float)); /* this was noted in DNA_mesh, curve, mball */
|
|
|
|
|
|
|
|
if(to->type==OB_MESH) ;
|
|
|
|
else if(to->type==OB_MBALL) tex_space_mball(to);
|
|
|
|
else tex_space_curve(to->data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void copy_attr(Scene *scene, View3D *v3d, short event)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Base *base;
|
|
|
|
Curve *cu, *cu1;
|
|
|
|
Nurb *nu;
|
|
|
|
int do_scene_sort= 0;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
if(!(ob=OBACT)) return;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) { // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
/* obedit_copymenu(); */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(event==9) {
|
|
|
|
copymenu_properties(scene, v3d, ob);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(event==10) {
|
|
|
|
copymenu_logicbricks(scene, v3d, ob);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(event==24) {
|
|
|
|
copymenu_modifiers(scene, v3d, ob);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(base != BASACT) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
base->object->recalc |= OB_RECALC_OB;
|
|
|
|
|
|
|
|
if(event==1) { /* loc */
|
|
|
|
VECCOPY(base->object->loc, ob->loc);
|
|
|
|
VECCOPY(base->object->dloc, ob->dloc);
|
|
|
|
}
|
|
|
|
else if(event==2) { /* rot */
|
|
|
|
VECCOPY(base->object->rot, ob->rot);
|
|
|
|
VECCOPY(base->object->drot, ob->drot);
|
|
|
|
/* Quats arnt used yet */
|
|
|
|
/*VECCOPY(base->object->quat, ob->quat);
|
|
|
|
VECCOPY(base->object->dquat, ob->dquat);*/
|
|
|
|
}
|
|
|
|
else if(event==3) { /* size */
|
|
|
|
VECCOPY(base->object->size, ob->size);
|
|
|
|
VECCOPY(base->object->dsize, ob->dsize);
|
|
|
|
}
|
|
|
|
else if(event==4) { /* drawtype */
|
|
|
|
base->object->dt= ob->dt;
|
|
|
|
base->object->dtx= ob->dtx;
|
|
|
|
base->object->empty_drawtype= ob->empty_drawtype;
|
|
|
|
base->object->empty_drawsize= ob->empty_drawsize;
|
|
|
|
}
|
|
|
|
else if(event==5) { /* time offs */
|
|
|
|
base->object->sf= ob->sf;
|
|
|
|
}
|
|
|
|
else if(event==6) { /* dupli */
|
|
|
|
base->object->dupon= ob->dupon;
|
|
|
|
base->object->dupoff= ob->dupoff;
|
|
|
|
base->object->dupsta= ob->dupsta;
|
|
|
|
base->object->dupend= ob->dupend;
|
|
|
|
|
|
|
|
base->object->transflag &= ~OB_DUPLI;
|
|
|
|
base->object->transflag |= (ob->transflag & OB_DUPLI);
|
|
|
|
|
|
|
|
base->object->dup_group= ob->dup_group;
|
|
|
|
if(ob->dup_group)
|
|
|
|
id_us_plus((ID *)ob->dup_group);
|
|
|
|
}
|
|
|
|
else if(event==7) { /* mass */
|
|
|
|
base->object->mass= ob->mass;
|
|
|
|
}
|
|
|
|
else if(event==8) { /* damping */
|
|
|
|
base->object->damping= ob->damping;
|
|
|
|
base->object->rdamping= ob->rdamping;
|
|
|
|
}
|
|
|
|
else if(event==11) { /* all physical attributes */
|
|
|
|
base->object->gameflag = ob->gameflag;
|
|
|
|
base->object->inertia = ob->inertia;
|
|
|
|
base->object->formfactor = ob->formfactor;
|
|
|
|
base->object->damping= ob->damping;
|
|
|
|
base->object->rdamping= ob->rdamping;
|
|
|
|
base->object->mass= ob->mass;
|
|
|
|
if (ob->gameflag & OB_BOUNDS) {
|
|
|
|
base->object->boundtype = ob->boundtype;
|
|
|
|
}
|
|
|
|
base->object->margin= ob->margin;
|
|
|
|
base->object->bsoft= copy_bulletsoftbody(ob->bsoft);
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(event==17) { /* tex space */
|
|
|
|
copy_texture_space(base->object, ob);
|
|
|
|
}
|
|
|
|
else if(event==18) { /* font settings */
|
|
|
|
|
|
|
|
if(base->object->type==ob->type) {
|
|
|
|
cu= ob->data;
|
|
|
|
cu1= base->object->data;
|
|
|
|
|
|
|
|
cu1->spacemode= cu->spacemode;
|
|
|
|
cu1->spacing= cu->spacing;
|
|
|
|
cu1->linedist= cu->linedist;
|
|
|
|
cu1->shear= cu->shear;
|
|
|
|
cu1->fsize= cu->fsize;
|
|
|
|
cu1->xof= cu->xof;
|
|
|
|
cu1->yof= cu->yof;
|
|
|
|
cu1->textoncurve= cu->textoncurve;
|
|
|
|
cu1->wordspace= cu->wordspace;
|
|
|
|
cu1->ulpos= cu->ulpos;
|
|
|
|
cu1->ulheight= cu->ulheight;
|
|
|
|
if(cu1->vfont) cu1->vfont->id.us--;
|
|
|
|
cu1->vfont= cu->vfont;
|
|
|
|
id_us_plus((ID *)cu1->vfont);
|
|
|
|
if(cu1->vfontb) cu1->vfontb->id.us--;
|
|
|
|
cu1->vfontb= cu->vfontb;
|
|
|
|
id_us_plus((ID *)cu1->vfontb);
|
|
|
|
if(cu1->vfonti) cu1->vfonti->id.us--;
|
|
|
|
cu1->vfonti= cu->vfonti;
|
|
|
|
id_us_plus((ID *)cu1->vfonti);
|
|
|
|
if(cu1->vfontbi) cu1->vfontbi->id.us--;
|
|
|
|
cu1->vfontbi= cu->vfontbi;
|
|
|
|
id_us_plus((ID *)cu1->vfontbi);
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
text_to_curve(scene, base->object, 0); /* needed? */
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
strcpy(cu1->family, cu->family);
|
|
|
|
|
|
|
|
base->object->recalc |= OB_RECALC_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==19) { /* bevel settings */
|
|
|
|
|
|
|
|
if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
|
|
|
|
cu= ob->data;
|
|
|
|
cu1= base->object->data;
|
|
|
|
|
|
|
|
cu1->bevobj= cu->bevobj;
|
|
|
|
cu1->taperobj= cu->taperobj;
|
|
|
|
cu1->width= cu->width;
|
|
|
|
cu1->bevresol= cu->bevresol;
|
|
|
|
cu1->ext1= cu->ext1;
|
|
|
|
cu1->ext2= cu->ext2;
|
|
|
|
|
|
|
|
base->object->recalc |= OB_RECALC_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==25) { /* curve resolution */
|
|
|
|
|
|
|
|
if(ELEM(base->object->type, OB_CURVE, OB_FONT)) {
|
|
|
|
cu= ob->data;
|
|
|
|
cu1= base->object->data;
|
|
|
|
|
|
|
|
cu1->resolu= cu->resolu;
|
|
|
|
cu1->resolu_ren= cu->resolu_ren;
|
|
|
|
|
|
|
|
nu= cu1->nurb.first;
|
|
|
|
|
|
|
|
while(nu) {
|
|
|
|
nu->resolu= cu1->resolu;
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
base->object->recalc |= OB_RECALC_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==21){
|
|
|
|
if (base->object->type==OB_MESH) {
|
|
|
|
ModifierData *md = modifiers_findByType(ob, eModifierType_Subsurf);
|
|
|
|
|
|
|
|
if (md) {
|
|
|
|
ModifierData *tmd = modifiers_findByType(base->object, eModifierType_Subsurf);
|
|
|
|
|
|
|
|
if (!tmd) {
|
|
|
|
tmd = modifier_new(eModifierType_Subsurf);
|
|
|
|
BLI_addtail(&base->object->modifiers, tmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
modifier_copyData(md, tmd);
|
|
|
|
base->object->recalc |= OB_RECALC_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==22) {
|
|
|
|
/* Copy the constraint channels over */
|
|
|
|
copy_constraints(&base->object->constraints, &ob->constraints);
|
|
|
|
if (U.dupflag& USER_DUP_IPO)
|
|
|
|
copy_constraint_channels(&base->object->constraintChannels, &ob->constraintChannels);
|
|
|
|
else
|
|
|
|
clone_constraint_channels (&base->object->constraintChannels, &ob->constraintChannels);
|
|
|
|
|
|
|
|
do_scene_sort= 1;
|
|
|
|
}
|
|
|
|
else if(event==23) {
|
|
|
|
base->object->softflag= ob->softflag;
|
|
|
|
if(base->object->soft) sbFree(base->object->soft);
|
|
|
|
|
|
|
|
base->object->soft= copy_softbody(ob->soft);
|
|
|
|
|
|
|
|
if (!modifiers_findByType(base->object, eModifierType_Softbody)) {
|
|
|
|
BLI_addhead(&base->object->modifiers, modifier_new(eModifierType_Softbody));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==26) {
|
|
|
|
copy_nlastrips(&base->object->nlastrips, &ob->nlastrips);
|
|
|
|
}
|
|
|
|
else if(event==27) { /* autosmooth */
|
|
|
|
if (base->object->type==OB_MESH) {
|
|
|
|
Mesh *me= ob->data;
|
|
|
|
Mesh *cme= base->object->data;
|
|
|
|
cme->smoothresh= me->smoothresh;
|
|
|
|
if(me->flag & ME_AUTOSMOOTH)
|
|
|
|
cme->flag |= ME_AUTOSMOOTH;
|
|
|
|
else
|
|
|
|
cme->flag &= ~ME_AUTOSMOOTH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==28) { /* UV orco */
|
|
|
|
if(ELEM(base->object->type, OB_CURVE, OB_SURF)) {
|
|
|
|
cu= ob->data;
|
|
|
|
cu1= base->object->data;
|
|
|
|
|
|
|
|
if(cu->flag & CU_UV_ORCO)
|
|
|
|
cu1->flag |= CU_UV_ORCO;
|
|
|
|
else
|
|
|
|
cu1->flag &= ~CU_UV_ORCO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==29) { /* protected bits */
|
|
|
|
base->object->protectflag= ob->protectflag;
|
|
|
|
}
|
|
|
|
else if(event==30) { /* index object */
|
|
|
|
base->object->index= ob->index;
|
|
|
|
}
|
|
|
|
else if(event==31) { /* object color */
|
|
|
|
QUATCOPY(base->object->col, ob->col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
if(do_scene_sort)
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
|
|
|
if(event==20) {
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
BIF_undo_push("Copy Attributes");
|
|
|
|
}
|
|
|
|
|
|
|
|
void copy_attr_menu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
short event;
|
|
|
|
char str[512];
|
|
|
|
|
|
|
|
if(!(ob=OBACT)) return;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if (scene->obedit) { // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
// if (ob->type == OB_MESH)
|
|
|
|
// XXX mesh_copy_menu();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Object Mode */
|
|
|
|
|
|
|
|
/* If you change this menu, don't forget to update the menu in header_view3d.c
|
|
|
|
* view3d_edit_object_copyattrmenu() and in toolbox.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
strcpy(str, "Copy Attributes %t|Location%x1|Rotation%x2|Size%x3|Draw Options%x4|Time Offset%x5|Dupli%x6|Object Color%x31|%l|Mass%x7|Damping%x8|All Physical Attributes%x11|Properties%x9|Logic Bricks%x10|Protected Transform%x29|%l");
|
|
|
|
|
|
|
|
strcat (str, "|Object Constraints%x22");
|
|
|
|
strcat (str, "|NLA Strips%x26");
|
|
|
|
|
|
|
|
// XXX if (OB_SUPPORT_MATERIAL(ob)) {
|
|
|
|
// strcat(str, "|Texture Space%x17");
|
|
|
|
// }
|
|
|
|
|
|
|
|
if(ob->type == OB_FONT) strcat(str, "|Font Settings%x18|Bevel Settings%x19");
|
|
|
|
if(ob->type == OB_CURVE) strcat(str, "|Bevel Settings%x19|UV Orco%x28");
|
|
|
|
|
|
|
|
if((ob->type == OB_FONT) || (ob->type == OB_CURVE)) {
|
|
|
|
strcat(str, "|Curve Resolution%x25");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ob->type==OB_MESH){
|
|
|
|
strcat(str, "|Subsurf Settings%x21|AutoSmooth%x27");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ob->soft) strcat(str, "|Soft Body Settings%x23");
|
|
|
|
|
|
|
|
strcat(str, "|Pass Index%x30");
|
|
|
|
|
|
|
|
if(ob->type==OB_MESH || ob->type==OB_CURVE || ob->type==OB_LATTICE || ob->type==OB_SURF){
|
|
|
|
strcat(str, "|Modifiers ...%x24");
|
|
|
|
}
|
|
|
|
|
|
|
|
event= pupmenu(str);
|
|
|
|
if(event<= 0) return;
|
|
|
|
|
|
|
|
copy_attr(scene, v3d, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void link_to_scene(unsigned short nr)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
Scene *sce= (Scene*) BLI_findlink(&G.main->scene, G.curscreen->scenenr-1);
|
|
|
|
Base *base, *nbase;
|
|
|
|
|
|
|
|
if(sce==0) return;
|
|
|
|
if(sce->id.lib) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASE(v3d, base)) {
|
|
|
|
|
|
|
|
nbase= MEM_mallocN( sizeof(Base), "newbase");
|
|
|
|
*nbase= *base;
|
|
|
|
BLI_addhead( &(sce->base), nbase);
|
|
|
|
id_us_plus((ID *)base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void make_links(Scene *scene, View3D *v3d, short event)
|
|
|
|
{
|
|
|
|
Object *ob, *obt;
|
|
|
|
Base *base, *nbase, *sbase;
|
|
|
|
Scene *sce = NULL;
|
|
|
|
ID *id;
|
|
|
|
int a;
|
|
|
|
short nr=0;
|
|
|
|
char *strp;
|
|
|
|
|
|
|
|
if(!(ob=OBACT)) return;
|
|
|
|
|
|
|
|
if(event==1) {
|
|
|
|
IDnames_to_pupstring(&strp, NULL, NULL, &(G.main->scene), 0, &nr);
|
|
|
|
|
|
|
|
if(nr == -2) {
|
|
|
|
MEM_freeN(strp);
|
|
|
|
|
|
|
|
// XXX activate_databrowse((ID *)scene, ID_SCE, 0, B_INFOSCE, &(G.curscreen->scenenr), link_to_scene );
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
event= pupmenu_col(strp, 20);
|
|
|
|
MEM_freeN(strp);
|
|
|
|
|
|
|
|
if(event<= 0) return;
|
|
|
|
|
|
|
|
nr= 1;
|
|
|
|
sce= G.main->scene.first;
|
|
|
|
while(sce) {
|
|
|
|
if(nr==event) break;
|
|
|
|
nr++;
|
|
|
|
sce= sce->id.next;
|
|
|
|
}
|
|
|
|
if(sce==scene) {
|
|
|
|
error("This is the current scene");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(sce==0 || sce->id.lib) return;
|
|
|
|
|
|
|
|
/* remember: is needed below */
|
|
|
|
event= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All non group linking */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(event==1 || base != BASACT) {
|
|
|
|
|
|
|
|
obt= base->object;
|
|
|
|
|
|
|
|
if(TESTBASE(v3d, base)) {
|
|
|
|
|
|
|
|
if(event==1) { /* to scene */
|
|
|
|
|
|
|
|
/* test if already linked */
|
|
|
|
sbase= sce->base.first;
|
|
|
|
while(sbase) {
|
|
|
|
if(sbase->object==base->object) break;
|
|
|
|
sbase= sbase->next;
|
|
|
|
}
|
|
|
|
if(sbase) { /* remove */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
nbase= MEM_mallocN( sizeof(Base), "newbase");
|
|
|
|
*nbase= *base;
|
|
|
|
BLI_addhead( &(sce->base), nbase);
|
|
|
|
id_us_plus((ID *)base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(event==2 || event==5) { /* obdata */
|
|
|
|
if(ob->type==obt->type) {
|
|
|
|
|
|
|
|
id= obt->data;
|
|
|
|
id->us--;
|
|
|
|
|
|
|
|
id= ob->data;
|
|
|
|
id_us_plus(id);
|
|
|
|
obt->data= id;
|
|
|
|
|
|
|
|
/* if amount of material indices changed: */
|
|
|
|
test_object_materials(obt->data);
|
|
|
|
|
|
|
|
obt->recalc |= OB_RECALC_DATA;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==4) { /* ob ipo */
|
|
|
|
if(obt->ipo) obt->ipo->id.us--;
|
|
|
|
obt->ipo= ob->ipo;
|
|
|
|
if(obt->ipo) {
|
|
|
|
id_us_plus((ID *)obt->ipo);
|
2009-01-04 14:14:06 +00:00
|
|
|
do_ob_ipo(scene, obt);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==6) {
|
|
|
|
if(ob->dup_group) ob->dup_group->id.us--;
|
|
|
|
obt->dup_group= ob->dup_group;
|
|
|
|
if(obt->dup_group) {
|
|
|
|
id_us_plus((ID *)obt->dup_group);
|
|
|
|
obt->transflag |= OB_DUPLIGROUP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(event==3) { /* materials */
|
|
|
|
|
|
|
|
/* new approach, using functions from kernel */
|
|
|
|
for(a=0; a<ob->totcol; a++) {
|
|
|
|
Material *ma= give_current_material(ob, a+1);
|
|
|
|
assign_material(obt, ma, a+1); /* also works with ma==NULL */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
allqueue(REDRAWBUTSHEAD, 0);
|
|
|
|
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
|
|
|
BIF_undo_push("Create links");
|
|
|
|
}
|
|
|
|
|
|
|
|
void make_links_menu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
short event=0;
|
|
|
|
char str[140];
|
|
|
|
|
|
|
|
if(!(ob=OBACT)) return;
|
|
|
|
|
|
|
|
strcpy(str, "Make Links %t|To Scene...%x1|%l|Object Ipo%x4");
|
|
|
|
|
|
|
|
if(ob->type==OB_MESH)
|
|
|
|
strcat(str, "|Mesh Data%x2|Materials%x3");
|
|
|
|
else if(ob->type==OB_CURVE)
|
|
|
|
strcat(str, "|Curve Data%x2|Materials%x3");
|
|
|
|
else if(ob->type==OB_FONT)
|
|
|
|
strcat(str, "|Text Data%x2|Materials%x3");
|
|
|
|
else if(ob->type==OB_SURF)
|
|
|
|
strcat(str, "|Surface Data%x2|Materials%x3");
|
|
|
|
else if(ob->type==OB_MBALL)
|
|
|
|
strcat(str, "|Materials%x3");
|
|
|
|
else if(ob->type==OB_CAMERA)
|
|
|
|
strcat(str, "|Camera Data%x2");
|
|
|
|
else if(ob->type==OB_LAMP)
|
|
|
|
strcat(str, "|Lamp Data%x2");
|
|
|
|
else if(ob->type==OB_LATTICE)
|
|
|
|
strcat(str, "|Lattice Data%x2");
|
|
|
|
else if(ob->type==OB_ARMATURE)
|
|
|
|
strcat(str, "|Armature Data%x2");
|
|
|
|
|
|
|
|
event= pupmenu(str);
|
|
|
|
|
|
|
|
if(event<= 0) return;
|
|
|
|
|
|
|
|
make_links(scene, v3d, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void apply_objects_internal(Scene *scene, View3D *v3d, int apply_scale, int apply_rot )
|
|
|
|
{
|
|
|
|
Base *base, *basact;
|
|
|
|
Object *ob;
|
|
|
|
bArmature *arm;
|
|
|
|
Mesh *me;
|
|
|
|
Curve *cu;
|
|
|
|
Nurb *nu;
|
|
|
|
BPoint *bp;
|
|
|
|
BezTriple *bezt;
|
|
|
|
MVert *mvert;
|
|
|
|
float mat[3][3];
|
|
|
|
int a, change = 0;
|
|
|
|
|
|
|
|
if (!apply_scale && !apply_rot) {
|
|
|
|
/* do nothing? */
|
|
|
|
error("Nothing to do!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* first check if we can execute */
|
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->type==OB_MESH) {
|
|
|
|
me= ob->data;
|
|
|
|
|
|
|
|
if(me->id.us>1) {
|
|
|
|
error("Can't apply to a multi user mesh, doing nothing.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ob->type==OB_ARMATURE) {
|
|
|
|
arm= ob->data;
|
|
|
|
|
|
|
|
if(arm->id.us>1) {
|
|
|
|
error("Can't apply to a multi user armature, doing nothing.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
|
|
|
|
cu= ob->data;
|
|
|
|
|
|
|
|
if(cu->id.us>1) {
|
|
|
|
error("Can't apply to a multi user curve, doing nothing.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(cu->key) {
|
|
|
|
error("Can't apply to a curve with vertex keys, doing nothing.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now execute */
|
|
|
|
basact= BASACT;
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
ob= base->object;
|
|
|
|
|
|
|
|
if(ob->type==OB_MESH) {
|
|
|
|
/* calculate matrix */
|
|
|
|
if (apply_scale && apply_rot)
|
|
|
|
object_to_mat3(ob, mat);
|
|
|
|
else if (apply_scale)
|
|
|
|
object_scale_to_mat3(ob, mat);
|
|
|
|
else
|
|
|
|
object_rot_to_mat3(ob, mat);
|
|
|
|
|
|
|
|
/* get object data */
|
|
|
|
me= ob->data;
|
|
|
|
|
|
|
|
/* adjust data */
|
|
|
|
mvert= me->mvert;
|
|
|
|
for(a=0; a<me->totvert; a++, mvert++) {
|
|
|
|
Mat3MulVecfl(mat, mvert->co);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (me->key) {
|
|
|
|
KeyBlock *kb;
|
|
|
|
|
|
|
|
for (kb=me->key->block.first; kb; kb=kb->next) {
|
|
|
|
float *fp= kb->data;
|
|
|
|
|
|
|
|
for (a=0; a<kb->totelem; a++, fp+=3)
|
|
|
|
Mat3MulVecfl(mat, fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* adjust transforms */
|
|
|
|
if (apply_scale)
|
|
|
|
ob->size[0]= ob->size[1]= ob->size[2]= 1.0f;
|
|
|
|
if (apply_rot)
|
|
|
|
ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0f;
|
|
|
|
/*QuatOne(ob->quat);*/ /* Quats arnt used yet */
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* texspace and normals */
|
|
|
|
BASACT= base;
|
2009-01-01 18:05:12 +00:00
|
|
|
// XXX ED_object_enter_editmode(C, 0);
|
2008-12-23 19:47:33 +00:00
|
|
|
BIF_undo_push("Applied object"); /* editmode undo itself */
|
2009-01-01 18:05:12 +00:00
|
|
|
// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
|
2008-12-23 19:47:33 +00:00
|
|
|
BASACT= basact;
|
|
|
|
|
|
|
|
change = 1;
|
|
|
|
}
|
|
|
|
else if (ob->type==OB_ARMATURE) {
|
|
|
|
if (apply_scale && apply_rot)
|
|
|
|
object_to_mat3(ob, mat);
|
|
|
|
else if (apply_scale)
|
|
|
|
object_scale_to_mat3(ob, mat);
|
|
|
|
else
|
|
|
|
object_rot_to_mat3(ob, mat);
|
|
|
|
arm= ob->data;
|
|
|
|
|
|
|
|
/* see checks above */
|
|
|
|
// XXX apply_rot_armature(ob, mat);
|
|
|
|
|
|
|
|
/* Reset the object's transforms */
|
|
|
|
if (apply_scale)
|
|
|
|
ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
|
|
|
|
if (apply_rot)
|
|
|
|
ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
|
|
|
|
/*QuatOne(ob->quat); (not used anymore)*/
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
change = 1;
|
|
|
|
}
|
|
|
|
else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
|
|
|
|
float scale;
|
|
|
|
if (apply_scale && apply_rot)
|
|
|
|
object_to_mat3(ob, mat);
|
|
|
|
else if (apply_scale)
|
|
|
|
object_scale_to_mat3(ob, mat);
|
|
|
|
else
|
|
|
|
object_rot_to_mat3(ob, mat);
|
|
|
|
scale = Mat3ToScalef(mat);
|
|
|
|
cu= ob->data;
|
|
|
|
|
|
|
|
/* see checks above */
|
|
|
|
|
|
|
|
nu= cu->nurb.first;
|
|
|
|
while(nu) {
|
|
|
|
if( (nu->type & 7)==1) {
|
|
|
|
a= nu->pntsu;
|
|
|
|
bezt= nu->bezt;
|
|
|
|
while(a--) {
|
|
|
|
Mat3MulVecfl(mat, bezt->vec[0]);
|
|
|
|
Mat3MulVecfl(mat, bezt->vec[1]);
|
|
|
|
Mat3MulVecfl(mat, bezt->vec[2]);
|
|
|
|
bezt->radius *= scale;
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
bp= nu->bp;
|
|
|
|
while(a--) {
|
|
|
|
Mat3MulVecfl(mat, bp->vec);
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nu= nu->next;
|
|
|
|
}
|
|
|
|
if (apply_scale)
|
|
|
|
ob->size[0]= ob->size[1]= ob->size[2]= 1.0;
|
|
|
|
if (apply_rot)
|
|
|
|
ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0;
|
|
|
|
/*QuatOne(ob->quat); (quats arnt used anymore)*/
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
/* texspace and normals */
|
|
|
|
BASACT= base;
|
2009-01-01 18:05:12 +00:00
|
|
|
// XXX ED_object_enter_editmode(C, 0);
|
2008-12-23 19:47:33 +00:00
|
|
|
BIF_undo_push("Applied object"); /* editmode undo itself */
|
2009-01-01 18:05:12 +00:00
|
|
|
// XXX ED_object_exit_editmode(C, EM_FREEDATA|EM_WAITCURSOR); /* freedata, but no undo */
|
2008-12-23 19:47:33 +00:00
|
|
|
BASACT= basact;
|
|
|
|
|
|
|
|
change = 1;
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
ignore_parent_tx(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (change) {
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
if (apply_scale && apply_rot)
|
|
|
|
BIF_undo_push("Apply Objects Scale & Rotation");
|
|
|
|
else if (apply_scale)
|
|
|
|
BIF_undo_push("Apply Objects Scale");
|
|
|
|
else
|
|
|
|
BIF_undo_push("Apply Objects Rotation");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void apply_objects_locrot(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
apply_objects_internal(scene, v3d, 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void apply_objects_scale(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
apply_objects_internal(scene, v3d, 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void apply_objects_rot(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
apply_objects_internal(scene, v3d, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void apply_objects_visual_tx( Scene *scene, View3D *v3d )
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
int change = 0;
|
|
|
|
|
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
ob= base->object;
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
VECCOPY(ob->loc, ob->obmat[3]);
|
|
|
|
Mat4ToSize(ob->obmat, ob->size);
|
|
|
|
Mat4ToEul(ob->obmat, ob->rot);
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
change = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (change) {
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
BIF_undo_push("Apply Objects Visual Transform");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void single_object_users__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
|
|
|
|
{
|
|
|
|
ID_NEW(*obpoin);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void copy_object__forwardModifierLinks(void *userData, Object *ob,
|
|
|
|
ID **idpoin)
|
|
|
|
{
|
|
|
|
/* this is copied from ID_NEW; it might be better to have a macro */
|
|
|
|
if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* after copying objects, copied data should get new pointers */
|
|
|
|
static void copy_object_set_idnew(Scene *scene, View3D *v3d, int dupflag)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
Material *ma, *mao;
|
|
|
|
ID *id;
|
|
|
|
Ipo *ipo;
|
|
|
|
bActionStrip *strip;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
/* check object pointers */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
ob= base->object;
|
|
|
|
relink_constraints(&ob->constraints);
|
|
|
|
if (ob->pose){
|
|
|
|
bPoseChannel *chan;
|
|
|
|
for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
|
|
|
|
relink_constraints(&chan->constraints);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
modifiers_foreachIDLink(ob, copy_object__forwardModifierLinks, NULL);
|
|
|
|
ID_NEW(ob->parent);
|
|
|
|
ID_NEW(ob->track);
|
|
|
|
ID_NEW(ob->proxy);
|
|
|
|
ID_NEW(ob->proxy_group);
|
|
|
|
|
|
|
|
for(strip= ob->nlastrips.first; strip; strip= strip->next) {
|
|
|
|
bActionModifier *amod;
|
|
|
|
for(amod= strip->modifiers.first; amod; amod= amod->next)
|
|
|
|
ID_NEW(amod->ob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* materials */
|
|
|
|
if( dupflag & USER_DUP_MAT) {
|
|
|
|
mao= G.main->mat.first;
|
|
|
|
while(mao) {
|
|
|
|
if(mao->id.newid) {
|
|
|
|
|
|
|
|
ma= (Material *)mao->id.newid;
|
|
|
|
|
|
|
|
if(dupflag & USER_DUP_TEX) {
|
|
|
|
for(a=0; a<MAX_MTEX; a++) {
|
|
|
|
if(ma->mtex[a]) {
|
|
|
|
id= (ID *)ma->mtex[a]->tex;
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US(ma->mtex[a]->tex)
|
|
|
|
else ma->mtex[a]->tex= copy_texture(ma->mtex[a]->tex);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
id= (ID *)ma->ipo;
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US(ma->ipo)
|
|
|
|
else ma->ipo= copy_ipo(ma->ipo);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mao= mao->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lamps */
|
|
|
|
if( dupflag & USER_DUP_IPO) {
|
|
|
|
Lamp *la= G.main->lamp.first;
|
|
|
|
while(la) {
|
|
|
|
if(la->id.newid) {
|
|
|
|
Lamp *lan= (Lamp *)la->id.newid;
|
|
|
|
id= (ID *)lan->ipo;
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US(lan->ipo)
|
|
|
|
else lan->ipo= copy_ipo(lan->ipo);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
la= la->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ipos */
|
|
|
|
ipo= G.main->ipo.first;
|
|
|
|
while(ipo) {
|
|
|
|
if(ipo->id.lib==NULL && ipo->id.newid) {
|
|
|
|
Ipo *ipon= (Ipo *)ipo->id.newid;
|
|
|
|
IpoCurve *icu;
|
|
|
|
for(icu= ipon->curve.first; icu; icu= icu->next) {
|
|
|
|
if(icu->driver) {
|
|
|
|
ID_NEW(icu->driver->ob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ipo= ipo->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_sca_new_poins();
|
|
|
|
|
|
|
|
clear_id_newpoins();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void make_object_duplilist_real(Scene *scene, View3D *v3d, Base *base)
|
|
|
|
{
|
|
|
|
Base *basen;
|
|
|
|
Object *ob;
|
|
|
|
ListBase *lb;
|
|
|
|
DupliObject *dob;
|
|
|
|
|
|
|
|
if(!base && !(base = BASACT))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(!(base->object->transflag & OB_DUPLI))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lb= object_duplilist(scene, base->object);
|
|
|
|
|
|
|
|
for(dob= lb->first; dob; dob= dob->next) {
|
|
|
|
ob= copy_object(dob->ob);
|
|
|
|
/* font duplis can have a totcol without material, we get them from parent
|
|
|
|
* should be implemented better...
|
|
|
|
*/
|
|
|
|
if(ob->mat==NULL) ob->totcol= 0;
|
|
|
|
|
|
|
|
basen= MEM_dupallocN(base);
|
|
|
|
basen->flag &= ~OB_FROMDUPLI;
|
|
|
|
BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
|
|
|
|
basen->object= ob;
|
|
|
|
ob->ipo= NULL; /* make sure apply works */
|
|
|
|
ob->parent= ob->track= NULL;
|
|
|
|
ob->disp.first= ob->disp.last= NULL;
|
|
|
|
ob->transflag &= ~OB_DUPLI;
|
|
|
|
|
|
|
|
Mat4CpyMat4(ob->obmat, dob->mat);
|
2009-01-05 15:19:31 +00:00
|
|
|
ED_object_apply_obmat(ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
copy_object_set_idnew(scene, v3d, 0);
|
|
|
|
|
|
|
|
free_object_duplilist(lb);
|
|
|
|
|
|
|
|
base->object->transflag &= ~OB_DUPLI;
|
|
|
|
}
|
|
|
|
|
|
|
|
void make_duplilist_real(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
/* extern ListBase duplilist; */
|
|
|
|
|
|
|
|
if(okee("Make dupli objects real")==0) return;
|
|
|
|
|
|
|
|
clear_id_newpoins();
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASE(v3d, base)) {
|
|
|
|
make_object_duplilist_real(scene, v3d, base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("Make duplicates real");
|
|
|
|
}
|
|
|
|
|
|
|
|
void apply_object(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
int evt;
|
|
|
|
int shift= 0;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) return; // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
if(shift) {
|
|
|
|
ob= OBACT;
|
|
|
|
if(ob==0) return;
|
|
|
|
|
|
|
|
if(ob->transflag & OB_DUPLI) {
|
|
|
|
make_duplilist_real(scene, v3d);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(okee("Apply deformation")) {
|
|
|
|
// XXX object_apply_deform(ob);
|
|
|
|
BIF_undo_push("Apply deformation");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ob= OBACT;
|
|
|
|
if(ob==0) return;
|
|
|
|
|
|
|
|
if ((ob->pose) && (ob->flag & OB_POSEMODE))
|
|
|
|
evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3");
|
|
|
|
else
|
|
|
|
evt = pupmenu("Apply Object%t|Scale and Rotation to ObData%x1|Visual Transform to Objects Loc/Scale/Rot%x2|Scale to ObData%x4|Rotation to ObData%x5");
|
|
|
|
if (evt==-1) return;
|
|
|
|
|
|
|
|
switch (evt) {
|
|
|
|
case 1:
|
|
|
|
apply_objects_locrot(scene, v3d);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
apply_objects_visual_tx(scene, v3d);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// XXX apply_armature_pose2bones();
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
apply_objects_scale(scene, v3d);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
apply_objects_rot(scene, v3d);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ************************************** */
|
|
|
|
|
|
|
|
|
|
|
|
void single_object_users(Scene *scene, View3D *v3d, int flag)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
Object *ob, *obn;
|
|
|
|
|
|
|
|
clear_sca_new_poins(); /* sensor/contr/act */
|
|
|
|
|
|
|
|
/* duplicate (must set newid) */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
ob= base->object;
|
|
|
|
|
|
|
|
if( (base->flag & flag)==flag ) {
|
|
|
|
if(ob->id.lib==NULL && ob->id.us>1) {
|
|
|
|
/* base gets copy of object */
|
|
|
|
obn= copy_object(ob);
|
|
|
|
base->object= obn;
|
|
|
|
ob->id.us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ID_NEW(scene->camera);
|
|
|
|
if(v3d) ID_NEW(v3d->camera);
|
|
|
|
|
|
|
|
/* object pointers */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->id.lib==NULL) {
|
|
|
|
relink_constraints(&base->object->constraints);
|
|
|
|
if (base->object->pose){
|
|
|
|
bPoseChannel *chan;
|
|
|
|
for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){
|
|
|
|
relink_constraints(&chan->constraints);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
modifiers_foreachObjectLink(base->object, single_object_users__forwardModifierLinks, NULL);
|
|
|
|
|
|
|
|
ID_NEW(ob->parent);
|
|
|
|
ID_NEW(ob->track);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_sca_new_poins();
|
|
|
|
}
|
|
|
|
|
|
|
|
void new_id_matar(Material **matar, int totcol)
|
|
|
|
{
|
|
|
|
ID *id;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
for(a=0; a<totcol; a++) {
|
|
|
|
id= (ID *)matar[a];
|
|
|
|
if(id && id->lib==0) {
|
|
|
|
if(id->newid) {
|
|
|
|
matar[a]= (Material *)id->newid;
|
|
|
|
id_us_plus(id->newid);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
else if(id->us>1) {
|
|
|
|
matar[a]= copy_material(matar[a]);
|
|
|
|
id->us--;
|
|
|
|
id->newid= (ID *)matar[a];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void single_obdata_users(Scene *scene, View3D *v3d, int flag)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Lamp *la;
|
|
|
|
Curve *cu;
|
|
|
|
Camera *cam;
|
|
|
|
Base *base;
|
|
|
|
Mesh *me;
|
|
|
|
ID *id;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->id.lib==NULL && (base->flag & flag)==flag ) {
|
|
|
|
id= ob->data;
|
|
|
|
|
|
|
|
if(id && id->us>1 && id->lib==0) {
|
|
|
|
ob->recalc= OB_RECALC_DATA;
|
|
|
|
|
|
|
|
switch(ob->type) {
|
|
|
|
case OB_LAMP:
|
|
|
|
if(id && id->us>1 && id->lib==NULL) {
|
|
|
|
ob->data= la= copy_lamp(ob->data);
|
|
|
|
for(a=0; a<MAX_MTEX; a++) {
|
|
|
|
if(la->mtex[a]) {
|
|
|
|
ID_NEW(la->mtex[a]->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_CAMERA:
|
|
|
|
ob->data= copy_camera(ob->data);
|
|
|
|
break;
|
|
|
|
case OB_MESH:
|
|
|
|
me= ob->data= copy_mesh(ob->data);
|
|
|
|
if(me && me->key)
|
|
|
|
ipo_idnew(me->key->ipo); /* drivers */
|
|
|
|
break;
|
|
|
|
case OB_MBALL:
|
|
|
|
ob->data= copy_mball(ob->data);
|
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
|
|
|
case OB_FONT:
|
|
|
|
ob->data= cu= copy_curve(ob->data);
|
|
|
|
ID_NEW(cu->bevobj);
|
|
|
|
ID_NEW(cu->taperobj);
|
|
|
|
break;
|
|
|
|
case OB_LATTICE:
|
|
|
|
ob->data= copy_lattice(ob->data);
|
|
|
|
break;
|
|
|
|
case OB_ARMATURE:
|
|
|
|
ob->recalc |= OB_RECALC_DATA;
|
|
|
|
ob->data= copy_armature(ob->data);
|
|
|
|
armature_rebuild_pose(ob, ob->data);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("ERROR single_obdata_users: %s\n", id->name);
|
|
|
|
error("Read console");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
id->us--;
|
|
|
|
id->newid= ob->data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
id= (ID *)ob->action;
|
|
|
|
if (id && id->us>1 && id->lib==NULL){
|
|
|
|
if(id->newid){
|
|
|
|
ob->action= (bAction *)id->newid;
|
|
|
|
id_us_plus(id->newid);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ob->action= copy_action(ob->action);
|
|
|
|
id->us--;
|
|
|
|
id->newid=(ID *)ob->action;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
id= (ID *)ob->ipo;
|
|
|
|
if(id && id->us>1 && id->lib==NULL) {
|
|
|
|
if(id->newid) {
|
|
|
|
ob->ipo= (Ipo *)id->newid;
|
|
|
|
id_us_plus(id->newid);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ob->ipo= copy_ipo(ob->ipo);
|
|
|
|
id->us--;
|
|
|
|
id->newid= (ID *)ob->ipo;
|
|
|
|
}
|
|
|
|
ipo_idnew(ob->ipo); /* drivers */
|
|
|
|
}
|
|
|
|
/* other ipos */
|
|
|
|
switch(ob->type) {
|
|
|
|
case OB_LAMP:
|
|
|
|
la= ob->data;
|
|
|
|
if(la->ipo && la->ipo->id.us>1) {
|
|
|
|
la->ipo->id.us--;
|
|
|
|
la->ipo= copy_ipo(la->ipo);
|
|
|
|
ipo_idnew(la->ipo); /* drivers */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_CAMERA:
|
|
|
|
cam= ob->data;
|
|
|
|
if(cam->ipo && cam->ipo->id.us>1) {
|
|
|
|
cam->ipo->id.us--;
|
|
|
|
cam->ipo= copy_ipo(cam->ipo);
|
|
|
|
ipo_idnew(cam->ipo); /* drivers */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
me= G.main->mesh.first;
|
|
|
|
while(me) {
|
|
|
|
ID_NEW(me->texcomesh);
|
|
|
|
me= me->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void single_ipo_users(Scene *scene, View3D *v3d, int flag)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Base *base;
|
|
|
|
ID *id;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
|
|
|
|
ob->recalc= OB_RECALC_DATA;
|
|
|
|
|
|
|
|
id= (ID *)ob->ipo;
|
|
|
|
if(id && id->us>1 && id->lib==NULL) {
|
|
|
|
ob->ipo= copy_ipo(ob->ipo);
|
|
|
|
id->us--;
|
|
|
|
ipo_idnew(ob->ipo); /* drivers */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void single_mat_users(Scene *scene, View3D *v3d, int flag)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Base *base;
|
|
|
|
Material *ma, *man;
|
|
|
|
Tex *tex;
|
|
|
|
int a, b;
|
|
|
|
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->id.lib==NULL && (flag==0 || (base->flag & SELECT)) ) {
|
|
|
|
|
|
|
|
for(a=1; a<=ob->totcol; a++) {
|
|
|
|
ma= give_current_material(ob, a);
|
|
|
|
if(ma) {
|
|
|
|
/* do not test for LIB_NEW: this functions guaranteed delivers single_users! */
|
|
|
|
|
|
|
|
if(ma->id.us>1) {
|
|
|
|
man= copy_material(ma);
|
|
|
|
|
|
|
|
man->id.us= 0;
|
|
|
|
assign_material(ob, man, a);
|
|
|
|
|
|
|
|
if(ma->ipo) {
|
|
|
|
man->ipo= copy_ipo(ma->ipo);
|
|
|
|
ma->ipo->id.us--;
|
|
|
|
ipo_idnew(ma->ipo); /* drivers */
|
|
|
|
}
|
|
|
|
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(ma->mtex[b] && ma->mtex[b]->tex) {
|
|
|
|
tex= ma->mtex[b]->tex;
|
|
|
|
if(tex->id.us>1) {
|
|
|
|
ma->mtex[b]->tex= copy_texture(tex);
|
|
|
|
tex->id.us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_single_tex_user(Tex **from)
|
|
|
|
{
|
|
|
|
Tex *tex, *texn;
|
|
|
|
|
|
|
|
tex= *from;
|
|
|
|
if(tex==0) return;
|
|
|
|
|
|
|
|
if(tex->id.newid) {
|
|
|
|
*from= (Tex *)tex->id.newid;
|
|
|
|
id_us_plus(tex->id.newid);
|
|
|
|
tex->id.us--;
|
|
|
|
}
|
|
|
|
else if(tex->id.us>1) {
|
|
|
|
texn= copy_texture(tex);
|
|
|
|
tex->id.newid= (ID *)texn;
|
|
|
|
tex->id.us--;
|
|
|
|
*from= texn;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void single_tex_users_expand()
|
|
|
|
{
|
|
|
|
/* only when 'parent' blocks are LIB_NEW */
|
|
|
|
Material *ma;
|
|
|
|
Lamp *la;
|
|
|
|
World *wo;
|
|
|
|
int b;
|
|
|
|
|
|
|
|
ma= G.main->mat.first;
|
|
|
|
while(ma) {
|
|
|
|
if(ma->id.flag & LIB_NEW) {
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(ma->mtex[b] && ma->mtex[b]->tex) {
|
|
|
|
do_single_tex_user( &(ma->mtex[b]->tex) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ma= ma->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
la= G.main->lamp.first;
|
|
|
|
while(la) {
|
|
|
|
if(la->id.flag & LIB_NEW) {
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(la->mtex[b] && la->mtex[b]->tex) {
|
|
|
|
do_single_tex_user( &(la->mtex[b]->tex) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
la= la->id.next;
|
|
|
|
}
|
|
|
|
wo= G.main->world.first;
|
|
|
|
while(wo) {
|
|
|
|
if(wo->id.flag & LIB_NEW) {
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(wo->mtex[b] && wo->mtex[b]->tex) {
|
|
|
|
do_single_tex_user( &(wo->mtex[b]->tex) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wo= wo->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void single_mat_users_expand(void)
|
|
|
|
{
|
|
|
|
/* only when 'parent' blocks are LIB_NEW */
|
|
|
|
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
Curve *cu;
|
|
|
|
MetaBall *mb;
|
|
|
|
Material *ma;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
ob= G.main->object.first;
|
|
|
|
while(ob) {
|
|
|
|
if(ob->id.flag & LIB_NEW) {
|
|
|
|
new_id_matar(ob->mat, ob->totcol);
|
|
|
|
}
|
|
|
|
ob= ob->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
me= G.main->mesh.first;
|
|
|
|
while(me) {
|
|
|
|
if(me->id.flag & LIB_NEW) {
|
|
|
|
new_id_matar(me->mat, me->totcol);
|
|
|
|
}
|
|
|
|
me= me->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
cu= G.main->curve.first;
|
|
|
|
while(cu) {
|
|
|
|
if(cu->id.flag & LIB_NEW) {
|
|
|
|
new_id_matar(cu->mat, cu->totcol);
|
|
|
|
}
|
|
|
|
cu= cu->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
mb= G.main->mball.first;
|
|
|
|
while(mb) {
|
|
|
|
if(mb->id.flag & LIB_NEW) {
|
|
|
|
new_id_matar(mb->mat, mb->totcol);
|
|
|
|
}
|
|
|
|
mb= mb->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* material imats */
|
|
|
|
ma= G.main->mat.first;
|
|
|
|
while(ma) {
|
|
|
|
if(ma->id.flag & LIB_NEW) {
|
|
|
|
for(a=0; a<MAX_MTEX; a++) {
|
|
|
|
if(ma->mtex[a]) {
|
|
|
|
ID_NEW(ma->mtex[a]->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ma= ma->id.next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void single_user(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
int nr;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
clear_id_newpoins();
|
|
|
|
|
|
|
|
nr= pupmenu("Make Single User%t|Object|Object & ObData|Object & ObData & Materials+Tex|Materials+Tex|Ipos");
|
|
|
|
if(nr>0) {
|
|
|
|
|
|
|
|
if(nr==1) single_object_users(scene, v3d, 1);
|
|
|
|
|
|
|
|
else if(nr==2) {
|
|
|
|
single_object_users(scene, v3d, 1);
|
|
|
|
single_obdata_users(scene, v3d, 1);
|
|
|
|
}
|
|
|
|
else if(nr==3) {
|
|
|
|
single_object_users(scene, v3d, 1);
|
|
|
|
single_obdata_users(scene, v3d, 1);
|
|
|
|
single_mat_users(scene, v3d, 1); /* also tex */
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(nr==4) {
|
|
|
|
single_mat_users(scene, v3d, 1);
|
|
|
|
}
|
|
|
|
else if(nr==5) {
|
|
|
|
single_ipo_users(scene, v3d, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
clear_id_newpoins();
|
|
|
|
|
|
|
|
allqueue(REDRAWALL, 0);
|
|
|
|
BIF_undo_push("Single user");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************* */
|
|
|
|
|
|
|
|
/* helper for below, ma was checked to be not NULL */
|
|
|
|
static void make_local_makelocalmaterial(Material *ma)
|
|
|
|
{
|
|
|
|
ID *id;
|
|
|
|
int b;
|
|
|
|
|
|
|
|
make_local_material(ma);
|
|
|
|
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(ma->mtex[b] && ma->mtex[b]->tex) {
|
|
|
|
make_local_texture(ma->mtex[b]->tex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
id= (ID *)ma->ipo;
|
|
|
|
if(id && id->lib) make_local_ipo(ma->ipo);
|
|
|
|
|
|
|
|
/* nodetree? XXX */
|
|
|
|
}
|
|
|
|
|
|
|
|
void make_local(Scene *scene, View3D *v3d, int mode)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
bActionStrip *strip;
|
|
|
|
ParticleSystem *psys;
|
|
|
|
Material *ma, ***matarar;
|
|
|
|
Lamp *la;
|
|
|
|
Curve *cu;
|
|
|
|
ID *id;
|
|
|
|
int a, b;
|
|
|
|
|
|
|
|
/* WATCH: the function new_id(..) re-inserts the id block!!! */
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
if(mode==3) {
|
|
|
|
all_local(NULL, 0); /* NULL is all libs */
|
|
|
|
allqueue(REDRAWALL, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(mode<1) return;
|
|
|
|
|
|
|
|
clear_id_newpoins();
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if( TESTBASE(v3d, base) ) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->id.lib) {
|
|
|
|
make_local_object(ob);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* maybe object pointers */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if( TESTBASE(v3d, base) ) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->id.lib==NULL) {
|
|
|
|
ID_NEW(ob->parent);
|
|
|
|
ID_NEW(ob->track);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if( TESTBASE(v3d, base) ) {
|
|
|
|
ob= base->object;
|
|
|
|
id= ob->data;
|
|
|
|
|
|
|
|
if(id && mode>1) {
|
|
|
|
|
|
|
|
switch(ob->type) {
|
|
|
|
case OB_LAMP:
|
|
|
|
make_local_lamp((Lamp *)id);
|
|
|
|
|
|
|
|
la= ob->data;
|
|
|
|
id= (ID *)la->ipo;
|
|
|
|
if(id && id->lib) make_local_ipo(la->ipo);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OB_CAMERA:
|
|
|
|
make_local_camera((Camera *)id);
|
|
|
|
break;
|
|
|
|
case OB_MESH:
|
|
|
|
make_local_mesh((Mesh *)id);
|
|
|
|
make_local_key( ((Mesh *)id)->key );
|
|
|
|
break;
|
|
|
|
case OB_MBALL:
|
|
|
|
make_local_mball((MetaBall *)id);
|
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
|
|
|
case OB_FONT:
|
|
|
|
cu= (Curve *)id;
|
|
|
|
make_local_curve(cu);
|
|
|
|
id= (ID *)cu->ipo;
|
|
|
|
if(id && id->lib) make_local_ipo(cu->ipo);
|
|
|
|
make_local_key( cu->key );
|
|
|
|
break;
|
|
|
|
case OB_LATTICE:
|
|
|
|
make_local_lattice((Lattice *)id);
|
|
|
|
make_local_key( ((Lattice *)id)->key );
|
|
|
|
break;
|
|
|
|
case OB_ARMATURE:
|
|
|
|
make_local_armature ((bArmature *)id);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(psys=ob->particlesystem.first; psys; psys=psys->next)
|
|
|
|
make_local_particlesettings(psys->part);
|
|
|
|
}
|
|
|
|
id= (ID *)ob->ipo;
|
|
|
|
if(id && id->lib) make_local_ipo(ob->ipo);
|
|
|
|
|
|
|
|
id= (ID *)ob->action;
|
|
|
|
if(id && id->lib) make_local_action(ob->action);
|
|
|
|
|
|
|
|
for(strip=ob->nlastrips.first; strip; strip=strip->next) {
|
|
|
|
if(strip->act && strip->act->id.lib)
|
|
|
|
make_local_action(strip->act);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mode>1) {
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if( TESTBASE(v3d, base) ) {
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->type==OB_LAMP) {
|
|
|
|
la= ob->data;
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(la->mtex[b] && la->mtex[b]->tex) {
|
|
|
|
make_local_texture(la->mtex[b]->tex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
for(a=0; a<ob->totcol; a++) {
|
|
|
|
ma= ob->mat[a];
|
|
|
|
if(ma)
|
|
|
|
make_local_makelocalmaterial(ma);
|
|
|
|
}
|
|
|
|
|
|
|
|
matarar= (Material ***)give_matarar(ob);
|
|
|
|
if (matarar) {
|
|
|
|
for(a=0; a<ob->totcol; a++) {
|
|
|
|
ma= (*matarar)[a];
|
|
|
|
if(ma)
|
|
|
|
make_local_makelocalmaterial(ma);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWALL, 0);
|
|
|
|
BIF_undo_push("Make local");
|
|
|
|
}
|
|
|
|
|
|
|
|
void make_local_menu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
int mode;
|
|
|
|
|
|
|
|
/* If you modify this menu, please remember to update view3d_edit_object_makelocalmenu
|
|
|
|
* in header_view3d.c and the menu in toolbox.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
mode = pupmenu("Make Local%t|Selected Objects %x1|Selected Objects and Data %x2|All %x3");
|
|
|
|
|
|
|
|
if (mode <= 0) return;
|
|
|
|
|
|
|
|
make_local(scene, v3d, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This function duplicated the current visible selection, its used by Duplicate and Linked Duplicate
|
|
|
|
Alt+D/Shift+D as well as Pythons Object.Duplicate(), it takes
|
|
|
|
mode:
|
|
|
|
0: Duplicate with transform, Redraw.
|
|
|
|
1: Duplicate, no transform, Redraw
|
|
|
|
2: Duplicate, no transform, no redraw (Only used by python)
|
|
|
|
if true the user will not be dropped into grab mode directly after and..
|
|
|
|
dupflag: a flag made from constants declared in DNA_userdef_types.h
|
|
|
|
The flag tells adduplicate() weather to copy data linked to the object, or to reference the existing data.
|
|
|
|
U.dupflag for default operations or you can construct a flag as python does
|
|
|
|
if the dupflag is 0 then no data will be copied (linked duplicate) */
|
|
|
|
|
|
|
|
void adduplicate(Scene *scene, View3D *v3d, int mode, int dupflag)
|
|
|
|
{
|
|
|
|
Base *base, *basen;
|
|
|
|
Material ***matarar;
|
|
|
|
Object *ob, *obn;
|
|
|
|
ID *id;
|
|
|
|
int a, didit;
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
clear_id_newpoins();
|
|
|
|
clear_sca_new_poins(); /* sensor/contr/act */
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASE(v3d, base)) {
|
|
|
|
|
|
|
|
ob= base->object;
|
|
|
|
if(ob->flag & OB_POSEMODE) {
|
|
|
|
; /* nothing? */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
obn= copy_object(ob);
|
|
|
|
obn->recalc |= OB_RECALC;
|
|
|
|
|
|
|
|
basen= MEM_mallocN(sizeof(Base), "duplibase");
|
|
|
|
*basen= *base;
|
|
|
|
BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */
|
|
|
|
basen->object= obn;
|
|
|
|
base->flag &= ~SELECT;
|
|
|
|
|
|
|
|
if(basen->flag & OB_FROMGROUP) {
|
|
|
|
Group *group;
|
|
|
|
for(group= G.main->group.first; group; group= group->id.next) {
|
|
|
|
if(object_in_group(ob, group))
|
|
|
|
add_to_group(group, obn);
|
|
|
|
}
|
|
|
|
obn->flag |= OB_FROMGROUP; /* this flag is unset with copy_object() */
|
|
|
|
}
|
|
|
|
|
|
|
|
if(BASACT==base) BASACT= basen;
|
|
|
|
|
|
|
|
/* duplicates using userflags */
|
|
|
|
|
|
|
|
if(dupflag & USER_DUP_IPO) {
|
|
|
|
bConstraintChannel *chan;
|
|
|
|
id= (ID *)obn->ipo;
|
|
|
|
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US( obn->ipo)
|
|
|
|
else obn->ipo= copy_ipo(obn->ipo);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
/* Handle constraint ipos */
|
|
|
|
for (chan=obn->constraintChannels.first; chan; chan=chan->next){
|
|
|
|
id= (ID *)chan->ipo;
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US( chan->ipo)
|
|
|
|
else chan->ipo= copy_ipo(chan->ipo);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(dupflag & USER_DUP_ACT){ /* Not buttons in the UI to modify this, add later? */
|
|
|
|
id= (ID *)obn->action;
|
|
|
|
if (id){
|
|
|
|
ID_NEW_US(obn->action)
|
|
|
|
else{
|
|
|
|
obn->action= copy_action(obn->action);
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(dupflag & USER_DUP_MAT) {
|
|
|
|
for(a=0; a<obn->totcol; a++) {
|
|
|
|
id= (ID *)obn->mat[a];
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US(obn->mat[a])
|
|
|
|
else obn->mat[a]= copy_material(obn->mat[a]);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
id= obn->data;
|
|
|
|
didit= 0;
|
|
|
|
|
|
|
|
switch(obn->type) {
|
|
|
|
case OB_MESH:
|
|
|
|
if(dupflag & USER_DUP_MESH) {
|
|
|
|
ID_NEW_US2( obn->data )
|
|
|
|
else {
|
|
|
|
obn->data= copy_mesh(obn->data);
|
|
|
|
|
|
|
|
if(obn->fluidsimSettings) {
|
|
|
|
obn->fluidsimSettings->orgMesh = (Mesh *)obn->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
didit= 1;
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
if(dupflag & USER_DUP_CURVE) {
|
|
|
|
ID_NEW_US2(obn->data )
|
|
|
|
else {
|
|
|
|
obn->data= copy_curve(obn->data);
|
|
|
|
didit= 1;
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_SURF:
|
|
|
|
if(dupflag & USER_DUP_SURF) {
|
|
|
|
ID_NEW_US2( obn->data )
|
|
|
|
else {
|
|
|
|
obn->data= copy_curve(obn->data);
|
|
|
|
didit= 1;
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_FONT:
|
|
|
|
if(dupflag & USER_DUP_FONT) {
|
|
|
|
ID_NEW_US2( obn->data )
|
|
|
|
else {
|
|
|
|
obn->data= copy_curve(obn->data);
|
|
|
|
didit= 1;
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_MBALL:
|
|
|
|
if(dupflag & USER_DUP_MBALL) {
|
|
|
|
ID_NEW_US2(obn->data )
|
|
|
|
else {
|
|
|
|
obn->data= copy_mball(obn->data);
|
|
|
|
didit= 1;
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_LAMP:
|
|
|
|
if(dupflag & USER_DUP_LAMP) {
|
|
|
|
ID_NEW_US2(obn->data )
|
|
|
|
else obn->data= copy_lamp(obn->data);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OB_ARMATURE:
|
|
|
|
obn->recalc |= OB_RECALC_DATA;
|
|
|
|
if(obn->pose) obn->pose->flag |= POSE_RECALC;
|
|
|
|
|
|
|
|
if(dupflag & USER_DUP_ARM) {
|
|
|
|
ID_NEW_US2(obn->data )
|
|
|
|
else {
|
|
|
|
obn->data= copy_armature(obn->data);
|
|
|
|
armature_rebuild_pose(obn, obn->data);
|
|
|
|
didit= 1;
|
|
|
|
}
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OB_LATTICE:
|
|
|
|
if(dupflag!=0) {
|
|
|
|
ID_NEW_US2(obn->data )
|
|
|
|
else obn->data= copy_lattice(obn->data);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_CAMERA:
|
|
|
|
if(dupflag!=0) {
|
|
|
|
ID_NEW_US2(obn->data )
|
|
|
|
else obn->data= copy_camera(obn->data);
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(dupflag & USER_DUP_MAT) {
|
|
|
|
matarar= give_matarar(obn);
|
|
|
|
if(didit && matarar) {
|
|
|
|
for(a=0; a<obn->totcol; a++) {
|
|
|
|
id= (ID *)(*matarar)[a];
|
|
|
|
if(id) {
|
|
|
|
ID_NEW_US( (*matarar)[a] )
|
|
|
|
else (*matarar)[a]= copy_material((*matarar)[a]);
|
|
|
|
|
|
|
|
id->us--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
copy_object_set_idnew(scene, v3d, dupflag);
|
|
|
|
|
|
|
|
DAG_scene_sort(scene);
|
|
|
|
ED_anim_dag_flush_update(C);
|
|
|
|
|
|
|
|
if(mode==0) {
|
|
|
|
// XX BIF_TransformSetUndo("Add Duplicate");
|
|
|
|
// initTransform(TFM_TRANSLATION, CTX_NONE);
|
|
|
|
// Transform();
|
|
|
|
}
|
2008-12-29 12:15:42 +00:00
|
|
|
// XXX ED_base_object_activate(C, BASACT);
|
2008-12-23 19:47:33 +00:00
|
|
|
if(mode!=2) { /* mode of 2 is used by python to avoid unrequested redraws */
|
|
|
|
allqueue(REDRAWNLA, 0);
|
|
|
|
allqueue(REDRAWACTION, 0); /* also oops */
|
|
|
|
allqueue(REDRAWIPO, 0); /* also oops */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void selectlinks(Scene *scene, View3D *v3d, int nr)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Base *base;
|
|
|
|
void *obdata = NULL;
|
|
|
|
Ipo *ipo = NULL;
|
|
|
|
Material *mat = NULL, *mat1;
|
|
|
|
Tex *tex=0;
|
|
|
|
int a, b;
|
|
|
|
short changed = 0;
|
|
|
|
/* events (nr):
|
|
|
|
* Object Ipo: 1
|
|
|
|
* ObData: 2
|
|
|
|
* Current Material: 3
|
|
|
|
* Current Texture: 4
|
|
|
|
* DupliGroup: 5
|
|
|
|
* PSys: 6
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
ob= OBACT;
|
|
|
|
if(ob==0) return;
|
|
|
|
|
|
|
|
if(nr==1) {
|
|
|
|
ipo= ob->ipo;
|
|
|
|
if(ipo==0) return;
|
|
|
|
}
|
|
|
|
else if(nr==2) {
|
|
|
|
if(ob->data==0) return;
|
|
|
|
obdata= ob->data;
|
|
|
|
}
|
|
|
|
else if(nr==3 || nr==4) {
|
|
|
|
mat= give_current_material(ob, ob->actcol);
|
|
|
|
if(mat==0) return;
|
|
|
|
if(nr==4) {
|
|
|
|
if(mat->mtex[ (int)mat->texact ]) tex= mat->mtex[ (int)mat->texact ]->tex;
|
|
|
|
if(tex==0) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(nr==5) {
|
|
|
|
if(ob->dup_group==NULL) return;
|
|
|
|
}
|
|
|
|
else if(nr==6) {
|
|
|
|
if(ob->particlesystem.first==NULL) return;
|
|
|
|
}
|
|
|
|
else return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if (BASE_SELECTABLE(v3d, base) && !(base->flag & SELECT)) {
|
|
|
|
if(nr==1) {
|
|
|
|
if(base->object->ipo==ipo) base->flag |= SELECT;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
else if(nr==2) {
|
|
|
|
if(base->object->data==obdata) base->flag |= SELECT;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
else if(nr==3 || nr==4) {
|
|
|
|
ob= base->object;
|
|
|
|
|
|
|
|
for(a=1; a<=ob->totcol; a++) {
|
|
|
|
mat1= give_current_material(ob, a);
|
|
|
|
if(nr==3) {
|
|
|
|
if(mat1==mat) base->flag |= SELECT;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
else if(mat1 && nr==4) {
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(mat1->mtex[b]) {
|
|
|
|
if(tex==mat1->mtex[b]->tex) {
|
|
|
|
base->flag |= SELECT;
|
|
|
|
changed = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(nr==5) {
|
|
|
|
if(base->object->dup_group==ob->dup_group) {
|
|
|
|
base->flag |= SELECT;
|
|
|
|
changed = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(nr==6) {
|
|
|
|
/* loop through other, then actives particles*/
|
|
|
|
ParticleSystem *psys;
|
|
|
|
ParticleSystem *psys_act;
|
|
|
|
|
|
|
|
for(psys=base->object->particlesystem.first; psys; psys=psys->next) {
|
|
|
|
for(psys_act=ob->particlesystem.first; psys_act; psys_act=psys_act->next) {
|
|
|
|
if (psys->part == psys_act->part) {
|
|
|
|
base->flag |= SELECT;
|
|
|
|
changed = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (base->flag & SELECT) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base->object->flag= base->flag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWDATASELECT, 0);
|
|
|
|
allqueue(REDRAWOOPS, 0);
|
|
|
|
BIF_undo_push("Select linked");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void selectlinks_menu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
int nr;
|
|
|
|
|
|
|
|
ob= OBACT;
|
|
|
|
if(ob==0) return;
|
|
|
|
|
|
|
|
/* If you modify this menu, please remember to update view3d_select_linksmenu
|
|
|
|
* in header_view3d.c and the menu in toolbox.c
|
|
|
|
*/
|
|
|
|
nr= pupmenu("Select Linked%t|Object Ipo%x1|ObData%x2|Material%x3|Texture%x4|DupliGroup%x5|ParticleSystem%x6");
|
|
|
|
|
|
|
|
if (nr <= 0) return;
|
|
|
|
|
|
|
|
selectlinks(scene, v3d, nr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void image_aspect(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
/* all selected objects with an image map: scale in image aspect */
|
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
Material *ma;
|
|
|
|
Tex *tex;
|
|
|
|
float x, y, space;
|
|
|
|
int a, b, done;
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) return; // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
ob= base->object;
|
|
|
|
done= 0;
|
|
|
|
|
|
|
|
for(a=1; a<=ob->totcol; a++) {
|
|
|
|
ma= give_current_material(ob, a);
|
|
|
|
if(ma) {
|
|
|
|
for(b=0; b<MAX_MTEX; b++) {
|
|
|
|
if(ma->mtex[b] && ma->mtex[b]->tex) {
|
|
|
|
tex= ma->mtex[b]->tex;
|
|
|
|
if(tex->type==TEX_IMAGE && tex->ima) {
|
|
|
|
ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, NULL);
|
|
|
|
|
|
|
|
/* texturespace */
|
|
|
|
space= 1.0;
|
|
|
|
if(ob->type==OB_MESH) {
|
|
|
|
float size[3];
|
|
|
|
mesh_get_texspace(ob->data, NULL, NULL, size);
|
|
|
|
space= size[0]/size[1];
|
|
|
|
}
|
|
|
|
else if(ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) {
|
|
|
|
Curve *cu= ob->data;
|
|
|
|
space= cu->size[0]/cu->size[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
x= ibuf->x/space;
|
|
|
|
y= ibuf->y;
|
|
|
|
|
|
|
|
if(x>y) ob->size[0]= ob->size[1]*x/y;
|
|
|
|
else ob->size[1]= ob->size[0]*y/x;
|
|
|
|
|
|
|
|
done= 1;
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_OB);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(done) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(done) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
BIF_undo_push("Image aspect");
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_ob_ipoflags(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
int set= 1;
|
|
|
|
|
|
|
|
if (!v3d) {
|
|
|
|
error("Can't do this! Open a 3D window");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base->object->ipoflag & OB_DRAWKEY) {
|
|
|
|
set= 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(set) {
|
|
|
|
base->object->ipoflag |= OB_DRAWKEY;
|
|
|
|
if(base->object->ipo) base->object->ipo->showkey= 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
base->object->ipoflag &= ~OB_DRAWKEY;
|
|
|
|
if(base->object->ipo) base->object->ipo->showkey= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
allqueue(REDRAWNLA, 0);
|
|
|
|
allqueue (REDRAWACTION, 0);
|
|
|
|
// allspace(REMAKEIPO, 0);
|
|
|
|
allqueue(REDRAWIPO, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void select_select_keys(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
IpoCurve *icu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
if (!v3d) {
|
|
|
|
error("Can't do this! Open a 3D window");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(scene->id.lib) return;
|
|
|
|
|
|
|
|
if(okee("Show and select all keys")==0) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
if(base->object->ipo) {
|
|
|
|
base->object->ipoflag |= OB_DRAWKEY;
|
|
|
|
base->object->ipo->showkey= 1;
|
|
|
|
icu= base->object->ipo->curve.first;
|
|
|
|
while(icu) {
|
|
|
|
a= icu->totvert;
|
|
|
|
bezt= icu->bezt;
|
|
|
|
while(a--) {
|
|
|
|
bezt->f1 |= SELECT;
|
|
|
|
bezt->f2 |= SELECT;
|
|
|
|
bezt->f3 |= SELECT;
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
icu= icu->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWNLA, 0);
|
|
|
|
allqueue(REDRAWACTION, 0);
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
// allspace(REMAKEIPO, 0);
|
|
|
|
allqueue(REDRAWIPO, 0);
|
|
|
|
|
|
|
|
BIF_undo_push("Select keys");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int vergbaseco(const void *a1, const void *a2)
|
|
|
|
{
|
|
|
|
Base **x1, **x2;
|
|
|
|
|
|
|
|
x1= (Base **) a1;
|
|
|
|
x2= (Base **) a2;
|
|
|
|
|
|
|
|
if( (*x1)->sy > (*x2)->sy ) return 1;
|
|
|
|
else if( (*x1)->sy < (*x2)->sy) return -1;
|
|
|
|
else if( (*x1)->sx > (*x2)->sx ) return 1;
|
|
|
|
else if( (*x1)->sx < (*x2)->sx ) return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void auto_timeoffs(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base, **basesort, **bs;
|
|
|
|
float start, delta;
|
|
|
|
int tot=0, a;
|
|
|
|
short offset=25;
|
|
|
|
|
|
|
|
if(BASACT==0 || v3d==NULL) return;
|
|
|
|
// XXX if(button(&offset, 0, 1000,"Total time")==0) return;
|
|
|
|
|
|
|
|
/* make array of all bases, xco yco (screen) */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
tot++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delta= (float)offset/(float)tot;
|
|
|
|
start= OBACT->sf;
|
|
|
|
|
|
|
|
bs= basesort= MEM_mallocN(sizeof(void *)*tot,"autotimeoffs");
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
*bs= base;
|
|
|
|
bs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
qsort(basesort, tot, sizeof(void *), vergbaseco);
|
|
|
|
|
|
|
|
bs= basesort;
|
|
|
|
for(a=0; a<tot; a++) {
|
|
|
|
|
|
|
|
(*bs)->object->sf= start;
|
|
|
|
start+= delta;
|
|
|
|
|
|
|
|
bs++;
|
|
|
|
}
|
|
|
|
MEM_freeN(basesort);
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ofs_timeoffs(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
float offset=0.0f;
|
|
|
|
|
|
|
|
if(BASACT==0 || v3d==NULL) return;
|
|
|
|
|
|
|
|
// XXX if(fbutton(&offset, -10000.0f, 10000.0f, 10, 10, "Offset")==0) return;
|
|
|
|
|
|
|
|
/* make array of all bases, xco yco (screen) */
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
base->object->sf += offset;
|
|
|
|
if (base->object->sf < -MAXFRAMEF) base->object->sf = -MAXFRAMEF;
|
|
|
|
else if (base->object->sf > MAXFRAMEF) base->object->sf = MAXFRAMEF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void rand_timeoffs(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
float rand=0.0f;
|
|
|
|
|
|
|
|
if(BASACT==0 || v3d==NULL) return;
|
|
|
|
|
|
|
|
// XXX if(fbutton(&rand, 0.0f, 10000.0f, 10, 10, "Randomize")==0) return;
|
|
|
|
|
|
|
|
rand *= 2;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
base->object->sf += (BLI_drand()-0.5) * rand;
|
|
|
|
if (base->object->sf < -MAXFRAMEF) base->object->sf = -MAXFRAMEF;
|
|
|
|
else if (base->object->sf > MAXFRAMEF) base->object->sf = MAXFRAMEF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSOBJECT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void texspace_edit(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
int nr=0;
|
|
|
|
|
|
|
|
/* first test if from visible and selected objects
|
|
|
|
* texspacedraw is set:
|
|
|
|
*/
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(scene->obedit) return; // XXX get from context
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(base==0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nr= pupmenu("Texture Space %t|Grab/Move%x1|Size%x2");
|
|
|
|
if(nr<1) return;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
base->object->dtx |= OB_TEXSPACE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(nr==1) {
|
|
|
|
// XXX initTransform(TFM_TRANSLATION, CTX_TEXTURE);
|
|
|
|
// XXX Transform();
|
|
|
|
}
|
|
|
|
else if(nr==2) {
|
|
|
|
// XXX initTransform(TFM_RESIZE, CTX_TEXTURE);
|
|
|
|
// XXX Transform();
|
|
|
|
}
|
|
|
|
else if(nr==3) {
|
|
|
|
// XXX initTransform(TFM_ROTATION, CTX_TEXTURE);
|
|
|
|
// XXX Transform();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************************************************************** */
|
|
|
|
/* Mirror function in Edit Mode */
|
|
|
|
|
|
|
|
void mirrormenu(void)
|
|
|
|
{
|
|
|
|
if(G.f & G_PARTICLEEDIT) {
|
|
|
|
// XXX PE_mirror_x(0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// XXX initTransform(TFM_MIRROR, CTX_NO_PET);
|
|
|
|
// XXX Transform();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void hookmenu(Scene *scene, View3D *v3d)
|
|
|
|
{
|
|
|
|
/* only called in object mode */
|
|
|
|
short event, changed=0;
|
|
|
|
Object *ob;
|
|
|
|
Base *base;
|
|
|
|
ModifierData *md;
|
|
|
|
HookModifierData *hmd;
|
|
|
|
|
|
|
|
event= pupmenu("Modify Hooks for Selected...%t|Reset Offset%x1|Recenter at Cursor%x2");
|
|
|
|
if (event==-1) return;
|
|
|
|
if (event==2 && !(v3d)) {
|
|
|
|
error("Cannot perform this operation without a 3d view");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(TESTBASELIB(v3d, base)) {
|
|
|
|
for (md = base->object->modifiers.first; md; md=md->next) {
|
|
|
|
if (md->type==eModifierType_Hook) {
|
|
|
|
ob = base->object;
|
|
|
|
hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copied from modifiers_cursorHookCenter and
|
|
|
|
* modifiers_clearHookOffset, should consolidate
|
|
|
|
* */
|
|
|
|
|
|
|
|
if (event==1) {
|
|
|
|
if(hmd->object) {
|
|
|
|
Mat4Invert(hmd->object->imat, hmd->object->obmat);
|
|
|
|
Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
changed= 1;
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
float *curs = give_cursor(scene, v3d);
|
|
|
|
float bmat[3][3], imat[3][3];
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
where_is_object(scene, ob);
|
2008-12-23 19:47:33 +00:00
|
|
|
|
|
|
|
Mat3CpyMat4(bmat, ob->obmat);
|
|
|
|
Mat3Inv(imat, bmat);
|
|
|
|
|
|
|
|
curs= give_cursor(scene, v3d);
|
|
|
|
hmd->cent[0]= curs[0]-ob->obmat[3][0];
|
|
|
|
hmd->cent[1]= curs[1]-ob->obmat[3][1];
|
|
|
|
hmd->cent[2]= curs[2]-ob->obmat[3][2];
|
|
|
|
Mat3MulVecfl(imat, hmd->cent);
|
|
|
|
|
|
|
|
changed= 1;
|
|
|
|
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
if (event==1)
|
|
|
|
BIF_undo_push("Clear hook offset for selected");
|
|
|
|
else if (event==2)
|
|
|
|
BIF_undo_push("Hook cursor center for selected");
|
|
|
|
|
|
|
|
allqueue(REDRAWVIEW3D, 0);
|
|
|
|
allqueue(REDRAWBUTSEDIT, 0);
|
|
|
|
}
|
|
|
|
}
|