Added a new selection command option "select intersect" that selects
the area of intersection between any number of types.
This commit is contained in:
parent
e152deb97b
commit
7cb88ffceb
147
commands/CmdRS.c
147
commands/CmdRS.c
|
|
@ -528,6 +528,26 @@ CmdSee(w, cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
#define SEL_AREA 0
|
||||
#define SEL_VISIBLE 1
|
||||
#define SEL_CELL 2
|
||||
#define SEL_LABELS 3
|
||||
#define SEL_INTERSECT 4
|
||||
#define SEL_CLEAR 5
|
||||
#define SEL_FLAT 6
|
||||
#define SEL_HELP 7
|
||||
#define SEL_KEEP 8
|
||||
#define SEL_MOVE 9
|
||||
#define SEL_PICK 10
|
||||
#define SEL_SAVE 11
|
||||
#define SEL_FEEDBACK 12
|
||||
#define SEL_BBOX 13
|
||||
#define SEL_BOX 14
|
||||
#define SEL_CHUNK 15
|
||||
#define SEL_REGION 16
|
||||
#define SEL_NET 17
|
||||
#define SEL_SHORT 18
|
||||
#define SEL_DEFAULT 19
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
|
|
@ -550,86 +570,10 @@ CmdSee(w, cmd)
|
|||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
cmdSelectArea(layers, less)
|
||||
char *layers; /* Which layers are to be selected. */
|
||||
bool less;
|
||||
{
|
||||
SearchContext scx;
|
||||
TileTypeBitMask mask;
|
||||
int windowMask, xMask;
|
||||
DBWclientRec *crec;
|
||||
MagWindow *window;
|
||||
|
||||
bzero(&scx, sizeof(SearchContext));
|
||||
window = ToolGetBoxWindow(&scx.scx_area, &windowMask);
|
||||
if (window == NULL)
|
||||
{
|
||||
TxPrintf("The box isn't in a window.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Since the box may actually be in multiple windows, we have to
|
||||
* be a bit careful. If the box is only in one window, then there's
|
||||
* no problem. If it's in more than window, the cursor must
|
||||
* disambiguate the windows.
|
||||
*/
|
||||
|
||||
xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask;
|
||||
if ((windowMask & ~xMask) != 0)
|
||||
{
|
||||
window = CmdGetRootPoint((Point *) NULL, (Rect *) NULL);
|
||||
xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask;
|
||||
if ((windowMask & xMask) == 0)
|
||||
{
|
||||
TxPrintf("The box is in more than one window; use the cursor\n");
|
||||
TxPrintf("to select the one you want to select from.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (CmdParseLayers(layers, &mask))
|
||||
{
|
||||
if (TTMaskEqual(&mask, &DBSpaceBits))
|
||||
(void) CmdParseLayers("*,label", &mask);
|
||||
TTMaskClearType(&mask, TT_SPACE);
|
||||
}
|
||||
else return;
|
||||
|
||||
if (less)
|
||||
{
|
||||
(void) SelRemoveArea(&scx.scx_area, &mask);
|
||||
return;
|
||||
}
|
||||
|
||||
scx.scx_use = (CellUse *) window->w_surfaceID;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
crec = (DBWclientRec *) window->w_clientData;
|
||||
SelectArea(&scx, &mask, crec->dbw_bitmask);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* cmdSelectVisible --
|
||||
*
|
||||
* This is a utility procedure used by CmdSelect to do area
|
||||
* selection of visible paint.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The selection is augmented to contain all the information on
|
||||
* layers that is visible under the box, including paint, labels,
|
||||
* and expanded subcells.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
void
|
||||
cmdSelectVisible(layers, less)
|
||||
cmdSelectArea(layers, less, option)
|
||||
char *layers; /* Which layers are to be selected. */
|
||||
bool less;
|
||||
int option; /* Option from defined list above */
|
||||
{
|
||||
SearchContext scx;
|
||||
TileTypeBitMask mask;
|
||||
|
|
@ -680,6 +624,7 @@ cmdSelectVisible(layers, less)
|
|||
scx.scx_use = (CellUse *) window->w_surfaceID;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
crec = (DBWclientRec *) window->w_clientData;
|
||||
if (option == SEL_VISIBLE)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < DBNumUserLayers; i++)
|
||||
|
|
@ -688,7 +633,10 @@ cmdSelectVisible(layers, less)
|
|||
TTMaskClearType(&mask, i);
|
||||
}
|
||||
}
|
||||
SelectArea(&scx, &mask, crec->dbw_bitmask);
|
||||
if (option == SEL_INTERSECT)
|
||||
SelectIntersect(&scx, &mask, crec->dbw_bitmask);
|
||||
else
|
||||
SelectArea(&scx, &mask, crec->dbw_bitmask);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -728,32 +676,13 @@ CmdSelect(w, cmd)
|
|||
* second table, due to a help message for ":select" with no arguments.
|
||||
*/
|
||||
|
||||
#define SEL_AREA 0
|
||||
#define SEL_VISIBLE 1
|
||||
#define SEL_CELL 2
|
||||
#define SEL_LABELS 3
|
||||
#define SEL_CLEAR 4
|
||||
#define SEL_FLAT 5
|
||||
#define SEL_HELP 6
|
||||
#define SEL_KEEP 7
|
||||
#define SEL_MOVE 8
|
||||
#define SEL_PICK 9
|
||||
#define SEL_SAVE 10
|
||||
#define SEL_FEEDBACK 11
|
||||
#define SEL_BBOX 12
|
||||
#define SEL_BOX 13
|
||||
#define SEL_CHUNK 14
|
||||
#define SEL_REGION 15
|
||||
#define SEL_NET 16
|
||||
#define SEL_SHORT 17
|
||||
#define SEL_DEFAULT 18
|
||||
|
||||
static char *cmdSelectOption[] =
|
||||
{
|
||||
"area",
|
||||
"visible",
|
||||
"cell",
|
||||
"labels",
|
||||
"intersection",
|
||||
"clear",
|
||||
"flat",
|
||||
"help",
|
||||
|
|
@ -780,6 +709,7 @@ CmdSelect(w, cmd)
|
|||
"[more | less] visible [layers] [de]select all visible info under box in layers",
|
||||
"[more | less | top] cell [name] [de]select cell under cursor, or \"name\"",
|
||||
"[do | no] labels [do not] select subcell labels",
|
||||
"[more | less] intersection [layers] [de]select intersection of layers",
|
||||
"clear clear selection",
|
||||
"flat flatten the contents of the selection",
|
||||
"help print this message",
|
||||
|
|
@ -980,7 +910,7 @@ CmdSelect(w, cmd)
|
|||
}
|
||||
if (!(more || less)) SelectClear();
|
||||
if (cmd->tx_argc == 3)
|
||||
cmdSelectArea(optionArgs[1], less);
|
||||
cmdSelectArea(optionArgs[1], less, option);
|
||||
else cmdSelectArea("*,label,subcell", less);
|
||||
return;
|
||||
|
||||
|
|
@ -994,8 +924,21 @@ CmdSelect(w, cmd)
|
|||
if (cmd->tx_argc > 3) goto usageError;
|
||||
if (!(more || less)) SelectClear();
|
||||
if (cmd->tx_argc == 3)
|
||||
cmdSelectVisible(optionArgs[1], less);
|
||||
else cmdSelectVisible("*,label,subcell", less);
|
||||
cmdSelectArea(optionArgs[1], less, option);
|
||||
else cmdSelectArea("*,label,subcell", less, option);
|
||||
return;
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Select area that is the intersection of all the specified layers
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
case SEL_INTERSECT:
|
||||
if (cmd->tx_argc > 3) goto usageError;
|
||||
if (!(more || less)) SelectClear();
|
||||
if (cmd->tx_argc == 3)
|
||||
cmdSelectArea(optionArgs[1], less, option);
|
||||
else cmdSelectArea("*,label,subcell", less, option);
|
||||
return;
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -253,6 +253,205 @@ selClearFunc(scx)
|
|||
else return 2;
|
||||
}
|
||||
|
||||
/* Structure used by selIntersectPaintFunc() */
|
||||
|
||||
struct selIntersectData {
|
||||
Rect *sid_rect;
|
||||
TileType sid_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* selDupPaintFunc --
|
||||
*
|
||||
* Copy paint from tile area in Select2Def into SelectDef as all types
|
||||
* in rMask.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
selDupPaintFunc(tile, rMask)
|
||||
Tile *tile; /* The tile to get the area to copy paint. */
|
||||
TileTypeBitMask *rMask; /* Paint types to copy to. */
|
||||
{
|
||||
Rect r;
|
||||
|
||||
TiToRect(tile, &r);
|
||||
DBPaintMask(SelectDef, &r, rMask);
|
||||
|
||||
return 0; /* Keep the search going. */
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* selIntersectPaintFunc2 ---
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
selIntersectPaintFunc2(tile, sid)
|
||||
Tile *tile; /* The tile to copy paint from. */
|
||||
struct selIntersectData *sid;
|
||||
{
|
||||
Rect r;
|
||||
int p;
|
||||
|
||||
TiToRect(tile, &r);
|
||||
GEOCLIP(&r, sid->sid_rect); /* Clip out the intersection area */
|
||||
|
||||
DBPaint(Select2Def, &r, sid->sid_type); /* Paint back into Select2Def */
|
||||
|
||||
return 0; /* Keep the search going. */
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* selIntersectPaintFunc --
|
||||
*
|
||||
* Erase paint of types in rMask from the area of the tile.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
selIntersectPaintFunc(tile, type)
|
||||
Tile *tile; /* The tile to copy paint from. */
|
||||
TileType type; /* The type of tile to keep */
|
||||
{
|
||||
TileTypeBitMask tMask;
|
||||
Rect r;
|
||||
int plane;
|
||||
struct selIntersectData sid;
|
||||
|
||||
TiToRect(tile, &r);
|
||||
|
||||
TTMaskSetOnlyType(&tMask, type);
|
||||
plane = DBPlane(type);
|
||||
|
||||
sid.sid_type = TiGetTypeExact(tile);
|
||||
sid.sid_rect = &r;
|
||||
|
||||
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &r,
|
||||
&tMask, selIntersectPaintFunc2, (ClientData)&sid);
|
||||
|
||||
return 0; /* Keep the search going. */
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* SelectIntersect --
|
||||
*
|
||||
* This procedure selects all information that falls in a given area
|
||||
* and contains the intersection of all the supplied types.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The indicated information is added to the select cell, and
|
||||
* outlined on the screen. Only information of particular
|
||||
* types, and in expanded cells (according to xMask) is
|
||||
* selected.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
SelectIntersect(scx, types, xMask)
|
||||
SearchContext *scx; /* Describes the area in which material
|
||||
* is to be selected. The resulting
|
||||
* coordinates should map to the coordinates
|
||||
* of EditRootDef. The cell use should be
|
||||
* the root of a window.
|
||||
*/
|
||||
TileTypeBitMask *types; /* Indicates which intersecting layers to
|
||||
* select. May not include labels or cells.
|
||||
*/
|
||||
int xMask; /* Indicates window (or windows) where cells
|
||||
* must be expanded for their contents to be
|
||||
* considered. 0 means treat everything as
|
||||
* expanded.
|
||||
*/
|
||||
{
|
||||
TileTypeBitMask tMask, rMask;
|
||||
TileType s, t;
|
||||
int plane;
|
||||
|
||||
/* If the source definition is changing, clear the old selection. */
|
||||
|
||||
if (SelectRootDef != scx->scx_use->cu_def)
|
||||
{
|
||||
if (SelectRootDef != NULL)
|
||||
SelectClear();
|
||||
SelectRootDef = scx->scx_use->cu_def;
|
||||
SelSetDisplay(SelectUse, SelectRootDef);
|
||||
}
|
||||
|
||||
SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL);
|
||||
|
||||
/* Select all paint of types in "types" mask and copy into Select2Def */
|
||||
|
||||
DBCellClearDef(Select2Def);
|
||||
(void) DBCellCopyAllPaint(scx, types, xMask, Select2Use);
|
||||
|
||||
/* Find the first type in the list. This will be used as the reference */
|
||||
|
||||
for (t = 0; t < DBNumUserLayers; t++)
|
||||
if (TTMaskHasType(types, t))
|
||||
break;
|
||||
|
||||
if (t == DBNumUserLayers) return;
|
||||
|
||||
/* Compute the type mask of the reference type */
|
||||
TTMaskSetOnlyType(&tMask, t);
|
||||
plane = DBPlane(t);
|
||||
|
||||
/* For each other type in "types", do the following */
|
||||
|
||||
for (s = t + 1; s < DBNumUserLayers; s++)
|
||||
{
|
||||
if (TTMaskHasType(types, s))
|
||||
{
|
||||
/* Copy the reference paint type from Select2Def into SelectDef */
|
||||
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &scx->scx_area,
|
||||
&tMask, selDupPaintFunc, (ClientData)&tMask);
|
||||
|
||||
/* Erase the reference paint type from Select2Def */
|
||||
DBEraseMask(Select2Def, &TiPlaneRect, &tMask);
|
||||
|
||||
/* Scan Select2Def for all geometry of type s inside the areas of */
|
||||
/* the reference type, and copy back to Select2Def as the reference */
|
||||
/* type */
|
||||
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[plane],
|
||||
&scx->scx_area, &tMask, selIntersectPaintFunc, (ClientData)s);
|
||||
|
||||
/* Erase the reference paint type from SelectDef */
|
||||
DBEraseMask(SelectDef, &TiPlaneRect, &tMask);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy any remaining paint in the reference layer in Select2Def to */
|
||||
/* SelectDef as all the intersection types. */
|
||||
|
||||
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &scx->scx_area,
|
||||
&tMask, selDupPaintFunc, (ClientData)types);
|
||||
|
||||
SelectDef->cd_types = *types; /* Remember what types were requested */
|
||||
|
||||
/* Display the new selection. */
|
||||
|
||||
SelRememberForUndo(FALSE, SelectRootDef, &scx->scx_area);
|
||||
DBReComputeBbox(SelectDef);
|
||||
DBWHLRedraw(SelectRootDef, &scx->scx_area, TRUE);
|
||||
DBWAreaChanged(SelectDef, &SelectDef->cd_extended, DBW_ALLWINDOWS,
|
||||
&DBAllButSpaceBits);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ extern void SelectRegion();
|
|||
extern void SelectInit();
|
||||
extern void SelectClear();
|
||||
extern void SelectCell();
|
||||
extern void SelectIntersect();
|
||||
extern void SelRemoveArea();
|
||||
extern int SelRemoveSel2();
|
||||
extern int SelectRemoveCellUse();
|
||||
|
|
|
|||
Loading…
Reference in New Issue