#IPAS-Multiple Selections
4 messages in this thread
A pxp I am writing needs to iterate through a list of objects that were
selected before the plug-in was invoked -can a pxp have access to the list of
currently selected objects? If not, is it possible to include functionality
within the pxp to let the user select multiple objects? The EXP_PICK_OBJECT
message handles one selection only and it does not 'color' the selection like
the 3DS editor does. Can I offload this chore to 3DS without having to write a
select/deselect handler that also would also need to update the screen?
Thanks for any help.
Philippe Lourier
Hi Philippe,
<< .. is it possible to include functionality within the pxp to let the user
select multiple objects?..>>
have you seen?..
File Info for SELBYN.ZIP
Section: Software Dev. Kits Contributor: 76640,2515 Size: 30066
Submitted: 3/24/94 Type: Binary Accesses: 140
Title: Select Objects by Name source code and test .pxp
Keys: IPAS 3 IPAS3 SELECT OBJECTS BYNAME NAME DIALOG
This file contains the source code for a Select Objects by Name dialog in your
IPAS
routines. It also contains a test .pxp to show you that it looks and acts just
like the one
3DS has built in. Please direct all comments and suggestions to Douglas Holt
76640,5215. Hope you find it useful.
File size: 30,066
Hi Phillipe,
<< selection sets?.. >>
in addition to my previous response, you may want to compile and analyze
Danny's following code…
/**************************************************************************/
/* */
/* Autodesk 3D Studio 4.0 Res.c */
/* Resource IPAS (PXP) */
/* */
/* Purpose: Tests selection/deselection of 3DS objects. */
/* */
/* Version: 1.0 */
/* */
/* Company: Details, Inc. */
/* Written by: Danny Mercurio */
/* Created: 02-25-95 01:12pm */
/* Modified: 02-25-95 03:03pm */
/* Notes: Metaware HighC v3.1 specific */
/* */
/**************************************************************************/
/*________________________________________________________________________*/
#ifdef __HIGHC__ /* Metaware HighC specific */
pragma Offwarn(67); /* kills "switch statement has no cases" warning */
#endif
/*________________________________________________________________________*/
#include <conio.h>
#include <math.h> /* supports sine and cosine functions */
#include <stdarg.h> /* for reading argument lists */
#include <stdio.h> /* supports the printf function */
#include <stdlib.h> /* supports several common routines */
#include <string.h> /* supports several common routines */
#include <pxp.h> /* Autodesk PXP extension file */
#define VERSION 0x0507
/*________________________________________________________________________*/
/* Dialog description */
DlgEntry cdialog[]={
0, "TITLE=\"Selection Test IPAS\"",
0, "TITLE=\"by Danny Mercurio\"",
0, "TITLE=\"Details, Inc.\"",
0, "TITLE=\"\"",
0, NULL
};
/*_______________________________________________________________________ */
typedef struct{
ulong version;
} State;
XVData *vertdata = NULL;
XFData2 *facedata = NULL;
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. */
free(vertdata);
free(facedata);
}
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){
sprintf(gp_buffer, "\"%s\" Selected state is %d", data.name,
data.item.m.flags & MESH_SELECTED);
gfx_continu_line(gp_buffer);
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);
}
// 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 data.
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);
}
/*..continued..*/
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);
}