#Select/Deselect
10 messages in this thread
I have a question about how to select or deselect an object using a
PXP. It seems that three things need to happen:
– All the objects verticies must be selected
– All the objects faces must be selected
– The objects selected flag must be set.
I have written the code below to try to do this. It does not work
however. I can select an object, but I cannot deselect it.
If anyone has done something similiar, I'd appreciate if you could
review the code below and offer any suggestions. It is assumed a
global ItemData structure called item_data exists and is properly
loaded with a mesh object…
Thanks,
Mark
int do_toggle_selection(void)
{
int index, status;
// Save the function address for re-execution
get_function_index(do_toggle_selection, &last_function);
if (! item_loaded("Toggle Selection", last_function)) return(0);
if (item_index) {
if (item_type == ITEM_MESH) {
if (item_data.item.m.flags & MESH_SELECTED) {
status = set_object_selected_state(0); // Toggle Off
}
else {
status = set_object_selected_state(1); // Toggle On
}
if (status) {
pxp_erase_item(item_name);
pxp_change_item(&item_data, status);
pxp_draw_item(item_name);
}
else {
fmsg("Error: Could not Toggle object \"%s\" Selected state",
item_name);
}
}
}
return(1);
}
// This function selects/deselects all the objects verticies and faces
// and sets/clears the objects selected flag based on the state passed.
// Note: The object is selected/deselected in the 'current'
// 3ds selection set (A, B or C).
// The object to be modified should be loaded into the global item_data.
int set_object_selected_state(int select_it)
{
int i, faces, verts, status;
XFData2 *fdata = NULL;
XVData *vdata = NULL;
// Allocate temp space for the objects verts/faces
verts = item_data.item.m.verts;
faces = item_data.item.m.faces;
if (! (vdata = (XVData *)malloc(faces*sizeof(XVData)))) {
return(0);
}
if (! (fdata = (XFData2 *)malloc(faces*sizeof(XFData2)))) {
free(vdata);
return(0);
}
// Set all the verticies
pxp_get_verts(item_data.name, 0, verts, vdata, status);
if (status == 0) {
free(vdata); free(fdata);
fmsg("Could not get Vertex Info for object \"%s\"", item_data.name);
return(0);
}
for (i = 0; i < verts; i++) {
if (select_it) {
// vdata[i].flags |= (unsigned short) (XV_SELECTED | XV_SEL_A);
vdata[i].flags |= (unsigned short) XV_SELECTED;
}
else {
// vdata[i].flags &= (unsigned short) ~(XV_SELECTED | XV_SEL_A);
vdata[i].flags &= (unsigned short) ~XV_SELECTED;
}
}
pxp_put_verts(item_data.name, 0, verts, vdata, status);
// Set all the faces
pxp_get_faces2(item_data.name, 0, faces, fdata, status);
if (status == 0) {
free(vdata);
free(fdata);
fmsg("Could not get Face Info for object \"%s\"", item_data.name);
return(0);
}
for (i = 0; i < faces; i++) {
if (select_it) {
// fdata[i].flags |= (unsigned short) (XF_SELECTED | XF_SEL_A);
fdata[i].flags |= (unsigned short) XF_SELECTED;
}
else {
// fdata[i].flags &= (unsigned short) ~(XF_SELECTED | XF_SEL_A);
fdata[i].flags &= (unsigned short) ~XF_SELECTED;
}
}
pxp_put_faces2(item_data.name, 0, faces, fdata, status);
// Set/Clear the object selected flag
if (select_it) {
item_data.item.m.flags |= (unsigned short) MESH_SELECTED;
}
else {
item_data.item.m.flags &= (unsigned short) ~MESH_SELECTED;
}
free(vdata);
free(fdata);
return(status);
}
Looks like the last message got truncated…here goes again.
I have a question about how to select or deselect an object using a PXP. It
seems that three things need to happen:
– All the objects verticies must be selected
– All the objects faces must be selected
– The objects selected flag must be set.
I have written the code below to try to do this. It does not work however. I
can select an object, but I cannot deselect it.
If anyone has done something similiar, I'd appreciate if you could review the
code below and offer any suggestions. It is assumed a global ItemData
structure called item_data exists and is properly loaded with a mesh object…
Thanks,
Mark
int do_toggle_selection(void)
{
int index, status;
// Save the function address for re-execution
get_function_index(do_toggle_selection, &last_function);
if (! item_loaded("Toggle Selection", last_function)) return(0);
if (item_index) {
if (item_type == ITEM_MESH) {
if (item_data.item.m.flags & MESH_SELECTED) {
status = set_object_selected_state(0); // Toggle Off
}
else {
status = set_object_selected_state(1); // Toggle On
}
if (status) {
pxp_erase_item(item_name);
pxp_change_item(&item_data, status);
pxp_draw_item(item_name);
}
else {
fmsg("Error: Could not Toggle object \"%s\" Selected state",
item_name);
}
}
}
return(1);
}
// This function selects/deselects all the objects verticies and faces
// and sets/clears the objects selected flag based on the state passed.
// Note: The object is selected/deselected in the 'current'
// 3ds selection set (A, B or C).
// The object to be modified should be loaded into the global item_data.
int set_object_selected_state(int select_it)
{
int i, faces, verts, status;
XFData2 *fdata = NULL;
XVData *vdata = NULL;
// Allocate temp space for the objects verts/faces
verts = item_data.item.m.verts;
faces = item_data.item.m.faces;
if (! (vdata = (XVData *)malloc(faces*sizeof(XVData)))) {
return(0);
}
if (! (fdata = (XFData2 *)malloc(faces*sizeof(XFData2)))) {
free(vdata);
return(0);
}
// All the verticies
pxp_get_verts(item_data.name, 0, verts, vdata, status);
if (status == 0) {
free(vdata); free(fdata);
fmsg("Could not get Vertex Info for object \"%s\"", item_data.name);
return(0);
}
for(i = 0; i < verts; i++) {
if (select_it) {
// vdata[i].flags |= (unsigned short) (XV_SELECTED | XV_SEL_A);
vdata[i].flags |= (unsigned short) XV_SELECTED;
}
else {
// vdata[i].flags &= (unsigned short) ~(XV_SELECTED | XV_SEL_A);
vdata[i].flags &= (unsigned short) ~XV_SELECTED;
}
}
pxp_put_verts(item_data.name, 0, verts, vdata, status);
// All the faces
pxp_get_faces2(item_data.name, 0, faces, fdata, status);
if (status == 0) {
free(vdata);
free(fdata);
fmsg("Could not get Face Info for object \"%s\"", item_data.name);
return(0);
}
for(i = 0; i < faces; i++) {
if (select_it) {
// fdata[i].flags |= (unsigned short) (XF_SELECTED | XF_SEL_A);
fdata[i].flags |= (unsigned short) XF_SELECTED;
}
else {
// fdata[i].flags &= (unsigned short) ~(XF_SELECTED | XF_SEL_A);
fdata[i].flags &= (unsigned short) ~XF_SELECTED;
}
}
pxp_put_faces2(item_data.name, 0, faces, fdata, status);
// Set/Clear the object selected flag
if (select_it) {
item_data.item.m.flags |= (unsigned short) MESH_SELECTED;
}
else {
item_data.item.m.flags &= (unsigned short) ~MESH_SELECTED;
}
free(vdata);
free(fdata);
return(status);
}
Hi Mark,
<< code.. >>
I'll put some time into this over the weekend. I may not be able to do
a lot of testing til monday though. Danny's done a lot of
select/deselection, maybe he'll jump in too.
Thanks Jonas
Mark
I sent Mark a simple PXP that does what he's looking for. If you're
interested, I can post the complete source and PXP here for anyone
who might make use of it.
Hi Mark,
I took a look at your problem and played around a bit. Here's a program that
correctly selects/deselects objects in the 3D Editor and is selection-set
sensitive.
I hope it helps. Take care,
Danny…
/*________________________________________________________________________*/
/* Dialog description */
DlgEntry cdialog[]={
0, "TITLE=\"Selection Test IPAS\"",
0, "TITLE=\"by Danny Mercurio\"",
0, "TITLE=\"Details, Inc.\"",
0, "TITLE=\"\"",
0, NULL
};
/*_______________________________________________________________________ */
#define VERSION 0x0507
typedef struct{
ulong version;
} State;
ItemData data;
static State init_state = {VERSION};
static State state = {VERSION};
int count = 0, counter = 0, status = 0;
int verts = 0, faces = 0, result = 0, sel = 0;
/*_______________________________________________________________________ */
/* declare global subroutines */
int selection_set(void);
int set_object_selected_state(int select_it, int sel);
int do_toggle_selection(int index);
/*_______________________________________________________________________ */
int ClientUsesInitDialog(void){
return(1);
}
void ClientSetStateVar(int id, void *ptr){
OVL o;
ulong *ul;
char *s;
ul = (ulong *)ptr;
s = (char *)ptr;
o.ul = *ul;
switch(id){
}
}
ulong ClientGetStateVar(int id){
OVL o;
switch(id){
}
return(o.ul);
}
int ClientVarSize(int id){
switch(id){
default:
return(1);
}
}
char *ClientGetState(int *size){
*size = sizeof(State);
return((char *)&state);
}
void ClientResetState(){
state = init_state;
}
void ClientStartup(EXPbuf *buf){
int result;
/* requires version 3.0 */
if(studio_version() < 300){
gfx_alert(0, "[Resource Test PXP Plug-in requires 3D Studio Release 3 or
later.][OK]", result);
buf->opcode = buf->usercode = EXP_TERMINATE;
return;
}
/* how many objects are in the editor? */
pxp_get_item_count(count);
if(count == 1){
gfx_alert(0, "[No objects in editor.][OK]", result);
buf->opcode = buf->usercode = EXP_TERMINATE;
return;
}
/* kicks things down to ClientUserCode */
buf->opcode = EXP_NOP;
buf->usercode = 0x0200;
buf->status = 1;
}
void ClientUserCode(EXPbuf *buf){
int n;
switch(buf->usercode){
case 0x0200:
counter = 0;
for(n = 1; n < count; n++){
if(!do_toggle_selection(n)){
gfx_alert(0, "[Unknown problem occurred][OK]", result);
buf->opcode = buf->usercode = EXP_TERMINATE;
break;
}
}
buf->opcode = EXP_NOP;
buf->usercode = 0x0210;
buf->status = 1;
break;
case 0x0210:
buf->opcode = buf->usercode = EXP_TERMINATE;
buf->status = 0;
break;
default:
buf->opcode = buf->usercode = EXP_TERMINATE;
buf->status = 0;
break;
}
}
void ClientTerminate(void){
/* free any data structures, etc. */
}
DlgEntry *ClientDialog(int n){
return(&cdialog[n]);
}
int ClientIsUniversal(void){
return(0);
}
/*________________________________________________________________________*/
int do_toggle_selection(int index){
int status;
pxp_get_item(index, &data, status);
if(status && data.type == PXPMESH){
if (data.item.m.flags & MESH_SELECTED) {
if(counter == 0) sel = selection_set(); // Which set are we in?
status = set_object_selected_state(0, sel); // Toggle Off
counter++;
} else {
status = set_object_selected_state(1, sel); // Toggle On
}
if (status) {
pxp_erase_item(data.name);
pxp_change_item(&data, status);
pxp_draw_item(data.name);
} else {
sprintf(gp_buffer, "Error: Could not Toggle object \"%s\" Selected
state", data.name);
gfx_continu_line(gp_buffer);
}
}
return(1);
}
int set_object_selected_state(int select_it, int sel){
int i, faces, verts, status, result;
XFData2 *fdata = NULL;
XVData *vdata = NULL;
// Allocate temp space for the objects verts/faces
verts = data.item.m.verts;
faces = data.item.m.faces;
vdata = (XVData *)malloc(verts*sizeof(XVData));
if (!vdata) {
gfx_alert(0, "[Insufficient memory for vertices.][OK]", result);
return(0);
}
fdata = (XFData2 *)malloc(faces*sizeof(XFData2));
if (!fdata) {
free(vdata);
gfx_alert(0, "[Insufficient memory for faces.][OK]", result);
return(0);
}
// All the verticies
pxp_get_verts(data.name, 0, verts, vdata, status);
if (status == 0) {
free(vdata); free(fdata);
sprintf(gp_buffer, "Could not get Vertex Info for object \"%s\"",
data.name);
gfx_continu_line(gp_buffer);
return(0);
}
for(i = 0; i < verts; i++) {
if (select_it) {
// vdata[i].flags |= (unsigned short) (XV_SELECTED | XV_SEL_A);
vdata[i].flags |= (unsigned short) XV_SELECTED;
} else {
// vdata[i].flags &= (unsigned short) ~(XV_SELECTED | XV_SEL_A);
// vdata[i].flags &= (unsigned short) ~XV_SELECTED;
switch(sel){
case 1: vdata[i].flags &= (unsigned short) ~(XV_SELECTED |
XV_SEL_A); break;
case 2: vdata[i].flags &= (unsigned short) ~(XV_SELECTED |
XV_SEL_B); break;
case 3: vdata[i].flags &= (unsigned short) ~(XV_SELECTED |
XV_SEL_C); break;
}
}
}
pxp_put_verts(data.name, 0, verts, vdata, status);
// All the faces
pxp_get_faces2(data.name, 0, faces, fdata, status);
if (status == 0) {
free(vdata); free(fdata);
sprintf(gp_buffer, "Could not get Face Info for object \"%s\"",
data.name);
gfx_continu_line(gp_buffer);
return(0);
}
for(i = 0; i < faces; i++) {
if (select_it) {
// fdata[i].flags |= (unsigned short) (XF_SELECTED | XF_SEL_A);
fdata[i].flags |= (unsigned short) XF_SELECTED;
} else {
// fdata[i].flags &= (unsigned short) ~(XF_SELECTED | XF_SEL_A);
// fdata[i].flags &= (unsigned short) ~XF_SELECTED;
switch(sel){
case 1: fdata[i].flags &= (unsigned short) ~(XF_SELECTED |
XF_SEL_A); break;
case 2: fdata[i].flags &= (unsigned short) ~(XF_SELECTED |
XF_SEL_B); break;
case 3: fdata[i].flags &= (unsigned short) ~(XF_SELECTED |
XF_SEL_C); break;
}
}
}
pxp_put_faces2(data.name, 0, faces, fdata, status);
// Set/Clear the object selected flag
if (select_it) {
data.item.m.flags |= (unsigned short) MESH_SELECTED;
} else {
data.item.m.flags &= (unsigned short) ~MESH_SELECTED;
}
free(vdata);
free(fdata);
return(status);
}
int selection_set(void){
int status, result, sel = 0, temp = 0;
XVData *vdata = NULL;
// Allocate temp space for the objects verts
vdata = (XVData *)malloc(sizeof(XVData));
if (!vdata) {
gfx_alert(0, "[Insufficient memory for vertices.][OK]", result);
return(0);
}
// Get a vertex
pxp_get_verts(data.name, 0, 1, vdata, status);
if (status == 0) {
free(vdata);
sprintf(gp_buffer, "Could not get Selection Info for object \"%s\"",
data.name);
gfx_continu_line(gp_buffer);
return(0);
}
// where are we?
pxp_get_verts(data.name, 0, 1, vdata, status);
if(status){
// save current selection info
temp = vdata[0].flags;
// reset selection info
vdata[0].flags = 0;
// set selection flag to see which set we're in
vdata[0].flags |= (unsigned short) XV_SELECTED;
pxp_put_verts(data.name, 0, 1, vdata, status);
}
if(status){
pxp_get_verts(data.name, 0, 1, vdata, status);
// set the selection flag accordingly
switch(vdata[0].flags){
case (XV_SELECTED | XV_SEL_A): sel = 1; break;
case (XV_SELECTED | XV_SEL_B): sel = 2; break;
case (XV_SELECTED | XV_SEL_C): sel = 3; break;
}
// put things back the way they were
vdata[0].flags = temp;
pxp_put_verts(data.name, 0, 1, vdata, status);
}
// free things up and return
free(vdata);
return(sel);
}
Thanks alot Danny!
My pleasure. I had fun writing it.
>> I've tried to send you the source to a small PXP that'll do what
you need, but I'm not sure if ASOFT messages can handle the number of
lines of source. <<
It came thru fine via email. Its been 45 minutes since I got the
code. I patched it into my program and it works perfectly. Thanks a
lot! I like the way you've handled finding the current selection
set. Clever.
>> I hope it helps. << Saved me hours (days?) and the frustration
reduction has added a few months to my life <g>.
Thanks again Danny,
I'm glad it worked for you Mark.
Take care,
Danny…