ZeroTouch Nodes - Default Inputs and flattening Output

Hey Jacob- I’ve moved over to Galloway now - trying to do some light development to export and reimport line weights for Revit. Wanted to make a node but am quickly heading towards an addin.

I have the base code and am trying to create a zero touch node to put out but I keep getting FUNCITON as output in Revit 2025 Dynamo. Tried numerous castings, etc. but no dice.

If I shared the project on GIT - would anyone have any suggestions on how to get the nodes to output a flat list? Or have zero touch been retired by Dynamo and Autodesk Revit?

Even peeling though the sites above - and looking for previous design script references for 25… I cannot find anything to cast it to an actual flat list.

and the codes/refs:

using Autodesk.DesignScript.Runtime;
using Autodesk.Revit.DB;
using RevitServices.Persistence;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace RonAllen_Lib.LineWeights
{
    public static class LineWeightNodes
    {
        /// <summary>
        /// Exports line weights as a list of strings (e.g., "1,1,0.1").
        /// </summary>
        /// <param name="doc">Revit document (optional; uses current document if null).</param>
        /// <returns>List of formatted strings: "Scale,Index,Value".</returns>
        [IsVisibleInDynamoLibrary(true)]
        public static List<string> ExportLineWeights(Document doc)
        {
            if (doc == null)
                doc = DocumentManager.Instance.CurrentDBDocument;

            var lwData = GetLineWeights(doc);
            var result = lwData.Select(lw => $"{lw.Scale},{lw.Index},{lw.Value}").ToList();

            return result;
        }

        /// <summary>
        /// Imports line weights from a flat list of strings (e.g., "1,1,0.1").
        /// </summary>
        /// <param name="doc">Revit document (optional; uses current document if null).</param>
        /// <param name="lineWeightData">List of strings to import.</param>
        [IsVisibleInDynamoLibrary(true)]
        public static void ImportLineWeights(Document doc, List<string> lineWeightData)
        {
            if (doc == null)
                doc = DocumentManager.Instance.CurrentDBDocument;

            if (lineWeightData == null || lineWeightData.Count == 0)
                throw new ArgumentException("Line weight data list is empty.");

            var settings = doc.Settings;
            var lwField = typeof(Settings).GetField("m_lineWeightsTable", BindingFlags.NonPublic | BindingFlags.Instance);
            var lwTable = lwField.GetValue(settings);
            var setMethod = lwTable.GetType().GetMethod("SetLineWeight", BindingFlags.NonPublic | BindingFlags.Instance);

            using (Transaction trans = new Transaction(doc, "Import Line Weights from List"))
            {
                trans.Start();

                foreach (var line in lineWeightData)
                {
                    if (line.StartsWith("ScaleIndex")) continue;

                    var parts = line.Split(',');
                    int scale = int.Parse(parts[0]);
                    int index = int.Parse(parts[1]);
                    int value = int.Parse(parts[2]);

                    setMethod.Invoke(lwTable, new object[] { index, scale, value });
                }

                trans.Commit();
            }
        }

        /// <summary>
        /// Helper method to extract line weights from document.
        /// </summary>
        /// <param name="doc">Revit document.</param>
        /// <returns>List of (Scale, Index, Value) tuples.</returns>
        private static List<(int Scale, int Index, object Value)> GetLineWeights(Document doc)
        {
            var settings = doc.Settings;
            var lwField = typeof(Settings).GetField("m_lineWeightsTable", BindingFlags.NonPublic | BindingFlags.Instance);
            var lwTable = lwField.GetValue(settings);
            var getMethod = lwTable.GetType().GetMethod("GetLineWeight", BindingFlags.NonPublic | BindingFlags.Instance);

            var result = new List<(int Scale, int Index, object Value)>();

            for (int scale = 1; scale <= 16; scale++)
            {
                for (int index = 1; index <= 16; index++)
                {
                    var lwValue = getMethod.Invoke(lwTable, new object[] { index, scale });
                    result.Add((scale, index, lwValue));
                }
            }

            return result;
        }
    }
}

No issues I see with the output. I do see an issue with the input.

You haven’t defined a default input for doc, and as such it won’t run as it’s missing the input - you can try enabling the default in the Dynamo UI and you’ll likely see it with behave one. Wire a Document.Current in and that can also confirm.

