Friday, January 17, 2014

Set Element Parameters in Dynamo Revit

I have been working diligently with my co-worker Michael Coffey (Revit API Guru) to try and develop some great tools that are missing inside of Dynamo.
We recently were able to modify the "Set Family Instance Parameters" node, which is currently limited to only family instances to allow you to set any element parameter weather its a loaded family or a system family! 

















We have found it particularly useful when trying to edit multiple sheet parameters at once in the entire file. Next step in the process will be to work out setting up custom filters to gather lists of specific elements in a project file.

In order to deploy it, copy the following files into....


....the below location....


Here is the source code:


using System;

using System.Collections.Generic;

using System.Globalization;

using System.Linq;

using System.Xml;

using Autodesk.Revit.DB;

using Dynamo.FSchemeInterop;

using Dynamo.Models;

using Dynamo.Utilities;


using Microsoft.FSharp.Collections;

using Value = Dynamo.FScheme.Value;
using Dynamo.Revit;

namespace Dynamo.Nodes
{
    /// <summary>
    ///     Create a custom node.
    /// </summary>
    [NodeName("Set Element Parameters")]
    [NodeCategory(BuiltinNodeCategories.REVIT_DOCUMENT)]
    [NodeDescription("Set Element Parameters from a given Input")]
    public class SetElementParameters : RevitTransactionNodeWithOneOutput
    {
        public SetElementParameters()
        {
          InPortData.Add(new PortData("elements", "The element from which to get parameters", typeof (Value.Container)));
            InPortData.Add(new PortData("param", "Parameter to modify (string).", typeof (Value.String)));
            InPortData.Add(new PortData("value", "Value to set the parameter to.", typeof (object)));
            OutPortData.Add(new PortData("elements", "Modified Elements.", typeof (Value.Container)));
            
            RegisterAllPorts();

//            ArgumentLacing = LacingStrategy.Longest;
        }
private static Value setParam(Element elem, string paramName, Value valueExpr)
        {
            var p = elem.get_Parameter(paramName);
            if (p != null)
            {
                return _setParam(elem, p, valueExpr);
            }
            throw new Exception("Parameter \"" + paramName + "\" was not found!");
        }

        private static Value setParam(Element elem, Definition paramDef, Value valueExpr)
        {
            var p = elem.get_Parameter(paramDef);
            if (p != null)
            {
                return _setParam(elem, p, valueExpr);
            }
            throw new Exception("Parameter \"" + paramDef.Name + "\" was not found!");
        }

        private static Value _setParam(Element elem, Parameter p, Value valueExpr)
        {
            if (p.StorageType == StorageType.Double)
            {
                p.Set(((Value.Number) valueExpr).Item);
            }
            else if (p.StorageType == StorageType.Integer)
            {
                p.Set((int) ((Value.Number) valueExpr).Item);
            }
            else if (p.StorageType == StorageType.String)
            {
                p.Set(((Value.String) valueExpr).Item);
            }
            else if (p.StorageType == StorageType.ElementId)
            {
                p.Set((ElementId) ((Value.Container) valueExpr).Item);
            }
            else if (valueExpr.IsNumber)
            {
                p.Set(new ElementId((int) (valueExpr as Value.Number).Item));
            }
            else
            {
                p.Set((ElementId) ((Value.Container) valueExpr).Item);
            }
            return Value.NewContainer(elem);
        }

        public override Value Evaluate(FSharpList<Value> args)
        {
            var valueExpr = args[2];

            var param = args[1];
            if (param.IsString)
            {
                var paramName = ((Value.String) param).Item;

                var input = args[0];
                if (input.IsList)
                {
                    var elemList = (input as Value.List).Item;
                    return Value.NewList(
                        Utils.SequenceToFSharpList(
                            elemList.Select(
                                x =>
                                setParam(
                                    (Element) ((Value.Container) x).Item,
                                    paramName,
                                    valueExpr))));
                }
                else
                {
                    var fs = (Element) ((Value.Container) input).Item;

                    return setParam(fs, paramName, valueExpr);
                }
            }
            else
            {
                var paramDef = (Definition) ((Value.Container) param).Item;

                var input = args[0];
                if (input.IsList)
                {
                    var eList = (input as Value.List).Item;
                    return Value.NewList(
                        Utils.SequenceToFSharpList(
                            eList.Select(
                                x =>
                                setParam(
                                    (Element) ((Value.Container) x).Item,
                                    paramDef,
                                    valueExpr))));
                }
                else
                {
                    var fs = (Element) ((Value.Container) input).Item;

                    return setParam(fs, paramDef, valueExpr);
                }
            }
        }
    }
}