admin 发表于 2015-2-6 12:43:29

NX二次开发源码分享:NXOpen C++创建UDO的过程



NX二次开发源码分享:NXOpen C++创建UDO的过程


UDO的创建是NX二次开发中最高深的一部分内容,通过这个实例,你可以看到如何注册UDO的回调函数,如何创建UDO,定义UDO的编辑,UDO的信息显示等内容!



#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <uf.h>
#include <uf_ui.h>
#include <uf_exit.h>
#include <uf_disp.h>

static void ECHO(char *format, ...)
{
    char msg;
    va_list args;
    va_start(args, format);
    vsprintf(msg, format, args);
    va_end(args);
    UF_UI_open_listing_window();
    UF_UI_write_listing_window(msg);
    UF_print_syslog(msg, FALSE);
}

#define UF_CALL(X) (report_error( __FILE__, __LINE__, #X, (X)))

static int report_error( char *file, int line, char *call, int irc)
{
    if (irc)
    {
      char err;

      UF_get_fail_message(irc, err);
      ECHO("*** ERROR code %d at line %d in %s:\n",
            irc, line, file);
      ECHO("+++ %s\n", err);
      ECHO("%s;\n", call);
    }

    return(irc);
}

#include <NXOpen/Session.hxx>
#include <NXOpen/Part.hxx>
#include <NXOpen/PartCollection.hxx>
#include <NXOpen/Callback.hxx>
#include <NXOpen/NXException.hxx>
#include <NXOpen/UI.hxx>
#include <NXOpen/Selection.hxx>
#include <NXOpen/LogFile.hxx>
#include <NXOpen/NXObjectManager.hxx>
#include <NXOpen/ListingWindow.hxx>
#include <NXOpen/View.hxx>

#include <NXOpen/UserDefinedObjects_UserDefinedClass.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedClassManager.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedObject.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedObjectManager.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedEvent.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedDisplayEvent.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedLinkEvent.hxx>
#include <NXOpen/UserDefinedObjects_UserDefinedObjectDisplayContext.hxx>

using namespace NXOpen;
using namespace NXOpen::UserDefinedObjects;

//static variables
static NXOpen::Session* theSession = NULL;
static UI* theUI = NULL;
static UserDefinedClass* myUDOclass = NULL;