Once confirmed, check the Developer section of the Dynamo Primer for info on defaults: Developer Primer | Dynamo

After that you may want to also look into how the Revit team integrates defaults via design script notation in some of their nodes in the github: GitHub - DynamoDS/DynamoRevit: Dynamo Libraries for Revit

1 Like

I don’t have much else to add other than, what the heck is this statement?

ZeroTouch is a process that allows for the import of public static methods. It isn’t “retired” and that comment just feels like a way to try to stir something up.

Also, just reference the DynamoCore libraries and you will have access to List.Flatten.

*Edit, I also split your topic as you revived an old (solved) topic.

2 Likes

IF doc isn’t defined it uses the current doc.

Spent last night on to modnight30 getting output from the node that keeps reading as “function”, so quite frustrated at this point. I did clone your GIT and take a look at the adds for the Nugets which I have only added and not dug into at this point.


.nuget\packages\dynamovisualprogramming.wpfuilibrary\3.0.4.7905
.nuget\packages\dynamovisualprogramming.dynamocorenodes\3.0.4.7905
.nuget\packages\dynamovisualprogramming.zerotouchlibrary\3.0.4.7905
.nuget\packages\dynamovisualprogramming.dynamoservices\3.0.4.7905\

I suspect the “zerotouchlibrary” is the key to getting output from the nodes.

Question where are we looking for these nodes? From about a dozen downloads and digging last night I didn’t find any of those aforementioned dll references in Dynamo Unchained 1: Learn how to develop Zero Touch Nodes in C# or dynamo, or the forums, or a dozen or more other sites dug through last night.

Thinking about putting together a GIT or a document for simple minded coders like myself that just need a few funcitons for R25/26 so we can Pull in the DLLs we use.

Yes and no. The code is structured to fetch the current document if it is undefined at the time of execution. However Dynamo isn’t executing the code as there is a missing input… it’s a function until you call it.

While I appreciate the effort and though around ‘defaulting’ the document of none given, you are adding complexity to the code which (1) need not be there as Document.Current is pretty much an instant call and (2) the functional use hasn’t been validated before you work out the specifics of the UX by solving the ‘I don’t want the graph author to have to place one extra node’. Saving that bit of work is a bonus, but it shouldn’t be the initial step.

For now, try the Document.Current test to confirm it works, then move into adding the default values for the input. If you do I’m confident that you’ll see that you don’t need to do any of the hoop jumping which you have started on.

As far as beginning a new git for developers… if you think the community will benefit, then feel free. But know you’ll need to update it about 6x a year, sometimes only taking 15 minutes if you have good automation capability in this space, other times taking a few days or a week, and even taking a few months (not a joke) I’d you don’t have experience or automation capability in this space yet. That time will decrease as your skill level increases, much like a trip to Mordor, one does not simply push a collection of references to NuGet and walk away. Personally I think the existing NuGet packages are beyond sufficient, with further fragmentation adding more to the problems rather than solving the issue.

You can default it with a GetNull() method to be null.

But I would encourage you to just leave it as a node that needs an input and fulfill it when you use. But then again, I have no idea what you are really trying to do.

1 Like

Agreed: ) removing it. Was concerned with Docs having different line weights. I Tried probably close to 50 different permutations last night - that was the last I tried.

As for a GIT - updated how tos would be welcome. I would hope more savvy teams could contribute towards base configs and more advanced configs like Rhythm as part of the education : ) There just was no effective way to access the lineweights VI Python that I found so I shifted. Currently well beyond my noob scope in this hybrid environment of Revit/C#/Dynamo nodes. I’d have better luck with direct addins at this point to remove that layer of complexity- but I want my end users (& others) to have access in Dynamo.

Is Autodesk managing the NuGet packages or are they deferring everything through the community open source?

Thanks John! - I’ll take a look tonight after I get those NuGets fully integrated and my includes re-jiggered : )

1 Like

Yes - the Dynamo team manages them, which makes ‘building your own’ a difficult thing.

The developer primer linked above is a good ‘how to’, but typically the detailed walkthroughs come from the user base (not just in Dynamo - the best ‘how to build families’ or ‘how to manage site coordinates’ in Revit come from users, not the development team or marketing team).