Adding an Interactive Selection Routine using SelectObject(...) and SelectObjects(...)

Adding an interactive selection routine also allows you to generalize your journal and make it more useful. Limiting, or filtering the allowed selection types is vital to getting your journal to work correctly.  The selection object will give you the power and flexibility needed for selecting one or more objects of one or more different types.

Using the Basic SelectObject(...)

This method of the selection object allows the user to select only a single object of a given type. To use it, you’ll need a reference to the UserInterface (UI) object (Journals that reference the UI object will not be able to run in batch mode). As of this writing, there are at least 3 ways to call the SelectObject Method. Technically speaking, the method is overloaded. If you don’t know or don’t care what that means, don’t worry the code samples will still work for you.

Here’s the signature of the first version:

Public Function SelectObject( _
    message As String, _
    title As String, _
    scope As Selection.SelectionScope, _
    keepHighlighted As Boolean, _
    typeArray As Selection.SelectionType(), _
    <OutAttribute> ByRef object As NXObject, _
    <OutAttribute> ByRef cursor As Point3d _
) As Selection.Response

The first 5 parameters are input to the function, setting certain desired behavior for the selection routine. The last 2 parameters are variables that will be modified (returned) by the function (note the <OutAttribute> tags).

When the method is called, a small dialog box will be presented to the user. This dialog box looks similar to the Export Parasolid dialog box, but with even fewer options. You can specify the title and prompt of this dialog box with the message and title parameters. The title parameter you pass in will appear in the title bar of the dialog box and the message parameter will show up in the cue line (which may be above or below the graphics window depending on the user interface layout options).

 

Limiting the SelectObject(...)

Next up, you can limit where a valid selection can take place with the scope parameter. The available options here are:

  • Selection.SelectionScope.UseDefaultSelection
  • SelectionScope.WorkPart - limit selection to only entities within the work part
  • Selection.SelectionScope.AnyInAssembly - select from pretty much anywhere
  • Selection.SelectionScope.WorkPartAndOccurrence - limit selection to the work part and its components

A boolean parameter (True or False), keepHighlighted, will control the highlight behavior of the selected object. A False value should be passed in, unless you have a good reason to keep the object highlighted for longer than what is normal for NX. Should you decide that keepHighlighted is what you need, you will need to add additional code to un-highlight the objects where you see fit. If you are using the dialog styler, you may need the control that keepHighlighting = True will give you. Should your journal end before the objects have been unhighlighted, they will remain highlighted until the user selects/deselects the object, or runs a part cleanup with the ‘Remove Extraneous Highlighting’ option; an annoyance your users will likely complain about. You have been warned.

The typeArray parameter is an array of Selection.SelectionType objects. The values you choose to pass in to this parameter will limit the types of objects allowed for selection. The available values to use are:

  • Selection.SelectionType.All
  • Selection.SelectionType.Features
  • Selection.SelectionType.Curves
  • Selection.SelectionType.Faces
  • Selection.SelectionType.Edges
  • Selection.SelectionType.CurvesAndEdges

If you want to limit selection to faces and edges, your type array would look like this:

Dim typeArray() As Selection.SelectionType = _
   {Selection.SelectionType.Faces, _
   Selection.SelectionType.Edges}

(Note: the variable does not need to be named typeArray, any valid variable name will work)
SelectionType.All is a little misleading, in reality it seems to mean all except faces, edges, and features. If you want to give the user the ability to select from anything use:

Dim typeArray() As Selection.SelectionType = _
   {Selection.SelectionType.All, _
   Selection.SelectionType.Faces, _
   Selection.SelectionType.Edges, _
   Selection.SelectionType.Features}

By using the filters on the selection toolbar, the user will be able to further narrow the selection type. For instance, if the journal specifies SelectionType.CurvesAndEdges, the user can filter his selection to only curves; he cannot, however, broaden the filter to include objects other than curves or edges.