//------------------------------------------------------------------------------
// Callback Name: myDisplayCB
// This is a callback method associated with displaying a UDO.
// This same callback is registered for display, select, fit, and attention point
//------------------------------------------------------------------------------
extern int myDisplayCB(UserDefinedDisplayEvent*displayEvent)
{
    try
    {
      // Get the doubles used to define the selected screen position for this UDO.
      std::vector<double> myUDOdoubles = displayEvent->UserDefinedObject()->GetDoubles();

      // Use the doubles to define points of a triangle
      std::vector<Point3d> myPoints(4);

      myPoints.X = myUDOdoubles + 0;
      myPoints.Y = myUDOdoubles + 0;
      myPoints.Z = myUDOdoubles + 0;

      myPoints.X = myUDOdoubles + 100;
      myPoints.Y = myUDOdoubles + 0;
      myPoints.Z = myUDOdoubles + 0;

      myPoints.X = myUDOdoubles + 0;
      myPoints.Y = myUDOdoubles + 100;
      myPoints.Z = myUDOdoubles + 0;

      myPoints.X = myUDOdoubles + 0;
      myPoints.Y = myUDOdoubles + 0;
      myPoints.Z = myUDOdoubles + 0;

      // Display the triangle
      displayEvent->DisplayContext()->DisplayPolyline(myPoints);

      // Display the text next to the triangle
      Point3d myPt = Point3d(myUDOdoubles + 100, myUDOdoubles, myUDOdoubles);
      displayEvent->DisplayContext()->DisplayText("C++ UDO", myPt, UserDefinedObjectDisplayContext::TextRefBottomLeft);

      // UserDefinedObjectDisplayContext::DisplayFacets fails - see PR 6731653
      // This demonstrates using UF_DISP_display_facets as a work around
      double normals = { 0,0,1, 0,0,1, 0,0,1 };
      double vertices = { myUDOdoubles, myUDOdoubles, myUDOdoubles,
                               myUDOdoubles + 100, myUDOdoubles, myUDOdoubles,
                               myUDOdoubles, myUDOdoubles + 100, myUDOdoubles };
      UF_DISP_facet_t facets = { vertices, normals };
      void *context = displayEvent->DisplayContext()->GetHandle();

      UF_initialize();
      UF_CALL(UF_DISP_display_facets(facets, 3, 1, UF_DISP_TRIANGLE, context));
      UF_terminate();

    }
    catch (NXException ex)
    {
      ECHO("Caught exception: %s\n", ex.Message());
    }
    return 0;
}
//------------------------------------------------------------------------------
// Callback Name: myEditCB
// This is a callback method associated with editing a UDO.
//------------------------------------------------------------------------------
extern int myEditCB(UserDefinedEvent* editEvent)
{
    try
    {
      // required for calls to legacy UF routines
      // such as UF_DISP_add_item_to_display
      UF_initialize();

      View* myView = NULL;
      Point3d myCursor(0,0,0);

      // highlight the current udo we are about to edit
      // this is helpful if multiple udo's were on the selection
      // list when the user decided to edit them
      editEvent->UserDefinedObject()->Highlight();

      // ask the user to select a new origin for this UDO
      Selection::DialogResponse myResponse = theUI->SelectionManager()->SelectScreenPosition("Select New Origin for C++ UDO", &myView, &myCursor);
      // we are done asking the user for input... unhighlight the udo
      editEvent->UserDefinedObject()->Unhighlight();

      // use the new screen position (if the user picked one)
      if( myResponse == Selection::DialogResponsePick )
      {
            std::vector<double> myUDOdoubles(3);
            myUDOdoubles = myCursor.X;
            myUDOdoubles = myCursor.Y;
            myUDOdoubles = myCursor.Z;
            // store the newly selected origin with the udo
            editEvent->UserDefinedObject()->SetDoubles(myUDOdoubles);
            // add the udo to the display list manually
            // this will force the udo display to regenerate
            // immediately and show the changes we just made
            UF_DISP_add_item_to_display(editEvent->UserDefinedObject()->GetTag());
      }
      UF_terminate();
    } catch (NXException ex)
    {
      ECHO("Caught exception: %s\n", ex.Message());
    } return 0;
}
//------------------------------------------------------------------------------
// Callback Name: myInfoCB
// This is a callback method associated with querying information for a UDO.
// The information is printed in the listing window.
//------------------------------------------------------------------------------
extern int myInfoCB(UserDefinedEvent* infoEvent)
{
    try
    {
      ListingWindow* theLW = theSession->ListingWindow();
      char msg;
      theLW->Open();
      theLW->WriteLine(" ");
      theLW->WriteLine("------------------------------------------------------------");
      theLW->WriteLine("Begin Custom Information");
      theLW->WriteLine(" ");
      sprintf( msg, "UDO Class Name: '%s'", infoEvent->UserDefinedObject()->UserDefinedClass()->ClassName().GetLocaleText() );
      theLW->WriteLine(msg);
      sprintf( msg, "UDO Friendly Name: '%s'", infoEvent->UserDefinedObject()->UserDefinedClass()->FriendlyName().GetLocaleText() );
      theLW->WriteLine(msg);
      std::vector<double> myUDOdoubles = infoEvent->UserDefinedObject()->GetDoubles();
      sprintf( msg, "myUDOdoubles(0) = %f", myUDOdoubles );
      theLW->WriteLine(msg);
      sprintf( msg, "myUDOdoubles(1) = %f", myUDOdoubles );
      theLW->WriteLine(msg); sprintf( msg, "myUDOdoubles(2) = %f", myUDOdoubles );
      theLW->WriteLine(msg);
      theLW->WriteLine(" ");
      theLW->WriteLine("End Custom Information");
    }
    catch (NXException ex)
    {
      ECHO("Caught exception: %s\n", ex.Message());
    }
    return 0;
}

