//- // ========================================================================== // Copyright (C) 1995 - 2005 Alias Systems Corp. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files are provided by Alias // Systems Corp. ("Alias") and/or its licensors for the exclusive use of the // Customer (as defined in the Alias Software License Agreement that // accompanies this Alias software). Such Customer has the right to use, // modify, and incorporate the Data into other products and to distribute such // products for use by end-users. // // THE DATA IS PROVIDED "AS IS". ALIAS HEREBY DISCLAIMS ALL WARRANTIES // RELATING TO THE DATA, INCLUDING, WITHOUT LIMITATION, ANY AND ALL EXPRESS OR // IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. IN NO EVENT SHALL ALIAS BE LIABLE FOR ANY DAMAGES // WHATSOEVER, WHETHER DIRECT, INDIRECT, SPECIAL, OR PUNITIVE, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, OR IN EQUITY, // ARISING OUT OF ACCESS TO, USE OF, OR RELIANCE UPON THE DATA. // ========================================================================== //+ ////////////////////////////////////////////////////// // // Marquee selection within a user defined context. // Draws the marquee using OpenGL. // Selection is done through the API (MGlobal). // ////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(OSMac_MachO_) #include #include #else #include #include #endif ////////////////////////////////////////////// // The user Context ////////////////////////////////////////////// const char helpString[] = "Click with left button or drag with middle button to select"; class marqueeContext : public MPxContext { public: marqueeContext(); virtual void toolOnSetup( MEvent & event ); virtual MStatus doPress( MEvent & event ); virtual MStatus doDrag( MEvent & event ); virtual MStatus doRelease( MEvent & event ); virtual MStatus doEnterRegion( MEvent & event ); private: short start_x, start_y; short last_x, last_y; #ifdef USE_SOFTWARE_OVERLAYS short p_last_x, p_last_y; bool fsDrawn; #endif MGlobal::ListAdjustment listAdjustment; M3dView view; }; marqueeContext::marqueeContext() { setTitleString ( "Marquee Tool" ); // Tell the context which XPM to use so the tool can properly // be a candidate for the 6th position on the mini-bar. setImage("marqueeTool.xpm", MPxContext::kImage1 ); } void marqueeContext::toolOnSetup ( MEvent & ) { setHelpString( helpString ); } MStatus marqueeContext::doPress( MEvent & event ) // // Begin marquee drawing (using OpenGL) // Get the start position of the marquee // { // Figure out which modifier keys were pressed, and set up the // listAdjustment parameter to reflect what to do with the selected points. if (event.isModifierShift() || event.isModifierControl() ) { if ( event.isModifierShift() ) { if ( event.isModifierControl() ) { // both shift and control pressed, merge new selections listAdjustment = MGlobal::kAddToList; } else { // shift only, xor new selections with previous ones listAdjustment = MGlobal::kXORWithList; } } else if ( event.isModifierControl() ) { // control only, remove new selections from the previous list listAdjustment = MGlobal::kRemoveFromList; } } else { listAdjustment = MGlobal::kReplaceList; } // Extract the event information // event.getPosition( start_x, start_y ); // Enable OpenGL drawing on viewport view = M3dView::active3dView(); view.beginGL(); #ifdef USE_SOFTWARE_OVERLAYS p_last_x = start_x; p_last_y = start_y; fsDrawn = false; #else // If HW overlays supported then initialize the overlay plane for drawing. view.beginOverlayDrawing(); #endif return MS::kSuccess; } MStatus marqueeContext::doDrag( MEvent & event ) // // Drag out the marquee (using OpenGL) // { event.getPosition( last_x, last_y ); #ifdef USE_SOFTWARE_OVERLAYS GLboolean depthTest[1]; GLboolean colorLogicOp[1]; GLboolean lineStipple[1]; // Save the state of these 3 attribtes and restore them later. glGetBooleanv (GL_DEPTH_TEST, depthTest); glGetBooleanv (GL_COLOR_LOGIC_OP, colorLogicOp); glGetBooleanv (GL_LINE_STIPPLE, lineStipple); #endif // Turn Line stippling on. glLineStipple( 1, 0x5555 ); glLineWidth( 1.0 ); glEnable( GL_LINE_STIPPLE ); // Save the state of the matrix on stack glMatrixMode (GL_MODELVIEW); glPushMatrix(); // Setup the Orthographic projection Matrix. glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0.0, (GLdouble) view.portWidth(), 0.0, (GLdouble) view.portHeight() ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef(0.375, 0.375, 0.0); // Set the draw color glIndexi (2); // If we are using software overlays then we need to draw the marquee // in XOR mode #ifdef USE_SOFTWARE_OVERLAYS glDisable (GL_DEPTH_TEST); // Enable XOR mode. glEnable(GL_COLOR_LOGIC_OP); glLogicOp (GL_XOR); // We erase the previously drawn rubber band on the screen by // redrawing it in XOR OpenGL mode. if (fsDrawn) { glBegin( GL_LINE_LOOP ); glVertex2i( start_x, start_y ); glVertex2i( p_last_x, start_y ); glVertex2i( p_last_x, p_last_y ); glVertex2i( start_x, p_last_y ); glEnd(); } fsDrawn = true; #else // If HW overlays enabled then we will clear the overlay plane // so that the previously drawn marquee does not appear on the screen // anymore view.clearOverlayPlane(); #endif // Draw the rectangular marquee // glBegin( GL_LINE_LOOP ); glVertex2i( start_x, start_y ); glVertex2i( last_x, start_y ); glVertex2i( last_x, last_y ); glVertex2i( start_x, last_y ); glEnd(); #ifdef _WIN32 SwapBuffers( view.deviceContext() ); #elif defined (OSMac_) ::aglSwapBuffers(view.display()); #else glXSwapBuffers( view.display(), view.window() ); #endif // Restore the state of the matrix from stack glMatrixMode( GL_MODELVIEW ); glPopMatrix(); #ifdef USE_SOFTWARE_OVERLAYS // Store the current x and y coordinates such that in the next iteration // we can erase this marquee by redrawing it in XOR mode. p_last_x = last_x; p_last_y = last_y; // Restore the previous state of these attributes if (colorLogicOp[0]) glEnable (GL_COLOR_LOGIC_OP); else glDisable (GL_COLOR_LOGIC_OP); if (depthTest[0]) glEnable (GL_DEPTH_TEST); else glDisable (GL_DEPTH_TEST); if (lineStipple[0]) glEnable( GL_LINE_STIPPLE ); else glDisable( GL_LINE_STIPPLE ); #endif return MS::kSuccess; } MStatus marqueeContext::doRelease( MEvent & event ) // // Selects objects within the marquee box. { MSelectionList incomingList, marqueeList; // Clear the marquee when you release the mouse button #ifdef USE_SOFTWARE_OVERLAYS GLboolean depthTest[1]; GLboolean colorLogicOp[1]; GLboolean lineStipple[1]; event.getPosition( last_x, last_y ); // Save the state of these 3 attribtes and restore them later. glGetBooleanv (GL_DEPTH_TEST, depthTest); glGetBooleanv (GL_COLOR_LOGIC_OP, colorLogicOp); glGetBooleanv (GL_LINE_STIPPLE, lineStipple); // Turn Line stippling on. glLineStipple( 1, 0x5555 ); glLineWidth( 1.0 ); glEnable( GL_LINE_STIPPLE ); // Disable GL_DEPTH_TEST glDisable (GL_DEPTH_TEST); // Enable XOR mode. glEnable(GL_COLOR_LOGIC_OP); glLogicOp (GL_INVERT); // Save the current Matrix onto the stack glMatrixMode (GL_MODELVIEW); glPushMatrix(); // Setup the Orthographic projection Matrix. glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0.0, (GLdouble) view.portWidth(), 0.0, (GLdouble) view.portHeight() ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef(0.375, 0.375, 0.0); // Set the draw color glIndexi (2); // Redraw the marquee so that it will be cleared from the screen // when the mouse is released. glBegin( GL_LINE_LOOP ); glVertex2i( start_x, start_y ); glVertex2i( p_last_x, start_y ); glVertex2i( p_last_x, p_last_y ); glVertex2i( start_x, p_last_y ); glEnd(); #ifndef _WIN32 glXSwapBuffers( view.display(), view.window() ); #else SwapBuffers( view.deviceContext() ); #endif // Restore saved Matrix from stack glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glDisable(GL_COLOR_LOGIC_OP); // Restore the previous state of these attributes if (colorLogicOp[0]) glEnable (GL_COLOR_LOGIC_OP); else glDisable (GL_COLOR_LOGIC_OP); if (depthTest[0]) glEnable (GL_DEPTH_TEST); else glDisable (GL_DEPTH_TEST); if (lineStipple[0]) glEnable( GL_LINE_STIPPLE ); else glDisable( GL_LINE_STIPPLE ); #else // If HW overlays enabled, then clear the overlay plane // such that the marquee is no longer drawn on screen. view.clearOverlayPlane(); view.endOverlayDrawing(); #endif view.endGL(); // Get the end position of the marquee event.getPosition( last_x, last_y ); // Save the state of the current selections. The "selectFromSceen" // below will alter the active list, and we have to be able to put // it back. MGlobal::getActiveSelectionList(incomingList); // If we have a zero dimension box, just do a point pick // if ( abs(start_x - last_x) < 2 && abs(start_y - last_y) < 2 ) { MGlobal::selectFromScreen( start_x, start_y, MGlobal::kReplaceList ); } else { // Select all the objects or components within the marquee. MGlobal::selectFromScreen( start_x, start_y, last_x, last_y, MGlobal::kReplaceList ); } // Get the list of selected items MGlobal::getActiveSelectionList(marqueeList); // Restore the active selection list to what it was before // the "selectFromScreen" MGlobal::setActiveSelectionList(incomingList, MGlobal::kReplaceList); // Update the selection list as indicated by the modifier keys. MGlobal::selectCommand(marqueeList, listAdjustment); return MS::kSuccess; } MStatus marqueeContext::doEnterRegion( MEvent & ) { return setHelpString( helpString ); } ////////////////////////////////////////////// // Command to create contexts ////////////////////////////////////////////// class marqueeContextCmd : public MPxContextCommand { public: marqueeContextCmd(); virtual MPxContext* makeObj(); static void* creator(); }; marqueeContextCmd::marqueeContextCmd() {} MPxContext* marqueeContextCmd::makeObj() { return new marqueeContext(); } void* marqueeContextCmd::creator() { return new marqueeContextCmd; } ////////////////////////////////////////////// // plugin initialization ////////////////////////////////////////////// MStatus initializePlugin( MObject obj ) { MStatus status; MFnPlugin plugin( obj, "Alias", "4.5", "Any"); status = plugin.registerContextCommand( "marqueeToolContext", marqueeContextCmd::creator ); return status; } MStatus uninitializePlugin( MObject obj ) { MStatus status; MFnPlugin plugin( obj ); status = plugin.deregisterContextCommand( "marqueeToolContext" ); return status; }