The object variable passed in will be set to a reference of the object the user picked and the cursor variable will return the cursor location when the object was picked; unless the user opted to select by name (the dialog box mentioned earlier allows for input of an object’s name) in which case cursor would be undefined.

An example program follows, I encourage you to change the members of typeArray to see what affect they have on the selection.

Option Strict Off
Imports System
Imports NXOpen
 
Module NXJournal
Sub Main
 
Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim lw As ListingWindow = theSession.ListingWindow
Dim mySelectedObject As NXObject
 
lw.Open
 
'Continue prompting for a selection until the user
'  presses Cancel or Back.
Do Until SelectAnObject("Hey, select something", _
                       mySelectedObject) = Selection.Response.Cancel
   lw.WriteLine("Object Tag: " & mySelectedObject.Tag)
   lw.WriteLine("Object Type: " & mySelectedObject.GetType.ToString)
   lw.WriteLine("")
Loop
 
' The close method closes the text stream to the window,
'   it does not close the window itself
'   (use the .CloseWindow() method for that).
' Also, if you are using the listing window to write
'   to a file, the close method will clean up and close the file.
lw.Close
 
End Sub
 
    Function SelectAnObject(prompt As String, _
               ByRef selObj As NXObject) As Selection.Response
 
       Dim theUI As UI = UI.GetUI
       Dim cursor As Point3d
       Dim typeArray() As Selection.SelectionType = _
           {Selection.SelectionType.All, _
               Selection.SelectionType.Faces, _
               Selection.SelectionType.Edges, _
               Selection.SelectionType.Features}
 
       Dim resp As Selection.Response = theUI.SelectionManager.SelectObject( _
               prompt, "Selection", _
               Selection.SelectionScope.AnyInAssembly, _
               False, typeArray, selobj, cursor)
 
       If resp = Selection.Response.ObjectSelected Or _
               resp = Selection.Response.ObjectSelectedByName Then
           Return Selection.Response.Ok
       Else
           Return Selection.Response.Cancel
       End If
 
    End Function
 
End Module

 

Using SelectObjects(...)

If you need to allow selection of multiple objects, try out the SelectObjects(...) method. The parameter signature of this method is very similar to the single select version; two notable exceptions are you must create and pass in an array variable to hold the selected object(s) and there is no cursor parameter (Point3d) passed to or returned from the function.

Option Strict Off
Imports System
Imports NXOpen
 
Module NXJournal
Sub Main
 
Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim lw As ListingWindow = theSession.ListingWindow
Dim mySelectedObjects as NXObject()
 
lw.Open
 
If SelectObjects("Hey, select multiple somethings", _
               mySelectedObjects) = Selection.Response.Ok Then
       lw.WriteLine("You selected " & mySelectedObjects.Length & " object(s)")
       lw.WriteLine("")
   For Each mySelObj As NXObject in mySelectedObjects
       lw.WriteLine("Object Tag: " & mySelObj.Tag)
       lw.WriteLine("Object Type: " & mySelObj.GetType.ToString)
       lw.WriteLine("")
   Next
 
End if
 
' The close method closes the text stream to the window,
'   it does not close the window itself
'   (use the .CloseWindow() method for that).
' Also, if you are using the listing window to write
'   to a file, the close method will clean up and close the file.
lw.Close
 
End Sub
 
    Function SelectObjects(prompt As String, _
               ByRef selObj as NXObject()) As Selection.Response
 
       Dim theUI As UI = UI.GetUI
       Dim typeArray() As Selection.SelectionType = _
           {Selection.SelectionType.All, _
               Selection.SelectionType.Faces, _
               Selection.SelectionType.Edges, _
               Selection.SelectionType.Features}
 
       Dim resp As Selection.Response = theUI.SelectionManager.SelectObjects( _
               prompt, "Selection", _
               Selection.SelectionScope.AnyInAssembly, _
               False, typeArray, selobj)
 
       If resp = Selection.Response.ObjectSelected Or _
               resp = Selection.Response.ObjectSelectedByName Or _
               resp = Selection.Response.OK Then
           Return Selection.Response.Ok
       Else
           return Selection.Response.Cancel
       End If
 
    End Function
 
