public override Value Evaluate(FSharpList <Value> args) { //Solid argument bool isSolid = ((Value.Number)args[0]).Item == 1; //Surface argument bool isSurface = ((Value.Number)args[2]).Item == 1; //Build up our list of list of references for the form by... var curvesListList = (Value.List)args[1]; //Now we add all of those references into ReferenceArrays ReferenceArrayArray refArrArr = new ReferenceArrayArray(); FSharpList <Value> vals = ((Value.List)curvesListList).Item; if (vals.Any() && (vals[0] is Value.Container) && ((Value.Container)vals[0]).Item is ModelCurveArray) { //Build a sequence that unwraps the input list from it's Value form. IEnumerable <ModelCurveArray> modelCurveArrays = ((Value.List)args[1]).Item.Select( x => (ModelCurveArray)((Value.Container)x).Item ); foreach (var modelCurveArray in modelCurveArrays) { var refArr = new ReferenceArray(); foreach (ModelCurve modelCurve in modelCurveArray) { refArr.Append(modelCurve.GeometryCurve.Reference); } refArrArr.Append(refArr); } } else { IEnumerable <IEnumerable <Reference> > refArrays = (curvesListList).Item.Select( //...first selecting everything in the topmost list... delegate(Value x) { //If the element in the topmost list is a sub-list... if (x.IsList) { //...then we return a new IEnumerable of References by converting the sub list. return((x as Value.List).Item.Select( delegate(Value y) { //Since we're in a sub-list, we can assume it's a container. var item = ((Value.Container)y).Item; if (item is CurveElement) { return (item as CurveElement).GeometryCurve.Reference; } else { return (Reference)item; } } )); } //If the element is not a sub-list, then just assume it's a container. else { var obj = ((Value.Container)x).Item; Reference r; if (obj is CurveElement) { r = (obj as CurveElement).GeometryCurve.Reference; } else { r = (Reference)obj; } //We return a list here since it's expecting an IEnumerable<Reference>. In reality, //just passing the element by itself instead of a sub-list is a shortcut for having //a list with one element, so this is just performing that for the user. return(new List <Reference>() { r }); } } ); //Now we add all of those references into ReferenceArrays foreach (IEnumerable <Reference> refs in refArrays.Where(x => x.Any())) { var refArr = new ReferenceArray(); foreach (Reference r in refs) { refArr.Append(r); } refArrArr.Append(refArr); } } //If we already have a form stored... if (this.Elements.Any()) { //is this same element? Element e = null; if (dynUtils.TryGetElement(this.Elements[0], typeof(Form), out e) && e != null && e is Form) { Form oldF = (Form)e; if (oldF.IsSolid == isSolid && preferSurfaceForOneLoop == isSurface && matchOrAddFormCurveToReferenceCurveMap(oldF, refArrArr, true)) { return(Value.NewContainer(oldF)); } } //Dissolve it, we will re-make it later. if (FormUtils.CanBeDissolved(this.UIDocument.Document, this.Elements.Take(1).ToList())) { FormUtils.DissolveForms(this.UIDocument.Document, this.Elements.Take(1).ToList()); } //And register the form for deletion. Since we've already deleted it here manually, we can //pass "true" as the second argument. this.DeleteElement(this.Elements[0], true); } else if (this.formId != ElementId.InvalidElementId) { Element e = null; if (dynUtils.TryGetElement(this.formId, typeof(Form), out e) && e != null && e is Form) { Form oldF = (Form)e; if (oldF.IsSolid == isSolid && preferSurfaceForOneLoop == isSurface && matchOrAddFormCurveToReferenceCurveMap(oldF, refArrArr, true)) { return(Value.NewContainer(oldF)); } } } preferSurfaceForOneLoop = isSurface; //We use the ReferenceArrayArray to make the form, and we store it for later runs. Form f; //if we only have a single refArr, we can make a capping surface or an extrusion if (refArrArr.Size == 1) { ReferenceArray refArr = refArrArr.get_Item(0); if (isSurface) // make a capping surface { f = this.UIDocument.Document.FamilyCreate.NewFormByCap(true, refArr); } else // make an extruded surface { // The extrusion form direction XYZ direction = new XYZ(0, 0, 50); f = this.UIDocument.Document.FamilyCreate.NewExtrusionForm(true, refArr, direction); } } else // make a lofted surface { f = this.UIDocument.Document.FamilyCreate.NewLoftForm(isSolid, refArrArr); } matchOrAddFormCurveToReferenceCurveMap(f, refArrArr, false); this.Elements.Add(f.Id); return(Value.NewContainer(f)); }