(menu locations in this tutorial are based on NX 7.5, programming language is Visual Basic)
Where to start? The best place to start writing a journal is with the journal recorder. This wonder of modern technology will translate your interactions with NX to journal code, in your language of choice! (this article will use Visual Basic, or VB for short). If you are following along, let’s make sure the journal output language is set to VB before we start.
Setting the Journal Programming Language:
In the menu, choosePreferences -> User Interface...; on the Journaltab choose Visual Basic as the language and make sure the Insert Menu/Dialog Box Commentsoption is checked.
Recording the Journal:
For starters, let’s assume you want to change the color of a specified solid body. Start by recording a journal Tools -> Journal -> Record... and specify a file name for your new journal, preferably something that describes its function such as “change_color.vb”. Once the journal recording process starts, you may notice a change in your toolbars and menus. The green marks on the toolbar icons/menu items indicate that journal recording is fully supported by this command; yellow marks indicate the command is partially supported.
Now that recording is under way, choose Edit -> Object Display... from the menu, pick the solid body of interest, and pick a new display color. OK the changes and then stop the journal recordingTools -> Journal -> Stop recording.
Time to test out the journal. Change the color of the solid body, or perform an Undo to get the original color back; now navigate to Tools -> Journal -> Play... and browse to your new journal file. Select your journal from the list and press the Playbutton. After a short pause, your solid body will change to the color you picked when you recorded the journal.
Understanding the New Journal Code:
Open a Windows file explorer window and browse to your new journal file, open it with a text editor (such as notepad) and take a peek at what goes on behind the scenes. Don’t worry if this looks like mumbo jumbo right now, we’ll step through it to see what is going on. I created a new file and inserted a block feature, then followed the steps outlined above; here is the resulting journal code:
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 ' ---------------------------------------------- ' Menu: Edit->Object Display... ' ---------------------------------------------- Dim markId1 As Session.UndoMarkId markId1 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, "Start") theSession.SetUndoMarkName(markId1, "Class Selection Dialog") Dim markId2 As Session.UndoMarkId markId2 = theSession.SetUndoMark(Session.MarkVisibility.Invisible, "Class Selection") theSession.DeleteUndoMark(markId2, Nothing) theSession.SetUndoMarkName(markId1, "Class Selection") theSession.DeleteUndoMark(markId1, Nothing) ' ---------------------------------------------- ' Dialog Begin Edit Object Display ' ---------------------------------------------- ' ---------------------------------------------- ' Dialog Begin Color ' ---------------------------------------------- Dim markId3 As Session.UndoMarkId markId3 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Edit Object Display") Dim displayModification1 As DisplayModification displayModification1 = theSession.DisplayManager.NewDisplayModification() displayModification1.ApplyToAllFaces = False displayModification1.ApplyToOwningParts = False displayModification1.NewColor = 103 Dim objects1(0) As DisplayableObject Dim body1 As Body = CType(workPart.Bodies.FindObject("BLOCK(0)"), Body) objects1(0) = body1 displayModification1.Apply(objects1) displayModification1.Dispose() ' ---------------------------------------------- ' Menu: Tools->Journal->Stop Recording ' ---------------------------------------------- End Sub End Module
Option Strict Off means the code will allow some types of implicit conversions, but really it isn’t something we’ll need to worry about right now.
Next up are the Imports statements, which import a specified namespace. It is important to note that these statements do not add more functionality to your code (ie they are not analogous to references to external libraries); rather they allow certain declarations to be abbreviated. In addition to NX code, journals are linked by default to certain .NET libraries. These libraries are:
A Module is declared next with the default name of NXJournal. A module is a container where all the code lives, if you skip down to the end of the journal you will see an End Module statement. Any code you add must be between the Module... End Module statements. You can change the module name to something more descriptive if you like, but since there is only one module in our journal, the default name is just fine. The module also determines the scope of variables and code it contains, but this is a topic for another day.
Sub Main is the block of code that gets called when your journal is run. As your journals get longer and more complex, it is helpful to break the code into multiple subroutines and functions and call them as necessary. Sub Main is where the core logic will reside. Every journal must have a Sub Main.
The next 3 lines initialize the session, display part, and work part for us to reference in our journal. Part and Session are classes in NXOpen, these object variables will give us access to other objects in NX.
All of the code we have looked at so far is included in every recorded journal. If you want to start a journal from scratch, including this code is a good idea.
A comment on comments:
A single apostrophe or the keyword rem indicates the start of a comment, the comment continues to the end of the line. Anything contained in the comment will be ignored by the compiler. Comments serve useful functions:
- They are most often used to document the code. Use comments to explain tricky bits of code or document the input/output requirements of functions and subroutines. Comments are also often used at the beginning of the code file to explain the who when and what: who wrote the program, when they wrote the program, and what problem the code solves or what process the code automates.
- Comments are also useful in the debugging process. Use comments to temporarily disable a line or entire block of code to try out an alternative solution without having to delete code that may yet prove useful.
Next up in the code, is the creation of a couple of useless undo marks. As you record and modify journals you will find that the journal recorder often throws in extra bits of code. The undo marks, markId1 and markId2, are good examples of this. The undo marks are created, named, renamed, and finally deleted (set to ‘nothing’) ultimately having no effect on the finished journal. If your journal contains similar code, feel free to delete it.
Creating an undo mark is a good way to start a journal as it will allow any changes made by the journal to be undone if necessary. MarkId3 is the real undo mark here. You can see the string “Edit Object Display” as one of the arguments when the id mark is set. This string is what will appear in the undo list after the journal is run. If the undo function is used, the model will roll back to the state it was in when the undo mark was set in code. It is a good idea to set an undo mark before trying to modify features; if there are any errors during the model update, it can roll back to a known state. Multiple undo marks can be set, which comes in handy in larger multi-step journals; changes can be rolled back in chunks rather than an all or nothing approach.
When declaring variables, this is the normal pattern:
Dim [variable name] as [variable type]
so the line:
Dim displayModification1 As DisplayModification
tells the compiler to set aside a block of memory large enough for a DisplayModification object and the name used to refer to it will be displayModification1. A DisplayModification is a temporary helper NX object that assists in changing the display attributes of one or more objects.
Now that we have a display modification object we can set our preferences:
displayModification1.ApplyToAllFaces = False
displayModification1.ApplyToOwningParts = False
displayModification1.NewColor = 103
As you can see, I picked color 103, cornflower blue, as my new object color. At this point our solid body has not yet changed, in fact the journal doesn’t yet know what object(s) these changes are going to apply to. Which brings us to:
Dim objects1(0) As DisplayableObject
Dim body1 As Body = CType(workPart.Bodies.FindObject("BLOCK(0)"), Body)
objects1(0) = body1
The display modification object requires an array of objects of the type DisplayableObject to work on. The first line creates a 1 element array (arrays are zero based) of DisplayableObjects, line 2 records the solid that I selected (your line of code may be different), and line 3 assigns the body to the array that will be used with the display modification object.
Now that the options are set and the object is specified we can apply our desired changes with
Now that the work is done, we can delete the temporary display modification object and free up the memory it used by calling its Dispose method:
At this point the journal exits and we can see the results in the modeling window. However, should you try to run this journal in a different file you would be met with an error message.
Hand Editing the Journal:
The reason that the journal in its current state will end in a error message when applied to a different file is that your journal is looking for the exact solid that you selected when the journal was recorded. This behavior is referred to as ‘selection stickiness’ and its removal is one of the main reasons for hand-editing journal code. You can greatly increase the usefulness of your code by replacing the hard coded reference to a specific object with a more general selection routine.
Below you will find the same script without the useless undo marks and with the selection stickiness removed. This journal can now be used on various files to change the selected solid body’s color.
Option Strict Off Imports System Imports NXOpen Imports NXOpen.UF Imports NXOpenUI 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 ufs As UFSession = UFSession.GetUFSession() Dim markId3 As Session.UndoMarkId markId3 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Edit Object Display") Dim displayModification1 As DisplayModification displayModification1 = theSession.DisplayManager.NewDisplayModification() displayModification1.ApplyToAllFaces = False displayModification1.ApplyToOwningParts = False displayModification1.NewColor = 103 Dim objects1(0) As DisplayableObject 'Dim body1 As Body = CType(workPart.Bodies.FindObject("BLOCK(0)"), Body) Dim body1 As Body = SelectSolid() objects1(0) = body1 displayModification1.Apply(objects1) displayModification1.Dispose() End Sub Function SelectSolid() As Body Dim ui As UI = ui.GetUI Dim message As String = "Select solid body" Dim title As String = "Selection" Dim scope As Selection.SelectionScope = Selection.SelectionScope.WorkPart Dim keepHighlighted As Boolean = False Dim includeFeatures As Boolean = True Dim selectionAction As Selection.SelectionAction = _ Selection.SelectionAction.ClearAndEnableSpecific 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 End With Dim selectedObject As NXObject = Nothing Dim cursor As Point3d ui.SelectionManager.SelectObject(message, title, scope, _ selectionAction, includeFeatures, _ keepHighlighted, selectionMask_array, _ selectedObject, cursor) Dim solid As Body = CType(selectedObject, Body) If solid Is Nothing Then Return Nothing End If Return solid End Function End Module
In review you can see how we can use NX Journal to create a basic journal designed to change the color of a solid body. Then we evaluated the code generated by the journal recorder and modified the code to be of broader use with just a few hand coded manipulations. The resulting journal can now change the body color of any part.
We learned how to record a journal. How to interpret the code behind the NX Journal and how to adjust the code to allow a journal to be useful across multiple files.