End Module

 

Recap:

By using the SelectObject()or SelectObjects() methods, we can easily prompt the user, limit the selected object types, and even limit the user to the selection of a single object. These methods also provide for an easy way to allow the user to select anything in the file.

The drawback to the typeArray method of selection is it may not give enough control. What if you needed to limit selection to circular edges, for example? The bad news is this version of SelectObjects won’t get you there; the good news is there is a version that will. This level of granularity comes at a price - it is more difficult to set up, but that’s a story for another article on selection SelectObjectMaskTriple().

Objectives:

In this tutorial we have identified the four options of the selection routine, discussed their purposes, and looked at the code behind each option.

Comments

Hi,

I am tyring to use a selection to create intersection curves. I created the journal and am now replacing the hardcoded objects with selections. However with my selections I am getting the following compile error;

Value of 'NXOpen.NXObject' cannot be converted to '1-dimensional array of NXOpen.NXObject'

The object I am trying to select used to look like this in the journal;

Dim trimBody1 As Features.TrimBody = CType(workPart.Features.FindObject("TRIM_BODY(7)"), Features.TrimBody)

Replaced with

Dim trimBody1 As Features.TrimBody = SelectObjects("SELECT", MySelectedObjects)

Using your code but with the selection intent limited to features. I have tried using the triple mask array, which compiles but I cannot limit the selection intent to my trim body, because the company I work for doesn't let us at the help files so don't know the code!!

Thanks for any help

Cheers,

David

The error message quoted means the function is expecting an array of objects, but you have passed it a single (non-array) object. If you look closely at the original journal recorder code, it probably has lines such as:

Dim trimBody1 As Features.TrimBody = CType(workPart.Features.FindObject("TRIM_BODY(7)"), Features.TrimBody)
Dim someObjects() as NXObject
someObject(0) = trimBody1
'do something with the someObject array

This way, your object is now in an array. At first glance, such code looks redundant and useless, but if the next function/method used expects an array of objects, you must pass it an array of objects - even if it is an array containing only 1 object.

Thanks for the reply. Perhaps I'm being stupid, I know have this;

Dim mySelectedObjects(0) As NXObject
Dim trimBody1 As Features.TrimBody() = SelectObjects("selection", mySelectedObjects(0))
Dim some_object(0) As Features.TrimBody
some_object(0) = trimBody1

And Now I'm getting the same error as before, and an additional one that is the reverse of it (if that makes sense).

If it helps, the next bit of code goes like this (eventually I need to add a selection for these faces)

Dim faces1(0) As Face
Dim face1 As Face = CType(some_object.FindObject("FACE 1 {(-108,0,13.2966628020032) LINKED_BODY(1)}"), Face)

faces1(0) = face1
Dim faceDumbRule1 As FaceDumbRule
faceDumbRule1 = workPart.ScRuleFactory.CreateRuleFaceDumb(faces1)

Dim rules1(0) As SelectionIntentRule
rules1(0) = faceDumbRule1
scCollector1.ReplaceRules(rules1, False)

sketchIntersectionCurveBuilder1.CollectorUpdated()

Again, thank you for any help

Cheers,

David

Hi

I am very new to this and may be asking a very basic question here, but when Selection interface where can I get a list of the selection type filters from.?

I can see from examples how to select a solid body but what if I want to filter just dimensions?

regards
Martyn

There is another version of the SelectObjects function that can further refine your filter by using "mask triple" values. For more info, see: http://nxjournaling.com/?q=content/using-mask-triples-selectobject-routine

Hi

Yes I ahve already seen that but my real question is where the filter information types come from? for instances what I have pasted below selects a Solid, but I want to select a dimension, is there a list of these filters?

Regards
Martyn

