Skip to content

Commit 260bf7f

Browse files
Merge pull request #1447 from mcneel/kike/1.36-merge-1.x
Merge branch 'kike/1.36' into 1.x
2 parents 350a1b1 + 6aae7af commit 260bf7f

File tree

13 files changed

+1618
-1370
lines changed

13 files changed

+1618
-1370
lines changed

src/RhinoInside.Revit.External/Extensions/RhinoCommon.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using Microsoft.Win32.SafeHandles;
5+
using Rhino.Render;
56
using RhinoInside.Revit.External.DB.Extensions;
67
using RhinoInside.Revit.Numerical;
78

@@ -1368,6 +1369,14 @@ public static Geometry.Rectangle3d GetFrustumRectangle(this ViewportInfo vport,
13681369

13691370
namespace Rhino.DocObjects.Tables
13701371
{
1372+
static class MaterialTableExtension
1373+
{
1374+
public static Material FindName(this MaterialTable table, string name)
1375+
{
1376+
return table.FirstOrDefault(x => !x.IsReference && !x.IsDeleted && string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase));
1377+
}
1378+
}
1379+
13711380
static class NamedConstructionPlaneTableExtension
13721381
{
13731382
public static int Add(this NamedConstructionPlaneTable table, ConstructionPlane cplane)
@@ -1533,6 +1542,11 @@ namespace Rhino.Render
15331542
{
15341543
static class RenderMaterialExtension
15351544
{
1545+
public static RenderMaterial FindName(this RenderMaterialTable table, string name)
1546+
{
1547+
return table.FirstOrDefault(x => !x.IsReference() && string.Equals(x.Name, name, StringComparison.InvariantCultureIgnoreCase));
1548+
}
1549+
15361550
#if !RHINO_8
15371551
public static RenderMaterial Find(this RenderMaterialTable table, Guid id)
15381552
{

src/RhinoInside.Revit.GH/Components/Element/Material/ByName.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ protected override void TrySolveInstance(IGH_DataAccess DA)
266266
if (newColor.Red != material.Color.Red || newColor.Green != material.Color.Green || newColor.Blue != material.Color.Blue)
267267
material.Color = newColor;
268268

269-
var newTransparency = (int) Math.Round((255 - color.A) * 100.0 / 255.0);
269+
var newTransparency = (int) Math.Round((byte.MaxValue - color.A) / 2.55);
270270
if (material.Transparency != newTransparency)
271271
material.Transparency = newTransparency;
272272

src/RhinoInside.Revit.GH/Types/Datums/ProjectLocation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ protected override void DrawViewportWires(GH_PreviewWireArgs args)
7474
bool IGH_BakeAwareData.BakeGeometry(RhinoDoc doc, ObjectAttributes att, out Guid guid) =>
7575
BakeElement(new Dictionary<ARDB.ElementId, Guid>(), true, doc, att, out guid);
7676

77-
public bool BakeElement
77+
public override bool BakeElement
7878
(
7979
IDictionary<ARDB.ElementId, Guid> idMap,
8080
bool overwrite,
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Grasshopper.Kernel;
5+
using Grasshopper.Kernel.Types;
6+
using Rhino;
7+
using Rhino.DocObjects;
8+
using Rhino.Geometry;
9+
using Rhino.Render;
10+
using ARDB = Autodesk.Revit.DB;
11+
12+
namespace RhinoInside.Revit.GH.Types
13+
{
14+
using Convert.DocObjects;
15+
using Convert.Geometry;
16+
using External.DB.Extensions;
17+
18+
partial class GeometricElement
19+
{
20+
#region IGH_BakeAwareElement
21+
bool IGH_BakeAwareData.BakeGeometry(RhinoDoc doc, ObjectAttributes att, out Guid guid) =>
22+
BakeElement(new Dictionary<ARDB.ElementId, Guid>(), true, doc, att, out guid);
23+
24+
static System.Drawing.Color EnsureNoBlack(System.Drawing.Color value)
25+
{
26+
return (value.R == 0 && value.G == 0 && value.B == 0) ? System.Drawing.Color.FromArgb(value.A, 1, 1, 1) : value;
27+
}
28+
29+
static ObjectAttributes CreateObjectAttributes(IDictionary<ARDB.ElementId, Guid> idMap, RhinoDoc doc, ARDB.Document document)
30+
{
31+
var context = GeometryDecoder.Context.Peek;
32+
var attributes = new ObjectAttributes();
33+
34+
if (context.Category is ARDB.Category category)
35+
{
36+
if (new Category(category).BakeElement(idMap, false, doc, default, out var layerGuid))
37+
attributes.LayerIndex = doc.Layers.FindId(layerGuid).Index;
38+
}
39+
40+
if (context.Material is ARDB.Material material)
41+
{
42+
if (new Material(material).BakeElement(idMap, false, doc, default, out var materialGuid))
43+
attributes.RenderMaterial = doc.RenderMaterials.Find(materialGuid);
44+
}
45+
46+
return attributes;
47+
}
48+
49+
public virtual bool BakeElement
50+
(
51+
IDictionary<ARDB.ElementId, Guid> idMap,
52+
bool overwrite,
53+
RhinoDoc doc,
54+
ObjectAttributes att,
55+
out Guid guid
56+
)
57+
{
58+
// 1. Check if is already cloned
59+
guid = Guid.Empty;
60+
61+
// 3. Update if necessary
62+
if (Value is ARDB.Element element)
63+
{
64+
using (var options = new ARDB.Options() { DetailLevel = ARDB.ViewDetailLevel.Fine })
65+
{
66+
using (var geometry = element.GetGeometry(options))
67+
{
68+
if (geometry is object)
69+
{
70+
using (var context = GeometryDecoder.Context.Push())
71+
{
72+
context.Element = element;
73+
context.Category = element.Category;
74+
context.Material = element.Category?.Material;
75+
76+
var location = element.Category is null || element.Category.Parent is object ?
77+
Plane.WorldXY :
78+
Location;
79+
80+
var worldToElement = Transform.PlaneToPlane(location, Plane.WorldXY);
81+
if (BakeGeometryElement(idMap, overwrite, doc, worldToElement, element, geometry, out var idefIndex))
82+
{
83+
att = att?.Duplicate() ?? doc.CreateDefaultAttributes();
84+
att.Space = ActiveSpace.ModelSpace;
85+
att.ViewportId = Guid.Empty;
86+
att.Name = element.get_Parameter(ARDB.BuiltInParameter.ALL_MODEL_MARK)?.AsString() ?? string.Empty;
87+
att.Url = element.get_Parameter(ARDB.BuiltInParameter.ALL_MODEL_URL)?.AsString() ?? string.Empty;
88+
89+
if (Category.BakeElement(idMap, false, doc, att, out var layerGuid))
90+
att.LayerIndex = doc.Layers.FindId(layerGuid).Index;
91+
92+
guid = doc.Objects.AddInstanceObject(idefIndex, Transform.PlaneToPlane(Plane.WorldXY, location), att);
93+
94+
// We don't want geometry on the active viewport but on its own.
95+
doc.Objects.ModifyAttributes(guid, att, quiet: true);
96+
}
97+
}
98+
99+
if (guid != Guid.Empty)
100+
return true;
101+
}
102+
}
103+
}
104+
}
105+
106+
return false;
107+
}
108+
109+
protected internal static bool BakeGeometryElement
110+
(
111+
IDictionary<ARDB.ElementId, Guid> idMap,
112+
bool overwrite,
113+
RhinoDoc doc,
114+
Transform transform,
115+
ARDB.Element element,
116+
ARDB.GeometryElement geometryElement,
117+
out int index
118+
)
119+
{
120+
// 1. Check if is already cloned
121+
if (idMap.TryGetValue(element.Id, out var guid))
122+
{
123+
index = doc.InstanceDefinitions.FindId(guid).Index;
124+
return true;
125+
}
126+
127+
var geometryElementContent = geometryElement.ToArray();
128+
if (geometryElementContent.Length < 1)
129+
{
130+
index = -1;
131+
return false;
132+
}
133+
else if
134+
(
135+
geometryElementContent.Length == 1 &&
136+
geometryElementContent[0] is ARDB.GeometryInstance geometryInstance &&
137+
geometryInstance.GetSymbol() is ARDB.ElementType symbol
138+
)
139+
{
140+
// Special case to simplify ARDB.FamilyInstance elements.
141+
var instanceTransform = geometryInstance.Transform.ToTransform();
142+
return BakeGeometryElement(idMap, false, doc, instanceTransform * transform, symbol, geometryInstance.SymbolGeometry, out index);
143+
}
144+
145+
// Get a Unique Instance Definition name.
146+
var idef_name = NameConverter.EscapeName(element, out var idef_description);
147+
148+
// 2. Check if already exist
149+
index = doc.InstanceDefinitions.Find(idef_name)?.Index ?? -1;
150+
151+
// 3. Update if necessary
152+
if (index < 0 || overwrite)
153+
{
154+
bool identity = transform.IsIdentity;
155+
156+
GeometryDecoder.UpdateGraphicAttributes(geometryElement);
157+
158+
var geometry = new List<GeometryBase>(geometryElementContent.Length);
159+
var attributes = new List<ObjectAttributes>(geometryElementContent.Length);
160+
161+
foreach (var g in geometryElementContent)
162+
{
163+
using (GeometryDecoder.Context.Push())
164+
{
165+
GeometryDecoder.UpdateGraphicAttributes(g);
166+
167+
var objectGeometry = default(GeometryBase);
168+
switch (g)
169+
{
170+
case ARDB.Mesh m: if (m.NumTriangles > 0) objectGeometry = m.ToMesh(); break;
171+
case ARDB.Solid s: if (!s.Faces.IsEmpty) objectGeometry = s.ToBrep(); break;
172+
case ARDB.Curve c: objectGeometry = c.ToCurve(); break;
173+
case ARDB.PolyLine p: if (p.NumberOfCoordinates > 0) objectGeometry = p.ToPolylineCurve(); break;
174+
case ARDB.GeometryInstance i:
175+
using (GeometryDecoder.Context.Push())
176+
{
177+
if (BakeGeometryElement(idMap, false, doc, Transform.Identity, i.GetSymbol(), i.SymbolGeometry, out var idefIndex))
178+
objectGeometry = new InstanceReferenceGeometry(doc.InstanceDefinitions[idefIndex].Id, i.Transform.ToTransform());
179+
}
180+
break;
181+
}
182+
183+
if (objectGeometry is null) continue;
184+
if (!identity) objectGeometry.Transform(transform);
185+
186+
var objectAttributes = CreateObjectAttributes(idMap, doc, element.Document);
187+
188+
if (objectGeometry is Mesh mesh)
189+
{
190+
var context = GeometryDecoder.Context.Peek;
191+
if (context.FaceMaterialId?.Length == 1 && context.FaceMaterialId[0].IsValid())
192+
{
193+
var faceMaterial = new Material(element.Document, context.FaceMaterialId[0]);
194+
if (faceMaterial.BakeElement(idMap, false, doc, null, out var materialId))
195+
{
196+
objectAttributes.RenderMaterial = doc.RenderMaterials.Find(materialId);
197+
objectAttributes.ColorSource = ObjectColorSource.ColorFromObject;
198+
objectAttributes.ObjectColor = faceMaterial.ObjectColor;
199+
}
200+
}
201+
}
202+
else if (objectGeometry is Brep brep)
203+
{
204+
// In case objectGeometry is a Brep and has different materials per face.
205+
var context = GeometryDecoder.Context.Peek;
206+
if (context.FaceMaterialId?.Length > 0)
207+
{
208+
bool hasPerFaceMaterials = false;
209+
{
210+
for (int f = 1; f < context.FaceMaterialId.Length && !hasPerFaceMaterials; ++f)
211+
hasPerFaceMaterials |= context.FaceMaterialId[f] != context.FaceMaterialId[f - 1];
212+
}
213+
214+
if (hasPerFaceMaterials)
215+
{
216+
var layer = doc.Layers[objectAttributes.LayerIndex];
217+
218+
if (objectAttributes.MaterialIndex < 0) objectAttributes.MaterialIndex = doc.Materials.Add();
219+
var objectMaterial = doc.Materials[objectAttributes.MaterialIndex];
220+
if (layer.RenderMaterial is RenderMaterial layerMaterial)
221+
{
222+
layerMaterial.SimulateMaterial(ref objectMaterial, RenderTexture.TextureGeneration.Allow);
223+
objectMaterial.RenderMaterialInstanceId = layerMaterial.Id;
224+
}
225+
else objectMaterial.RenderMaterialInstanceId = default;
226+
objectMaterial.ClearMaterialChannels();
227+
228+
foreach (var face in brep.Faces)
229+
{
230+
var faceMaterialId = context.FaceMaterialId[face.SurfaceIndex];
231+
if (faceMaterialId != (context.Material?.Id ?? ARDB.ElementId.InvalidElementId))
232+
{
233+
var faceMaterial = new Material(element.Document, faceMaterialId);
234+
if (faceMaterial.BakeSharedMaterial(idMap, false, doc, out var materialGuid))
235+
{
236+
face.MaterialChannelIndex = objectMaterial.MaterialChannelIndexFromId(materialGuid, true);
237+
}
238+
}
239+
else
240+
{
241+
var materialIndex = layer.RenderMaterialIndex;
242+
if (doc.Materials[materialIndex] is Rhino.DocObjects.Material material)
243+
{
244+
face.MaterialChannelIndex = objectMaterial.MaterialChannelIndexFromId(material.Id, true);
245+
face.PerFaceColor = EnsureNoBlack(material.DiffuseColor);
246+
}
247+
else
248+
{
249+
face.ClearMaterialChannelIndex();
250+
}
251+
}
252+
}
253+
254+
doc.Materials.Modify(objectMaterial, objectAttributes.MaterialIndex, quiet: true);
255+
objectAttributes.MaterialSource = ObjectMaterialSource.MaterialFromObject;
256+
}
257+
else if (context.FaceMaterialId[0].IsValid())
258+
{
259+
var objectMaterial = new Material(element.Document, context.FaceMaterialId[0]);
260+
if (objectMaterial.BakeElement(idMap, false, doc, null, out var materialId))
261+
{
262+
objectAttributes.RenderMaterial = doc.RenderMaterials.Find(materialId);
263+
objectAttributes.ColorSource = ObjectColorSource.ColorFromObject;
264+
objectAttributes.ObjectColor = objectMaterial.ObjectColor;
265+
}
266+
}
267+
268+
// If we don't have per-face materials let's try to convert it to an extrusion.
269+
if (!hasPerFaceMaterials && brep.TryGetExtrusion(out var extrusion) is true)
270+
objectGeometry = extrusion;
271+
}
272+
}
273+
274+
geometry.Add(objectGeometry);
275+
attributes.Add(objectAttributes);
276+
}
277+
}
278+
279+
if (index < 0) index = doc.InstanceDefinitions.Add(idef_name, idef_description, Point3d.Origin, geometry, attributes);
280+
else if (!doc.InstanceDefinitions.ModifyGeometry(index, geometry, attributes)) index = -1;
281+
282+
if (index >= 0) idMap[element.Id] = doc.InstanceDefinitions[index].Id;
283+
}
284+
285+
return index >= 0;
286+
}
287+
#endregion
288+
}
289+
}

0 commit comments

Comments
 (0)