// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "stdafx.h" #include "frantic/magma/maya/maya_magma_gui.hpp" #include "frantic/magma/maya/maya_magma_mel_window.hpp" #include "NodeView/connection.h" #include "NodeView/node.h" #include "NodeView/socket.h" #include <QGridLayout> #include <QHBoxLayout> #include <QVBoxLayout> #include <QWidget> #include <maya/MDataHandle.h> #include <maya/MFloatVector.h> #include <maya/MFnPluginData.h> #include <maya/MFnStringArrayData.h> #include <maya/MQtUtil.h> #include <sstream> #include "frantic/magma/maya/maya_magma_desc_mpxdata.hpp" #include "frantic/maya/parser_args.hpp" #include "frantic/maya/selection.hpp" #include <frantic/logging/logging_level.hpp> #include <frantic/maya/convert.hpp> #include <frantic/maya/maya_util.hpp> namespace frantic { namespace magma { namespace maya { namespace mel { const MString maya_magma_mel_window::commandName = "add_magma_flux_window"; std::map<frantic::tstring, maya_MagmaFLUX*> maya_magma_mel_window::m_WindowNameToMagmaFLUX; std::map<frantic::tstring, maya_MagmaFLUX*> maya_magma_mel_window::m_NodeNameToMagmaFLUX; void* maya_magma_mel_window::creator() { return new maya_magma_mel_window; } #pragma region Window Finding and Window Update Events maya_MagmaFLUX* maya_magma_mel_window::findMagmaFLUXWidgetByWindowName( const MString& windowName ) { frantic::tstring name = frantic::maya::from_maya_t( windowName ); if( m_WindowNameToMagmaFLUX.count( name ) > 0 ) { return m_WindowNameToMagmaFLUX[name]; } return NULL; } maya_MagmaFLUX* maya_magma_mel_window::findMagmaFLUXWidgetByNode( const MFnDependencyNode& node ) { MString name = frantic::maya::maya_util::get_node_full_name( node ); return findMagmaFLUXWidgetByNodeName( name ); } maya_MagmaFLUX* maya_magma_mel_window::findMagmaFLUXWidgetByNodeName( const MString& nodeName ) { frantic::tstring name = frantic::maya::from_maya_t( nodeName ); return findMagmaFLUXWidgetByNodeName( name ); } maya_MagmaFLUX* maya_magma_mel_window::findMagmaFLUXWidgetByNodeName( const frantic::tstring& nodeName ) { if( m_NodeNameToMagmaFLUX.count( nodeName ) > 0 ) { return m_NodeNameToMagmaFLUX[nodeName]; } return NULL; } std::vector<maya_MagmaFLUX*> maya_magma_mel_window::findAllMagmaFLUXWidgets() { std::vector<maya_MagmaFLUX*> result; for( std::map<frantic::tstring, maya_MagmaFLUX*>::const_iterator iter = m_WindowNameToMagmaFLUX.begin(); iter != m_WindowNameToMagmaFLUX.end(); ++iter ) { result.push_back( iter->second ); } return result; } void maya_magma_mel_window::onAttributeChangedUpdateNodesInWindow( MPlug& plug ) { MObject prtNode = plug.node(); MFnDependencyNode depNode( prtNode ); maya_MagmaFLUX* magma = maya_magma_mel_window::findMagmaFLUXWidgetByNode( depNode ); if( magma != NULL ) { magma->onAttributeChangedUpdateNodesInWindow( plug ); } } void maya_magma_mel_window::addErrorNode( const MObject& prtNode, int id ) { MFnDependencyNode depNode( prtNode ); maya_MagmaFLUX* magma = maya_magma_mel_window::findMagmaFLUXWidgetByNode( depNode ); if( magma != NULL ) { magma->setNodeError( id ); } } void maya_magma_mel_window::clearErrorNodes( const MObject& prtNode ) { MFnDependencyNode depNode( prtNode ); maya_MagmaFLUX* magma = maya_magma_mel_window::findMagmaFLUXWidgetByNode( depNode ); if( magma != NULL ) { magma->clearNodeErrors(); } } void maya_magma_mel_window::removeMagmaFLUX( maya_MagmaFLUX* window ) { frantic::tstring winName = frantic::maya::from_maya_t( window->getWindowName() ); m_WindowNameToMagmaFLUX.erase( winName ); frantic::tstring nodeName = frantic::maya::from_maya_t( window->getMayaNodeName() ); m_NodeNameToMagmaFLUX.erase( nodeName ); } void maya_magma_mel_window::addMagmaFLUX( maya_MagmaFLUX* window ) { frantic::tstring winName = frantic::maya::from_maya_t( window->getWindowName() ); m_WindowNameToMagmaFLUX[winName] = window; frantic::tstring nodeName = frantic::maya::from_maya_t( window->getMayaNodeName() ); m_NodeNameToMagmaFLUX[nodeName] = window; } #pragma endregion MStatus maya_magma_mel_window::parseArgs( const MArgList& args, frantic::magma::maya::desc::maya_magma_desc_ptr desc, MFnDependencyNode& depNode ) { QWidget* windowWidget = NULL; MString windowName; MString layoutName; MStatus hasWindowName; MStatus hasLayoutName; hasWindowName = frantic::maya::parser_args::get_arg( args, "-wn", "-windowName", windowName ); hasLayoutName = frantic::maya::parser_args::get_arg( args, "-ln", "-layoutName", layoutName ); // MString nodeName = frantic::maya::selection::get_current_selected_object_names()[0]; MString nodeName = frantic::maya::maya_util::get_node_full_name( depNode ); if( findMagmaFLUXWidgetByWindowName( windowName ) != NULL ) { throw maya_magma_exception( "maya_magma_mel_window::parseArgs specified window already contains a magma flux gui" ); } else if( findMagmaFLUXWidgetByNode( depNode ) != NULL ) { throw maya_magma_exception( "maya_magma_mel_window::parseArgs specified node already associated with a magma flux gui" ); } if( hasWindowName == MS::kSuccess && hasLayoutName == MS::kSuccess ) { windowWidget = MQtUtil::findLayout( layoutName, MQtUtil::findWindow( windowName ) ); } else if( hasWindowName == MS::kSuccess && hasLayoutName != MS::kSuccess ) { windowWidget = MQtUtil::findWindow( windowName ); //} else if ( hasWindowName != MS::kSuccess && hasLayoutName == MS::kSuccess ) { // windowWidget = MQtUtil::findLayout( windowName ); } else { throw maya_magma_exception( "maya_magma_mel_window::parseArgs no window name was specified" ); } MStatus outStatus( MS::kFailure ); if( !windowWidget ) { FF_LOG( error ) << "-b layoutName = NULL: " << windowName.asChar() << " not found" << std::endl; return outStatus; } FF_LOG( debug ) << "Create window for node: " << nodeName.asChar() << std::endl; // Set up the GUI QLayout* layout = windowWidget->layout(); if( layout == NULL ) { // TODO: throw an exception instead? layout = new QGridLayout; windowWidget->setLayout( layout ); } maya_MagmaFLUX* magma = new maya_MagmaFLUX( windowName, nodeName, desc, depNode ); layout->addWidget( magma ); QSizePolicy sizePolicy; sizePolicy.setHorizontalPolicy( QSizePolicy::Expanding ); sizePolicy.setVerticalPolicy( QSizePolicy::Expanding ); magma->setSizePolicy( sizePolicy ); addMagmaFLUX( magma ); outStatus = MS::kSuccess; return outStatus; } //////////////////////////////////////////////////////////////////////////////// const MString maya_magma_mel_window_retrieve::commandName = "magma_flux_window_query"; void* maya_magma_mel_window_retrieve::creator() { return new maya_magma_mel_window_retrieve; } MStatus maya_magma_mel_window_retrieve::parseArgs( const MArgList& args, frantic::magma::maya::desc::maya_magma_desc_ptr desc, MFnDependencyNode& depNode ) { maya_MagmaFLUX* windowWidget; MString windowName; bool getNodes; bool getEdges; bool getLastXY; MStatus hasWindowName; int argCount = 0; hasWindowName = frantic::maya::parser_args::get_arg( args, "-i", "-id", windowName ); getNodes = frantic::maya::parser_args::get_bool_arg( args, "-n", "-nodes" ); getEdges = frantic::maya::parser_args::get_bool_arg( args, "-e", "-edges" ); getLastXY = frantic::maya::parser_args::get_bool_arg( args, "-lxy", "-lastXY" ); if( hasWindowName != MS::kSuccess ) { windowWidget = maya_magma_mel_window::findMagmaFLUXWidgetByNode( depNode ); } else { windowWidget = maya_magma_mel_window::findMagmaFLUXWidgetByWindowName( windowName ); } if( windowWidget == NULL ) { throw maya_magma_exception( "maya_magma_mel_window_retrieve::parseArgs window not found" ); } if( getNodes ) argCount++; if( getEdges ) argCount++; if( getLastXY ) argCount++; if( argCount > 1 ) { throw maya_magma_exception( "maya_magma_mel_window_retrieve::parseArgs more than one option specified, please " "specify just one option" ); } else if( argCount <= 0 ) { throw maya_magma_exception( "maya_magma_mel_window_retrieve::parseArgs no option specified" ); } if( getNodes ) { std::vector<int> nodes = windowWidget->getSelectedNodes(); MIntArray result; for( std::vector<int>::const_iterator iter = nodes.begin(); iter != nodes.end(); ++iter ) { result.append( *iter ); } setResult( result ); } else if( getEdges ) { std::vector<maya_MagmaFLUX::connection_data> edges = windowWidget->getSelectedEdges(); MStringArray result; for( std::vector<maya_MagmaFLUX::connection_data>::const_iterator iter = edges.begin(); iter != edges.end(); ++iter ) { result.append( iter->toStdString().c_str() ); } setResult( result ); } else if( getLastXY ) { MIntArray result( 2 ); int x, y; windowWidget->getLastNodePosition( x, y ); result[0] = x; result[1] = y; setResult( result ); } MStatus outStatus( MS::kSuccess ); return outStatus; } //////////////////////////////////////////////////////////////////////////////// const MString maya_magma_mel_window_set::commandName = "magma_flux_window_set"; void* maya_magma_mel_window_set::creator() { return new maya_magma_mel_window_set; } MStatus maya_magma_mel_window_set::parseArgs( const MArgList& args, frantic::magma::maya::desc::maya_magma_desc_ptr desc, MFnDependencyNode& depNode ) { maya_MagmaFLUX* windowWidget; MString windowName; MIntArray nodeIDs; MStringArray edgeData; MStatus hasWindowName; hasWindowName = frantic::maya::parser_args::get_arg( args, "-i", "-id", windowName ); if( hasWindowName != MS::kSuccess ) { windowWidget = maya_magma_mel_window::findMagmaFLUXWidgetByNode( depNode ); } else { windowWidget = maya_magma_mel_window::findMagmaFLUXWidgetByWindowName( windowName ); } if( windowWidget == NULL ) { throw maya_magma_exception( "magma_flux_window_set::parseArgs window not found" ); } { // Node / Edges Selection bool selected = false; std::vector<int> nodes; std::vector<maya_MagmaFLUX::connection_data> edges; if( frantic::maya::parser_args::get_int_array_arg( args, "-n", "-nodes", nodeIDs ) ) { for( unsigned int i = 0; i < nodeIDs.length(); i++ ) { nodes.push_back( nodeIDs[i] ); } selected = true; } if( frantic::maya::parser_args::get_string_array_arg( args, "-e", "-edges", edgeData ) ) { for( unsigned int i = 0; i < edgeData.length(); i++ ) { frantic::tstring data = frantic::maya::from_maya_t( edgeData[i] ); edges.push_back( maya_MagmaFLUX::connection_data( data ) ); } selected = true; } if( selected ) { windowWidget->setSelection( nodes, edges ); } } { // Last Node position int lastX, lastY; bool hasLastX, hasLastY; hasLastX = frantic::maya::parser_args::get_int_arg( args, "-lx", "-lastX", lastX ); hasLastY = frantic::maya::parser_args::get_int_arg( args, "-ly", "-lastY", lastY ); if( hasLastX || hasLastY ) { int lx, ly; windowWidget->getLastNodePosition( lx, ly ); if( hasLastX ) lx = lastX; if( hasLastY ) ly = lastY; windowWidget->setLastNodePosition( lx, ly ); } } { // Window background color int r, g, b; bool hasR, hasG, hasB; hasR = frantic::maya::parser_args::get_int_arg( args, "-bgr", "-backgroundred", r ); hasG = frantic::maya::parser_args::get_int_arg( args, "-bgg", "-backgroundgreen", g ); hasB = frantic::maya::parser_args::get_int_arg( args, "-bgb", "-backgroundblue", b ); if( hasR || hasG || hasB ) { QColor color = windowWidget->backgroundColor(); if( hasR ) color.setRed( r ); if( hasG ) color.setGreen( g ); if( hasB ) color.setBlue( b ); windowWidget->setBackgroundColor( color ); } } { // Grid color int r, g, b; bool hasR, hasG, hasB; hasR = frantic::maya::parser_args::get_int_arg( args, "-gr", "-gridred", r ); hasG = frantic::maya::parser_args::get_int_arg( args, "-gg", "-gridgreen", g ); hasB = frantic::maya::parser_args::get_int_arg( args, "-gb", "-gridblue", b ); if( hasR || hasG || hasB ) { QColor color = windowWidget->gridColor(); if( hasR ) color.setRed( r ); if( hasG ) color.setGreen( g ); if( hasB ) color.setBlue( b ); windowWidget->setGridColor( color ); } } { // Grid size int size; bool hasarg = frantic::maya::parser_args::get_int_arg( args, "-gs", "-gridsize", size ); if( hasarg ) { windowWidget->setGridSize( size ); } } { // Grid on/off bool on; bool hasarg = frantic::maya::parser_args::get_bool_arg( args, "-g", "-grid", on ); if( hasarg ) { windowWidget->setGridLines( on ); } } { // Grid snap bool on; bool hasarg = frantic::maya::parser_args::get_bool_arg( args, "-s", "-snaptogrid", on ); if( hasarg ) { windowWidget->setSnapToGrid( on ); } } { // Pan and Zoom double cx, cy; bool hasCx = frantic::maya::parser_args::get_float_arg( args, "-cx", "-centerx", cx ); bool hasCy = frantic::maya::parser_args::get_float_arg( args, "-cy", "-centery", cy ); if( hasCx || hasCy ) { QPointF currentCenter = windowWidget->mapToScene( windowWidget->viewport()->rect() ).boundingRect().center(); if( hasCx ) currentCenter.setX( cx ); if( hasCy ) currentCenter.setY( cy ); windowWidget->centerOn( currentCenter ); } double zoom; bool hasZoom = frantic::maya::parser_args::get_float_arg( args, "-z", "-zoom", zoom ); if( hasZoom ) { windowWidget->setZoom( zoom ); } } { // Selection mode int mode; bool hasSelectionMode = frantic::maya::parser_args::get_int_arg( args, "-sm", "-selectmode", mode ); if( hasSelectionMode ) { if( mode < 0 || mode >= 0x3 ) { // Invalid mode ignored } else { windowWidget->setRubberBandSelectionMode( static_cast<Qt::ItemSelectionMode>( mode ) ); } } } MStatus outStatus( MS::kSuccess ); return outStatus; } //////////////////////////////////////////////////////////////////////////////// const MString maya_magma_mel_window_menu::commandName = "magma_flux_window_menu"; void* maya_magma_mel_window_menu::creator() { return new maya_magma_mel_window_menu; } MStatus maya_magma_mel_window_menu::parseArgs( const MArgList& args, frantic::magma::maya::desc::maya_magma_desc_ptr desc, MFnDependencyNode& depNode ) { maya_MagmaFLUX* windowWidget; MString windowName; MStatus hasWindowName; hasWindowName = frantic::maya::parser_args::get_arg( args, "-i", "-id", windowName ); if( hasWindowName != MS::kSuccess ) { windowWidget = maya_magma_mel_window::findMagmaFLUXWidgetByNode( depNode ); } else { windowWidget = maya_magma_mel_window::findMagmaFLUXWidgetByWindowName( windowName ); } if( windowWidget == NULL ) { throw maya_magma_exception( "magma_flux_window_menu::parseArgs window not found" ); } bool clear; bool hasMenuPath; MStringArray menuPath; bool hasMenuCommand; MString menuCommand; bool hasShowCommand; MIntArray showCommandPosition; clear = frantic::maya::parser_args::get_bool_arg( args, "-c", "-clear" ); hasMenuPath = frantic::maya::parser_args::get_string_array_arg( args, "-m", "-menu", menuPath ); hasMenuCommand = frantic::maya::parser_args::get_arg( args, "-a", "-action", menuCommand ); hasShowCommand = frantic::maya::parser_args::get_int_array_arg( args, "-s", "-show", showCommandPosition ); if( hasMenuPath != hasMenuCommand ) { throw maya_magma_exception( "magma_flux_window_menu::parseArgs menu path and action command must both be specified" ); } if( hasShowCommand && showCommandPosition.length() < 2 ) { throw maya_magma_exception( "magma_flux_window_menu::parseArgs show command argument must be of size 2" ); } if( clear ) { windowWidget->clearRightClickMenu(); } if( hasMenuPath && hasMenuCommand ) { windowWidget->addRightClickMenu( frantic::maya::from_maya_t( menuPath ), frantic::maya::from_maya_t( menuCommand ) ); } if( hasShowCommand ) { MString result = windowWidget->showRightClickMenu( showCommandPosition[0], showCommandPosition[1] ); setResult( result ); } MStatus outStatus( MS::kSuccess ); return outStatus; } } // namespace mel } // namespace maya } // namespace magma } // namespace frantic