Dim selectionMask_array(0) As Selection.MaskTriple
With selectionMask_array(0)
.Type = UFConstants.UF_solid_type
.Subtype = 0
.SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_SOLID_BODY

Here's a quote from the article I linked in the previous post:

"So how do you know what numbers to pass in to the maskTriple? All of the available object types and subtypes can be found in the uf_object_types.h file which is in the UGOPEN subdirectory in your NX install path. The available SolidBodySubtypes can be found in the uf_ui_types.h file, which can also be found in the UGOPEN directory. This is a large file, so search for 'Constants for selection solid_type' to find your available options quickly."

Thanks very much for that, my brain is on overload so must have just missed that.

That certainly is a large file.

How would these change the code??

SelectionScope.WorkPart - limit selection to only entities within the work part
or
SelectionScope.displayPart - limit selection to only entities within the display part

Carlo Tony Daristotile

In NX8 and earlier (what I am working with at the time of this writing) SelectionScope.DisplayPart is NOT an option.

If you are working in the context of a piece part file, then SelectionScope.WorkPart and SelectionScope.AnyInAssembly are essentially the same. However, if you are working in the context of an assembly with a component set as the work part, you can limit the selection to just that work part, or allow anything in the assembly to be selected.

Hello, I'm working on Journaling to (1) select some edges, next (2)extrude the selected edges (with ExtrudeBuilder), and then (3) offset the surface that were generated in extrudeBuilder.