//------------------------------------------------------------------------------
// initUDO
// Checks to see which (if any) of the application's static variables are
// uninitialized, and sets them accordingly.
// Initializes the UDO class and registers all of its callback methods.
//------------------------------------------------------------------------------
static int initUDO( bool alertUser)
{
    try
    {
      if (theSession == NULL)
      {
            theSession = Session::GetSession();
      }
      if( theUI == NULL )
      {
            theUI = UI::GetUI();
      }
      if (myUDOclass == NULL)
      {
            if (alertUser)
            {
                ListingWindow*
                  theLW = theSession->ListingWindow();
                theLW->Open();
                theLW->WriteLine("Registering C++ UDO Class");
            }
            // Define your custom UDO class
            myUDOclass = theSession->UserDefinedClassManager()->CreateUserDefinedObjectClass("Sample_Cpp_UDO", "Sample C++ UDO");
            // Setup properties on the custom UDO class
            myUDOclass->SetAllowQueryClassFromName(UserDefinedClass::AllowQueryClassOn);
            // Register callbacks for the UDO class
            myUDOclass->AddDisplayHandler(make_callback(&myDisplayCB));
            myUDOclass->AddAttentionPointHandler(make_callback(&myDisplayCB));
            myUDOclass->AddFitHandler(make_callback(&myDisplayCB));
            myUDOclass->AddSelectionHandler(make_callback(&myDisplayCB));
            myUDOclass->AddEditHandler(make_callback(&myEditCB));
            myUDOclass->AddInformationHandler(make_callback(&myInfoCB));
            // Add this class to the list of object types available for selection in NX.
            // If you skip this step you won't be able to select UDO's of this class,
            // even though you registered a selection callback.
            theUI->SelectionManager()->SetSelectionStatusOfUserDefinedClass(myUDOclass, true);
      }
    }
    catch (NXException ex)
    {
      ECHO("Caught exception: %s\n", ex.Message());
    }
    return 0;
}

//------------------------------------------------------------------------------
// ufusr (Explicit Activation)
// This entry point is used to activate the application explicitly, as in
// "File->Execute UG/Open->NX Open..."
//------------------------------------------------------------------------------
extern void ufusr( char *parm, int *returnCode, int rlen )
{
    try
    {
      // required for calls to legacy UF routines
      // such as UF_DISP_add_item_to_display
      UF_initialize();

      // initialize the UDO - if we didn't load this library at
      // startup, here is our second chance to load it
      initUDO(true);

      // if we don't have any parts open create one
      BasePart* myBasePart = theSession->Parts()->BaseDisplay();
      if( myBasePart == NULL)
      {
            myBasePart = theSession->Parts()->NewBaseDisplay("test_cpp_udo.prt", BasePart::UnitsMillimeters);
      }

      View* myView = NULL;
      Point3d myCursor(0,0,0);

      // ask the user to select an origin for this UDO
      Selection::DialogResponse myResponse = theUI->SelectionManager()->SelectScreenPosition("Select Origin of C++ UDO", &myView, &myCursor);
      if( myResponse == Selection::DialogResponsePick )
      {
            // The user selected a point - go ahead and create the udo
            UserDefinedObjectManager* myUDOmanager = myBasePart->UserDefinedObjectManager();
            UserDefinedObject* firstUDO = myUDOmanager->CreateUserDefinedObject(myUDOclass);
            // set the color property of the udo - just for fun :)
            firstUDO->SetColor(36);
            // store the origin selected by the user with the udo
            std::vector<double> myUDOdoubles(3);
            myUDOdoubles = myCursor.X;
            myUDOdoubles = myCursor.Y;
            myUDOdoubles = myCursor.Z;
            firstUDO->SetDoubles(myUDOdoubles);
            // add the udo to the display list manually
            // this will force the udo to display immediately
            UF_DISP_add_item_to_display(firstUDO->GetTag());
      }
      UF_terminate();
    }
    catch (const NXOpen::NXException& ex)
    {
      ECHO("Caught exception: %s\n", ex.Message());
    }
}

//------------------------------------------------------------------------------
// ufsta
// Entrypoint used when program is loaded automatically
// as NX starts up. Note this application must be placed in a
// special folder for NX to find and load it during startup.
// Refer to the NX Open documentation for more details on how
// NX finds and loads applications during startup.
//------------------------------------------------------------------------------
extern void ufsta( char *param, int *returnCode, int rlen )
{
    try
    {
      initUDO(false);
    }
    catch (const NXOpen::NXException& ex)
    {
      ECHO("Caught exception: %s\n", ex.Message());
    }
}

//------------------------------------------------------------------------------
// ufusr_ask_unload
// Make sure you specify AtTermination for the unload option.
// If you unload the library before the NX Session Terminates
// bad things could happen when we try to execute a udo
// callback that no longer exists in the session.
//------------------------------------------------------------------------------
extern int ufusr_ask_unload( void )
{
    return (int)Session::LibraryUnloadOptionAtTermination;
}

页: [1]
查看完整版本: NX二次开发源码分享:NXOpen C++创建UDO的过程