ZT nodes & [NodeCategory()]

zerotouch
dynamo

#1

Hi All,

I’m trying to set the [NodeCategory()] as per the following post

If I have just one method and I use [NodeCategory("Query")], the node is shows in the “Create” subcategory

image

If I add another method and I use [NodeCategory("Action")], now the first method is shown correctly but not the second :thinking:

image

My packages

Ideas?


#2

cc: @Michael_Kirschner2


#3

can you post some sample code?


#4

@Michael_Kirschner2

I have a solution with 2 projects.

1st project class:

using Dynamo.Graph.Nodes;
using System.Collections.Generic;

namespace Test
{

	public static class RevitElem
	{

		[NodeCategory("Query")]
		public static List<string> elementNo (string paramName, List<Revit.Elements.Element> element)
		{
			return Test_NV.RevitNV.elementNoNV(paramName, element);			
		}
		

		[NodeCategory("Action")]
		public static string concatenate (string name)
		{

			return "Hello " + name;
		}
			   		 	  
	}
} 

2nd project class:

using Autodesk.DesignScript.Runtime;
using System.Collections.Generic;


namespace Test_NV
{

	[IsVisibleInDynamoLibrary(false)]
	public class RevitNV
	{
		public static List<string> elementNoNV(string paramName, List<Revit.Elements.Element> data)
		{
			var paramValues = new List<string>();

			foreach (var item in data)
			{
				Autodesk.Revit.DB.Element UnwrappedElement;
				UnwrappedElement = item.InternalElement;
				paramValues.Add(UnwrappedElement.LookupParameter(paramName).AsString());
			}

			return paramValues;
		}


	}
}

#5

are you testing these nodes in dynamo 1.3 or 2.0?


#6

@Michael_Kirschner2 1.3


#7

@salvatoredragotta @Michael_Kirschner2 the example posted above was done in 2.0+ with the new library, the behavior in 1.3 may have been a bit different and requires some investigation


#8

@alfarok is it possible to use the the new library and use the nodes in dynamo 1.3.3?


#9

@salvatoredragotta It may be possibly with some hacks as the library is really just a view extension but I wouldn’t recommend it. The library in Dynamo 2.0 was built specifically around other major 2.0 changes. Based on the date in the pull request linked above I would assume the NodeCategory attribute should work the same but based on your finding it’s possible it has regressed at some point around 1.3. We will have to take a closer look at the examples your provided.


#10

If I remember correctly, those attributes are only read and applied for NodeModel classes / assemblies, while for ZT loaded assemblies only the xml documentation and the …_customization files are ever used.


#11

@Dimitar_Venkov That’s a good point and seems to match what @Thomas_Mahon was saying in the other thread. It is possible in pre 2.0 builds these attributes only worked on NodeModel derived nodes but now both are supported in 2.0+


#12

@alfarok

I’ve created a custom node using the code below (which implements the NodeModel interface)

I use the node category [NodeCategory("ExplicitNodes.Test.Query")]

But it’s still not shown correctly.

image

image

The Orchid Package for Dyanamo 1.3.3 seems to arrange the nodes correctly.
I wonder how it’s done :thinking:

image


#13

Why not @erfajo and see if he’ll lend any suggestions?


#14

Not following the thread (it’s outside my wheelhouse by a bit), but… have we checked the Orchid GitHub to see how that was done?


#15

I don’t think he posts his raw code, just the compiled dll unless I have missed something looking there in the past.


#16

That’s correct but there’s another repository with a few examples. I had a look but I can’t figure it out.


#17

Thanks @Sean1 and @JacobSmall for reference this issue to me.

@salvatoredragotta, my package is freeware published under the CC BY-ND license. Meaning not opensource.

I have an example which shows how to do it in the DynamoSample (MIT license), in here you can see how I do it… and some smaller samples of some of the nodes I have in the package.

I have organized my project a bit different than what is shown by the Dynamo team. I do as I do since I want my package to be able to run in both D4R and Sandbox version AND at the same time be able to call as commands using DesignScript (or Python) in one common way. I don’t have the same options as the dynamo team has since you need to accept their way of loading assemblies.

So for a first time coder of dynamo packages, it might seem a bit too much… but in the long run it makes sense :slight_smile:

let me explain…the DynamoSample project
ZeroTouch -> holds all the computaional code (not for dropdown), everything inside here can be called in codeblocks or python scripts. It has no icons or visual elements. This one is NOT loaded by the pkg.json file!

ZeroTouchGeneric -> nodes to be runned only in Sandbox version, this is here icons and what users can see is placed. It has no “computational” code. This one is loaded by the pkg.json file!
ZeroTouchRevit -> nodes to be runned in D4R and Sandbox version (require Revit.dll), this is here icons and what users can see is placed. It has no “computational” code. This one is loaded by the pkg.json file!

ZeroTouchGenericUI -> dropdown nodes used only in Sandbox version, includes the “computational” code, cannot be called in code blocks or python scripts. This one is loaded by the pkg.json file!
ZeroTouchRevitUI -> dropdown nodes used in D4R and Sandbox version, includes the “computational” code, cannot be called in code blocks or python scripts. This one is loaded by the pkg.json file!


Zero Touch Customization.xml Nesting
#18

remember it is [NodeCategory("Actions")] you miss an “s” :slight_smile:


#19

Looking briefly into the behavior in 1.3 vs 2.0 I’ve noticed a couple things. It appears that these attributes work as expected in 1.3 as long as there is a public constructor for the class. Take a look at these examples…

  • Example 1 shows the default behavior in 1.3 with 2 (method/Action) nodes. By default an empty constructor is added even though it is absent from our implementation (no NodeCategory attributes applied)

  • Example 2 shows an empty constructor added to the implementation that was made private and the [NodeCategory("Query")] attribute is used on the AddSample node. This appears to cause one of our nodes (SubSample) to be tagged as Create node category even though it should be Action. This leads me to believe the library is expecting at least 1 Create node to be present. A work around would be to add a public constructor and hide it from the library using the [IsVisibleInDynamoLibrary(false)] attribute. Unfortunately it appears this attribute does not work on constructors from what I am seeing (but does work on methods or properties)

  • Example 3 adds a public constructor and applies the [NodeCategory("Query")] attribute on the AddSample node which appears to work as expected (but requires the a public constructor which now shows in the library)

  • Example 4 shows Dynamo 2.0+ where the default behavior is the same as 1.3 (no NodeCategory attributes applied)

  • Example 5 shows Dynamo 2.0+ with a private constructor which is automatically hidden from the library and achieves the desired behavior

TLDR: More investigation is required as to why constructors cannot be private or marked invisible without causing other nodes to be re-categorized unexpectedly in Dynamo 1.3.X. However, the desired behavior is achievable without workarounds using the latest Dynamo 2.X.

Hope this helps and please feel free to correct any oversight in the examples above.


#20

Thanks @erfajo but it doesn’t work with the correct spelling neither.

As @alfarok pointed out the library is expecting at least 1 Create node.