Blow were portion of the journal while I recorded for offsetFaceBuilder. But,I need to make the journal generic. I guess finding face using "For each ... Next" loop may be possible solution to avoid the findObject prolem. But, I can`t create correct journal with For each Next loop. Can anybody advise me to do that?

Thanks,
Kazu
'''''''''''''''''
''' extrude1 is resultant of extrudeBuilder
Dim face1 As Face = CType(extrude1.FindObject _
("FACE 160 {(2209.9739405704049,-395.8384292929383,1236.0401153256587) EXTRUDE(89)}"), Face)
'''''''''''''''''

The extrude builder's .CommitFeature method will return a reference to an extrude feature. You can use the extrude feature's .GetBodies method to get references to any bodies created by the extrude feature. When you have a reference to a body object, you can use its .GetFaces method to query all the faces in the body.

Hi,

I am trying to write/modify a journal that colors faces and bodies. Is selecetObjects(...) the function I want to use? And instead of a sub returning a type of body, what would the type be, string?

If you want the user to interactively select the bodies and/or faces; then yes, the selectObjects function would be a good method. Instead of passing in/returning a "body" or "face" object type, you could use the "displayableObject" type, from which both the body and face inherit.

If you have certain conditions of which faces/bodies should be changed, you could code that into the journal and skip the interactive selection step. For instance, if you want all the bodies/faces on layer 3 to be blue, you could write code to find those on layer 3 and change them accordingly.

Automating it would be awesome...however it might be a lot of coding, because the criteria i would need is for tap drilled holes to be one color, dowel holes to be another and fastener clearances a third color. Not to mention the machined faces. I am also dealing with primarily un-parameterized "dumb" solids

I also see a problem in that If a user has 5mm dowel pin and an M6 fastener, the tapped hole will be the same size. I did consider tagging faces, which may be more along the lines of six of one and half dozen of the other.

Hello,
With SelectObjects (...) I would like to add an expression in a child component selected with SelectObjects (...) from an assembly ... example an assembly of 4-5 components. I want the expressions to be added to the selected component without being forgotten to be MakeDiplayPart in the component. I would like to add four expressions;
1X trype string DIM1 = "TestDim1"
1X type number DIM2 = 1.23456
1X boolean DIM3 = True
1X Integer DIM4 = 20

Can you help me?
Regards!

Pat

In my code, from a assembly, I select a source component and want to copy some expression into a target component through an assembly. The section of my code to select the source and target comps works great.

But my problem is, that to edit an expression of must get an NXopen.part and my SelectObjects (...) I get an NXopen.component.assembly. When selecting the source component and the target component, the filter is on component.

I would like to know how to switch from a NXopen.component.assemly to a NXopen.part?

Here's a part of my code ...i have an error on ''iNXObject1 = component1.Prototype''...

Can someone have a solution for me?

Thank you !
Regards !

'*************************************************************************
' FONCTION "MANIPULATION DES EXPRESSION"
'*************************************************************************
Function ManipulationDesExpressions ()'(ByVal sel_obj_source As NXObject, ByVal sel_obj_cible As NXObject)

Dim component1 As NXOpen.Assemblies.Component = CType(sel_obj_source, NXOpen.Assemblies.Component)

Dim iNXObject1 As NXOpen.INXObject = Nothing
iNXObject1 = component1.Prototype

Dim part2 As NXOpen.Part = CType(iNXObject1, NXOpen.Part)

Dim ExpSource_EPAISSEUR As Expression
Try
ExpSource_EPAISSEUR = CType(part2.Expressions.FindObject("EPAISSEUR"), Expression)
Echo("Val: " & ExpSource_EPAISSEUR)

Catch ex As Exception

'---- Enter your exception handling code here -----
theUI.NXMessageBox.Show("Block Styler", NXMessageBox.DialogType.Error, ex.ToString)
End Try

End Function

Pat

If you have a reference to a component, you can use the .Prototype and .OwningPart properties/methods to get a reference to the piece part.

Dim myPart as Part = myComp.Prototype.OwningPart

If i would like to select same part of large quantities(>1).What would be the code for that case.
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections.Generic
imports System.Windows.Forms
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI

Module Module1

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work

Sub Main()

Dim selComp As NXOpen.Assemblies.Component = Nothing
If SelectComponent(selComp) = Selection.Response.Cancel Then
Exit Sub
End If

Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(message, _
title, scope, selAction, _
includeFeatures, keepHighlighted, selectionMask_array, _
selObj, cursor)
If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
Return Selection.Response.Ok
Else
Return Selection.Response.Cancel
End If

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer
GetUnloadOption = NXOpen.UF.UFConstants.UF_UNLOAD_IMMEDIATELY
End Function
End module

Once the selection is done i would like assign a value (either rotate/translate ) each of the selected parts.Suggestions please.

Atleaset for now please suggest on the Selection of Objects.

If you want to select more than one object, you will need to use the .SelectTaggedObjects method (note the "s" at the end of the name). See the "Using SelectObjects" section of article:
http://www.nxjournaling.com/content/using-mask-triples-selectobject-routine
The article was written before the NX API was updated with the .SelectTaggedObjects method, but the main points are the same.

Thanks.

Hello,

i try to set the selection Type = view

It's possible ?

Regards !

Pat

I'd suggest using the "mask triples" selection method for this task. The code below will allow you to select any type of view; by changing the subtype option, it can be made more specific, if desired.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
 
Module Module1
 
    Sub Main()
 
        Dim theSession As Session = Session.GetSession()
        If IsNothing(theSession.Parts.BaseWork) Then
            'active part required
            Return
        End If
 
        Dim workPart As Part = theSession.Parts.Work
        Dim lw As ListingWindow = theSession.ListingWindow
        lw.Open()
 
        Dim theDrftView As Drawings.DraftingView
        If SelectDraftingView("select drafting view", theDrftView) = Selection.Response.Cancel Then
            Return
        End If
 
        lw.WriteLine("view selected: " & theDrftView.Name)
 
        lw.Close()
 
    End Sub
 
    Function SelectDraftingView(ByVal prompt As String, ByRef selView As Drawings.DraftingView) As Selection.Response
 
        Dim theUI As UI = UI.GetUI
        Dim title As String = "Select a drafting view"
        Dim includeFeatures As Boolean = False
        Dim keepHighlighted As Boolean = False
        Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
        Dim cursor As Point3d
        Dim scope As Selection.SelectionScope = Selection.SelectionScope.WorkPart
        Dim selectionMask_array(0) As Selection.MaskTriple
        Dim selObj As TaggedObject
 
        With selectionMask_array(0)
            .Type = UFConstants.UF_view_type
            .Subtype = UFConstants.UF_all_subtype
        End With
 
        Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(prompt, _
         title, scope, selAction, _
         includeFeatures, keepHighlighted, selectionMask_array, _
         selObj, cursor)
        If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
            selView = CType(selObj, Drawings.DraftingView)
            Return Selection.Response.Ok
        Else
            Return Selection.Response.Cancel
        End If
 
    End Function
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image immediately after execution within NX
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
 
    End Function
 
End Module

Hello

thanks for the information.

When I click on a view your code works very well.
However, if I click on the '' Sheet '', I get an error message at line 21 and 53.

Do you have an idea how to avoid this error?

The selection mode not only allows to select a View but also the Sheet and that is what causes the error.

Pat

The code errors because it allows any type of view to be chosen, but it then assumes a drafting view was chosen and attempts to convert the chosen object to a drafting view (the sheet is technically not a drafting view). The fix we employ will depend on the behavior that you want: we can change the selection filter so that only drafting views may be chosen by the user or we can alter the other code to handle any type of view.

The code below allows any view to be chosen, it fixes the assumption made in the previous journal.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
 
Module Module1
 
    Sub Main()
 
        Dim theSession As Session = Session.GetSession()
        If IsNothing(theSession.Parts.BaseWork) Then
            'active part required
            Return
        End If
 
        Dim workPart As Part = theSession.Parts.Work
        Dim lw As ListingWindow = theSession.ListingWindow
        lw.Open()
 
        Dim theDrftView As View
        If SelectDraftingView("select a view", theDrftView) = Selection.Response.Cancel Then
            Return
        End If
 
        lw.WriteLine("view selected: " & theDrftView.Name)
 
        lw.Close()
 
    End Sub
 
    Function SelectDraftingView(ByVal prompt As String, ByRef selView As View) As Selection.Response
 
        Dim theUI As UI = UI.GetUI
        Dim title As String = "Select a view"
        Dim includeFeatures As Boolean = False
        Dim keepHighlighted As Boolean = False
        Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
        Dim cursor As Point3d
        Dim scope As Selection.SelectionScope = Selection.SelectionScope.WorkPart
        Dim selectionMask_array(0) As Selection.MaskTriple
        Dim selObj As TaggedObject
 
        With selectionMask_array(0)
            .Type = UFConstants.UF_view_type
            .Subtype = UFConstants.UF_all_subtype
        End With
 
        Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(prompt, _
         title, scope, selAction, _
         includeFeatures, keepHighlighted, selectionMask_array, _
         selObj, cursor)
        If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
            selView = CType(selObj, View)
            Return Selection.Response.Ok
        Else
            Return Selection.Response.Cancel
        End If
 
    End Function
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
 
        'Unloads the image immediately after execution within NX
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
 
    End Function
 
End Module

Hello,
when i refer to api reference it told me to use Selection.SelectTaggedObject instead.
But in fact,i cant find any selecttaggedobject method in the little box showing when i just type :NXOpen.Selection.".Acutally i can get access to selectTaggedObject method in
NXOpen namespace which is like"NXOpen.SelectTaggedObject",which confuses me a lot.
My real problem is i want to use selectTaggedObjects method.In the reference guide,it says that "Namespaces ► NXOpen ► Selection ► SelectTaggedObjects".Again,i cant find this function when i use my IDE(VS2012) under the Selection namespace,and under NXOpen,i can find SelectTaggedObject and SelectTaggedObjectList,is this later one what i want?
Thank you

The .SelectTaggedObject method (as used in the code above) can be found in the UI object:

NXOpen -> UI -> SelectionManager -> SelectTaggedObject