Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iLogic: Pass an argument back to calling rule

19 REPLIES 19
SOLVED
Reply
Message 1 of 20
DRoam
5242 Views, 19 Replies

iLogic: Pass an argument back to calling rule

So I just finally learned how to pass arguments when running an iLogic rule, which is awesome. This opens up a lot of doors. I can basically use an external rule as a "Sub" -- pass arguments to it, and make it do stuff based on them.

 

However, now that I can do this, it would be really neat if I could use an External rule as a "function". I'm wondering if it's possible for the called rule (the one that received arguments from the calling rule) to return a value BACK to the calling rule?

 

I've created a simple example below of how this might work. There's a main rule that wants to get the value of a custom iProperty, and it does so by calling on an External rule called "CustomPropCheck". Telling the External rule which iProperty to check for is easy enough, by passing it as an argument.

 

However, where I'm stumped is how to pass the iProperty value that "CustomPropCheck" gets BACK to the calling Main Rule.

 

The only thing I can think of is to maybe use Shared Variables, but I'd like to do this in a more direct way, like how Arguments work. Is there some way to pass a value back UP the call stack, like we can pass them DOWN the call stack via arguments?

 

Thanks for any suggestions!

 

Main Rule:

 

'---Set up arguments'---
Dim oRuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap() oRuleArguments.Add("oPropName","Total QTY")
'---Call external "function" rule--- iLogicVb.RunExternalRule("CustomPropCheck",oRuleArguments)
'---Retrieve resultant value from "function" rule--- 'How??
'---Display retrieved value--- MessageBox.Show("Main Rule - iProp Value: " & oPropValue)

 

"CustomPropCheck" external rule:

 

'---Get argument values---
Dim oPropName As String = RuleArguments("oPropName")

'---Determine iProperty value--- Dim oPropValue As String Try oPropValue = ThisDoc.Document.PropertySets.Item("Inventor User Defined Properties").Item(oPropName).Value Catch oPropValue = "**DNE**" End Try
'---Display iProperty value--- MessageBox.Show("CustomPropCheck - iProp Value: " & oPropValue)
'---Pass oPropValue value back to main rule--- 'How??

 

19 REPLIES 19
Message 2 of 20
R.Mabery
in reply to: DRoam

Hi DRoam,

 

Hope this helps

 

Main Rule:

 

'---Set up arguments'---
Dim oRuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
oRuleArguments.Add("oPropName","Total QTY")

'---Call external "function" rule---
iLogicVb.RunExternalRule("CustomPropCheck",oRuleArguments)

'---Retrieve resultant value from "function" rule---
oPropValue = oRuleArguments.Item("Return")

'---Display retrieved value---
MessageBox.Show("Main Rule - iProp Value: " & oPropValue)

CustomPropCheck rule:

'---Get argument values---
Dim oPropName As String = RuleArguments("oPropName")

'---Determine iProperty value---
Dim oPropValue As String

Try
	oPropValue = ThisDoc.Document.PropertySets.Item("Inventor User Defined Properties").Item(oPropName).Value
Catch
	oPropValue = "**DNE**"
End Try

'---Display iProperty value---
MessageBox.Show("CustomPropCheck - iProp Value: " & oPropValue)

'---Pass oPropValue value back to main rule---
RuleArguments.Arguments.Value("Return") = oPropValue 

 Let me know if you have any questions.


Thanks,
Randy Mabery
Applications Expert
IMAGINiT Technologies
Message 3 of 20
DRoam
in reply to: R.Mabery

Hi Randy, that's a really good suggestion. I thought it might work, but I tested it and it doesn't (unless I'm doing something wrong). I think it's because the RuleArguments collection for the "CustomPropCheck" rule is local to that rule, and likewise for the RuleArguments collection in the Main Rule. So we add the "Return" argument to CustomPropCheck's arguments with:

RuleArguments.Arguments.Value("Return") = oPropValue

But then when Main Rule takes back over, "Return" is not in its RuleArguments collection. So this line:

oPropValue = oRuleArguments.Item("Return")

...just returns an empty string.

 

Good suggestion, though.

 

After doing a bit more research, I'm fairly certain what I'm trying to do isn't possible (except by using Shared Variables). There doesn't seem to be any mechanism for passing a return value from a called iLogic rule to the calling rule (or, even for passing a return value from a called VBA function to the calling iLogic rule -- see here under the "Run Macro" section -- it says "You can call a VBA Function, but you cannot get a return value.").

 

Any other suggestions are welcome, though.

 

PS, one of the reasons I'm looking for something other than Shared Variables, is those can only store basic string, integer, Boolean, etc. variables, and I'd like for these Eternal iLogic rule "functions" to be able to return other Inventor objects as well.

 

PPS: well whaddya know, I was totally wrong about that. I had *assumed* that Shared Variables can only store those types of variables, but as it turns out they can store other object types, too, including Inventor objects like documents. So the code snippets below do exactly what I want:

 

Main Rule:

'---Set up arguments'---
Dim oRuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
oRuleArguments.Add("oPropName","Total QTY")

'---Call external "function" rule---
iLogicVb.RunExternalRule("CustomPropCheck",oRuleArguments)

'---Retrieve resultant value from "function" rule---
oPropValue = SharedVariable("oPropValue")
SharedVariable.Remove("oPropValue")

'---Display retrieved value---
MessageBox.Show("Main Rule - iProp Value: " & oPropValue)

 

"CustomPropCheck" external rule:

'---Get argument values---
Dim oPropName As String = RuleArguments("oPropName")

'---Determine iProperty value---
Dim oPropValue As String

Try
	oPropValue = ThisDoc.Document.PropertySets.Item("Inventor User Defined Properties").Item(oPropName).Value
Catch
	oPropValue = "**DNE**"
End Try

'---Display iProperty value---
MessageBox.Show("CustomPropCheck Rule - iProp Value: " & oPropValue)

'---Pass oPropValue value back to main rule---
SharedVariable("oPropValue") = oPropValue

This apparently will work for "returning" any object type back to the calling rule, including Inventor object types. Actually, I could even return multiple values back, as multiple Shared Variables, if required.

 

Unless someone replies back with a way to directly return a value from a called rule back to the calling rule, this will work for my purposes.

Message 4 of 20
philip1009
in reply to: DRoam

Shared Variables is my recommended route, basically they're variables that stay in the Inventor session memory until the session is closed or deleted by code.  The beauty is it also makes it easier to have multiple rules throughout your workflow to reference the same variables.  Whenever a relevant file is open I run a rule that automatically generates an appropriate set of Shared Variables so they can be referenced by whatever rule at any given time.

Message 5 of 20
R.Mabery
in reply to: DRoam

DRoam,

 

I'm curious to find out why it isn't working on your end....if you would indulge me with some questions.

 

What does the msgbox that's coming from the CustomPropCheck rule show?

 

What does the msgbox that's coming from the Main Rule show?

 

Thanks,


Thanks,
Randy Mabery
Applications Expert
IMAGINiT Technologies
Message 6 of 20
AlexFielder
in reply to: philip1009

If I can add my $0.02 to this thread:

 

I too recently figured out how to use RuleArguments to pass values from one rule to another in order to allow creation of "cascading multi-value lists" i.e. lists whose participants change based on the values in other "parent" lists.

 

Returning values from iLogic rules ought to be possible, but without testing it, the only way I can think of achieving this would be to leverage the IiLogicAutomation Interface described here: http://help.autodesk.com/view/INVNTOR/2019/ENU/?guid=__iLogic_API_html_8db501bb_0b0d_acaf_e151_dca66...

This would (I think) require the calling rule to actually create an iLogicRule object with which you should in theory be able to pass properties to/from.

 

After further reading, I don't think this is possible since the RunExternalRule method returns 0 if the resultant rule ran successfully. Attached is a file I created a week or so ago to demonstrate the cascading list principal to a colleague and here are the rules it uses:

 

(this first external rule populates a series of multivalue list objects in the parent assembly)

Option Explicit On
Imports System.Linq
''' This rule is designed to populate a series of supplied column parameters, creating them as required.
Sub Main()
	'Dim trans As Transaction = ThisApplication.TransactionManager.StartTransaction(ThisApplication.ActiveDocument, "Populate Multivalue Lists")
	Dim columns As String = "E,G,I,L,N,O,R" 'this could be automated by adding an "isKey" at the top of each column!?
	'Try
		Call SetMatchingParameterNames(columns, cDefaultMultivaluePrefix, cDefaultMultivalueSuffix)
		Call SetMatchingParameterNames(columns, cDefaultMultivaluePrefix)
		Call PopulateColumnDefaults(columns, cDefaultMultivaluePrefix, cDefaultMultivalueSuffix)
		Call PopulateColumnDefaults(columns, cDefaultMultivaluePrefix)
		'trans.End()
'	Catch ex As Exception
'		Logger.Error("The error was: " & ex.Message)
'		trans.Abort()
'	End Try
End Sub

Public Const cStartRow As Integer = 7
Public Const cEndRow As Integer = 50
Public Const cDefaultMultivaluePrefix As String = "column"
Public Const cDefaultMultivalueSuffix As String = "defaults"
Public ColumnAList As New List(Of Object)
Public ColumnBList As New List(Of Object)
Public ColumnCList As New List(Of Object)
Public ColumnDList As New List(Of Object)
Public ColumnEList As New List(Of Object)
Public ColumnGList As New List(Of Object)
Public ColumnIList As New List(Of Object)
Public ColumnLList As New List(Of Object)
Public ColumnNList As New List(Of Object)
Public ColumnOList As New List(Of Object)
Public ColumnRList As New List(Of Object)

Sub SetMatchingParameterNames(ByVal columnlist As String, ByVal columnPrefix As String, Optional columnSuffix As String = "")
	Dim Doc As AssemblyDocument = ThisApplication.ActiveDocument
	Dim columns As List(Of String) = columnlist.Split(",").ToList()
	For Each col As String In columns
		Dim thisParam As Inventor.Parameter = (From param As Inventor.Parameter In Doc.ComponentDefinition.Parameters
										Where param.Name = columnPrefix & col & columnSuffix
										Select param).FirstOrDefault()
		If thisParam Is Nothing Then
			Logger.Debug(columnPrefix & col & columnSuffix & " does not exist in " & Doc.FullFileName)
			Doc.ComponentDefinition.Parameters.UserParameters.AddByValue(columnPrefix & col & columnSuffix, "", UnitsTypeEnum.kTextUnits)
		Else
			Logger.Debug(thisParam.Name & " already exists")
		End If
	Next
End Sub

Sub PopulateColumnDefaults(ByVal columnlist As String, ByVal columnPrefix As String, Optional columnSuffix As String = "")
	Dim newFilesArray As New ArrayList
	newFilesArray = GoExcel.CellValues("path\to\spreadsheet.xlsx", "sheet1", "a1", "a2")
	Dim columns As List(Of String) = columnlist.Split(",").ToList()
	Logger.Debug(columns.ToString())
	Dim TempList As New List(Of Object)
	For Each col As String In columns
		Logger.Debug("columnname: "& col)
		For MyRow As Integer = cStartRow To cEndRow
			If Not CStr(GoExcel.CellValue(col & MyRow)) = "" Then
				If isParamText(columnPrefix & col & columnSuffix) And Not TypeOf GoExcel.CellValue(col & MyRow) Is String Then
					TempList.Add(GoExcel.CellValue(col & MyRow).ToString())
				Else
					TempList.Add(GoExcel.CellValue(col & MyRow))
				End If
			End If
		Next
		TempList.Sort()
		TempList = TempList.Distinct().ToList()
		Logger.Debug("Column" & col & "list.Count: " & TempList.Count)
		Dim tmpArrayList As ArrayList = New ArrayList(TempList)
		MultiValue.List(columnPrefix & col & columnSuffix) = tmpArrayList
		TempList.Clear()
	Next
'	break
End Sub

Function isParamText(ByVal paramName As String) As Boolean
	Logger.Debug("Parameter is: " & paramName)
	Dim p As Parameter = Parameter.Param(paramName)
	If p.Units = "Text" Or  p.units = "Boolean" Then
		Return True
	Else
		Return False	
	End If
End Function

Sub SetArrayListDefaults(col As String, tmplist As List(Of Object))
	Select col
		Case "E"
			ColumnEList.addrange(tmplist)
		Case "G"
			ColumnGList.addrange(tmplist)
		Case "I"
			ColumnIList.addrange(tmplist)
		Case "L"
			ColumnLList.addrange(tmplist)
		Case "N"
			ColumnNList.addrange(tmplist)
		Case "O"
			ColumnOList.addrange(tmplist)
		Case "R"
			ColumnRList.addrange(tmplist)
		Case Else
			'do nothing
	End Select
End Sub

 

Inside the assembly file itself we need a series of rules which reference the newly created multivalue parameters by name so taking column L as an example we have:

'columnL Rule
s = columnL 'Logger.Debug("columnL updated to: " & Parameter("columnL")) Dim RuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap() RuleArguments.Value("ParameterName") = "columnL" iLogicVb.RunExternalRule("UpdateMultivalueLists", RuleArguments)

This rule will fire every time the columnL parameter is updated. Which in turn activates this rule:

' UpdateMultiValueLists Rule
Option Explicit On Sub Main() If Not RuleArguments.Exists("ParameterName") Then 'not fired from relevant rule MessageBox.Show("This rule only works from the context-sensitive files we need!") Exit Sub Else Dim paramName As String = RuleArguments.Value("ParameterName") Dim p As Parameter = Parameter.Param(paramName) Logger.Debug(paramName & " updated value = " & p.Value) Dim FilterArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap() FilterArguments.Value("ParameterValue") = p.Value iLogicVb.RunExternalRule("Filter" & paramName, FilterArguments) End If End Sub

Which in turn fires the next rule in the sequence In this case "FilterColumnL":

'FilterColumnL Rule
Option Explicit On
Sub main()
	If Not RuleArguments.Exists("ParameterValue") Then
		MessageBox.Show("How did we get here?")
	Else
		'Column L
		Dim paramValue As String = RuleArguments.Value("ParameterValue")
		Dim FilterArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
		'this needs to be a list of values to remove/add from the next column along.
		Dim filterList As List(Of String) = New List(Of String)
		Select paramValue
			Case "L"
				filterList.Add("C")
				filterList.Add("K")
				filterList.Add("S")
			Case "R"
				filterList.Add("F")
				filterList.Add("K")
				filterList.Add("M")
				filterList.Add("S")
				filterList.Add("T")
			Case Else
		End Select
		FilterArguments.Value("UniqueValues") = filterList
		FilterArguments.Value("ColumnToFilter") = cNextColumn
		iLogicVb.RunExternalRule("FilterColumnRule", FilterArguments)
	End If
	
End Sub

Public Const cNextColumn As String = "N"

The final rule in the sequence takes us back to editing the multivalue list:

Option Explicit On
'FilterColumn Rule
Sub Main()
	If Not RuleArguments.Exists("UniqueValues") And Not RuleArguments.Exists("ColumnToFilter")Then
		MessageBox.Show("How did we get here?")
	Else
		Dim Doc As AssemblyDocument = ThisApplication.ActiveDocument
		Dim columnToEdit As Inventor.Parameter = (From param As Inventor.Parameter In Doc.ComponentDefinition.Parameters
										Where param.Name = "column" & RuleArguments.Value("ColumnToFilter")
										Select param).FirstOrDefault()
'		Dim columnToEdit As Inventor.Parameter = Parameter.Param("column" & RuleArguments.Value("ColumnToFilter"))
		Dim listofUniqueValues As List(Of String) = RuleArguments.Value("UniqueValues")
		Logger.Debug(columnToEdit.Name)
		Logger.Debug(debugListValues(listofUniqueValues))
		If Not listofUniqueValues Is Nothing And Not columnToEdit Is Nothing Then
			listofUniqueValues.Sort()
			Dim tmpArraylist As ArrayList = New ArrayList(listofUniqueValues)
			MultiValue.List(columnToEdit.Name) = tmpArraylist
		End If
	End If
End Sub

Function debugListValues(ByVal listofValues As List(Of String)) As String
	For Each Val As String In listofValues
		debugListValues = Val & "," & debugListValues
	Next
End Function

If you store the last two rules externally, and open the attached assembly file you'll see there's an iLogic form included in the assembly that will update the values of column 'N' when you change the selection in column L.

 

I'm not sure how much of this helps what you were trying to accomplish, but hopefully it will present some ideas not seen or considered before.

 

Cheers,

 

Alex.

Message 7 of 20
AlexFielder
in reply to: AlexFielder

Apparently the Forum is so broken (on Google Chrome 70.0.3538.77) it no longer allows attachments. So you can find the assembly file here:

https://1drv.ms/u/s!AiGmKryqFliPmKx3tz9elwa4krd4tw

 

 

Message 8 of 20
Curtis_Waguespack
in reply to: DRoam

Hi @DRoam

 

I think R.Mabery was on the right track, but maybe the iproperty did not exist in your test, so it returned blank?

 

These example rules are what I used  to test and it worked.

 

Note my external rule name was "Test Rule", since I keep an external rule named as such on disk for testing, I just reused it... change as needed.

 

I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com

 

 

'---Set up arguments'---
Dim oRuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
oRuleArguments.Add("oPropName","Total QTY")

'---Call external "function" rule---
iLogicVb.RunExternalRule("Test Rule",oRuleArguments)

'---Retrieve resultant value from "function" rule---
oPropValue = oRuleArguments.Item("T_QTY")

'---Display retrieved value---
MessageBox.Show("Total QTY: " & oPropValue)

Test Rule:

 

'---Get argument value---
Dim oPropName As String = RuleArguments("oPropName")

Try 'try to get current value to use in input box default	
	oPropValue = iProperties.Value(ThisDoc.Document ,"Custom", oPropName) 	
Catch 'catch error when iprop doesn't exit
End Try

'get user input
oInput = InputBox("Enter value for " & oPropName, "iLogic",oPropValue)
'sets or creates/sets iproperty
iProperties.Value(ThisDoc.Document,"Custom", oPropName)  = oInput
'create return value
RuleArguments.Arguments.Value("T_QTY") = oInput 

 

Message 9 of 20
DRoam
in reply to: Curtis_Waguespack

Ah, indeed you're right, Curits! Thanks for double-checking me on that. I'm really not sure why it didn't work before -- I was getting a value of "1" in the first messagebox but blank in the second, so I assumed the argument wasn't getting passed back properly. But I just tested again and it is indeed working.

 

So @R.Mabery your answer is exactly what I was looking for, thanks!

 

Maybe the two of you can enlighten me.... why does this work? Lol. I would have thought that "RuleArguments" are local object collections in each rule, and only get shared between rules if passed explicitly as a NameValueMap in a RunRule method...

 

So how does this work?

Message 10 of 20
Curtis_Waguespack
in reply to: DRoam


@DRoam wrote:

I would have thought that "RuleArguments" are local object collections in each rule, and only get shared between rules if passed explicitly as a NameValueMap in a RunRule method...

 

So how does this work?


Hi @DRoam

 

It works via the use of the APIs Transient Objects, which are objects that are considered temporary and only exist in memory.  

 

In other words, it works by first imagining a spoon , then once imagined you can bend that spoon... or in this case use the spoon to ladle soup from another rule. Smiley Wink

 

I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com

Message 11 of 20
DRoam
in reply to: Curtis_Waguespack

Hahaha ahh Curits, always on point with the spoon analogies... so basically what you're saying is instead of typing...

ThisApplication.TransientObjects.CreateNameValueMap()

 

...I could instead write:

ThisApplication.Spoons.CreateNameValueMap()

 

Correct?

 

I think I fully understand now, thanks 😉 

Message 12 of 20
Curtis_Waguespack
in reply to: DRoam

 

Dim Spoons As TransientObjects
Spoons = ThisApplication.TransientObjects

Dim oRuleArguments As Inventor.NameValueMap = Spoons.CreateNameValueMap()
oRuleArguments.Add("oPropName","Total QTY")

Smiley Wink

Message 13 of 20
Maxim-CADman77
in reply to: R.Mabery

I try to check how your solution works on a standard sample 3Dmodel (C:\Autodesk\autodesk_inventor_2019_samples_dlm\Models\Assemblies\Engine MKII\Components\Flywheel.ipt)

The rule i've run is 100% equal to Main Rule from your post marked as a solution.

The CustomPropCheck rule has only 1 line difference to yours (I've replaced a Custom iProp with Standard iProp*):

Dim oPropName As String = RuleArguments("oPropName")
Dim oPropValue As String
Try
	 oPropValue = iProperties.Value("Project", "Part Number")
Catch
	oPropValue = "**DNE**"
End Try
MessageBox.Show("CustomPropCheck - iProp Value: " & oPropValue)

I them get two consequent messages:

1st message with iProp value (as expected):

Msg1.png

But 2nd message is empty:

Msg2.png

 

The whole process seems so simple, thus I'm a bit puzzled regarding what was my mistake.

Any ideas?

 

* Neither it works with custom iProp (same result - 1st msg is OK; 2nd is empty).

PS: I've used Inventor 2019.2 

Message 14 of 20

Issue is also reproducible after installing Update 2019.3

Message 15 of 20
DRoam
in reply to: Maxim-CADman77

@Maxim-CADman77, it looks like you're missing this line at the end of your CustomPropCheck rule:

 

 

'---Pass oPropValue value back to main rule---
RuleArguments.Arguments.Value("Return") = oPropValue 

 

Message 16 of 20
Maxim-CADman77
in reply to: DRoam

Wow!

Seems like the workflow discussed here doesn't support using CustomPropCheck rule from the shared net folder.
Can you please re-check  this statement on your side?

Message 17 of 20
freesbee
in reply to: R.Mabery

...I apologize for the simplicity of my question, but I probably miss a point in this construct (I am definitely NOT a software developer, so there may be something obvious that I ignore).

 

I am trying to solve a very simply problem: I want to pass an argument to my external rule "CleanUP" from my rule "DoSomething". Somehow I fail to figure out how to populate the NameValueMap. My rule CleanUP is designed to do some stuff, and give a feedback once it is done. When I call this rule from another rule, I prefer NOT to have that feedback, as this will be already coming from calling rule.

 

Here my rule "DoSomething":

Sub Main
Dim RuleTitle As String = "Do Something"

Dim oRuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
Dim hideFeedback As Boolean = True
oRuleArguments.Add(hideFeedback)

iLogicVb.RunExternalRule("CleanUP",oRuleArguments)

'--here I actually do stuff and give feedback once I am done...
End Sub

and here my rule "CleanUP":

Sub Main
Dim RuleTitle As String = "Clean UP"

Dim showFeedback As Boolean = True
If RuleArguments.Exists("hideFeedback") Then
	ShowFeedback = False
End If

'--here I actually do stuff...

If ShowFeedback = True Then
  MsgBox("CleanUP is done"& vbCr &"You're good to go!!", vbOKOnly + vbInformation, RuleTitle)
End If
End Sub

Whatever I try to do my code always fails at the line oRuleArguments.add

This makes me think that probably I am missing something so simple that it is obvious for all of you but not for me.

 

Massimo Frison
CAD R&D // PDM Admin · Hekuma GmbH
Message 18 of 20
AlexFielder
in reply to: DRoam

Hi @freesbee,

 

On the oRulearguments.add line, you need to add both the namevaluemap object and the name it is associated with:

 

Dim oRuleArguments As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
Dim hideFeedback As Boolean = True
oRuleArguments.Add("hideFeedback", hideFeedback)

 

🙂

 

Message 19 of 20
freesbee
in reply to: AlexFielder

...thank you so much!

I would have never figured out on my own.

Now I have also understood entirely how it works...

Massimo Frison
CAD R&D // PDM Admin · Hekuma GmbH
Message 20 of 20
_KarlH
in reply to: DRoam

This is such a useful thread. Thanks for everyone's input and examples.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report