Skip to content

Commit

Permalink
Change on Bake.
Browse files Browse the repository at this point in the history
Now shade-color is applied to the geometry directly.
In V8 this means color by material on solids, extrusions and meshes.
  • Loading branch information
kike-garbo committed Aug 27, 2024
1 parent 1245bbf commit c364c74
Showing 7 changed files with 303 additions and 95 deletions.
25 changes: 17 additions & 8 deletions src/RhinoInside.Revit.External/DB/Extensions/Category.cs
Original file line number Diff line number Diff line change
@@ -54,13 +54,13 @@ public static bool IsEquivalent(this Category self, Category other)

public static class CategoryNaming
{
const char CS = '\\'; // Category Separator
const char CS = '|'; // Category Separator

/// <summary>
/// Return the <paramref name="category"/> full name.
/// </summary>
/// <param name="category"></param>
/// <remarks>If it is a Subcategory this will be "ParentName\SubcategoryName".</remarks>
/// <remarks>If it is a Subcategory this will be "ParentName|SubcategoryName".</remarks>
/// <returns></returns>
public static string FullName(this Category category)
{
@@ -135,10 +135,10 @@ public static Document Document(this Category category)
}

/// <summary>
/// Gets the BuiltInCategory value for this category.
/// Gets the <see cref="Autodesk.Revit.DB.BuiltInCategory"/> value for this category.
/// </summary>
/// <param name="category"></param>
/// <returns>BuiltInCategory value for the category or INVALID if the category is not a built-in category.</returns>
/// <returns><see cref="Autodesk.Revit.DB.BuiltInCategory"/> value for the category or INVALID if the category is not a built-in category.</returns>
public static BuiltInCategory ToBuiltInCategory(this Category category)
{
#if REVIT_2023
@@ -149,13 +149,22 @@ public static BuiltInCategory ToBuiltInCategory(this Category category)
}

/// <summary>
/// Return the <paramref name="category"/> discipline. If it is a subCategory this will be the parent discipline"
/// Gets the root <see cref="Autodesk.Revit.DB.Category"/> of the input <paramref name="category"/>.
/// </summary>
/// <param name="category"></param>
/// <returns></returns>
public static CategoryDiscipline CategoryDiscipline(this Category category)
/// <returns>The top most <see cref="Autodesk.Revit.DB.Category"/>.</returns>
public static Category Root(this Category category)
{
return category.Parent?.CategoryDiscipline() ?? category.ToBuiltInCategory().CategoryDiscipline();
while (category?.Parent is object) category = category.Parent;
return category;
}

/// <summary>
/// Gets the <see cref="DB.CategoryDiscipline"/> of the input <paramref name="category"/>.
/// </summary>
/// <param name="category"></param>
/// <remarks>If it is a Subcategory this will be the discipline of the root category.</remarks>
/// <returns><see cref="DB.CategoryDiscipline"/> value for the category or None if the category is unknown.</returns>
public static CategoryDiscipline CategoryDiscipline(this Category category) => category.Root().ToBuiltInCategory().CategoryDiscipline();
}
}
99 changes: 99 additions & 0 deletions src/RhinoInside.Revit.External/Extensions/System.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;

namespace System
{
@@ -89,6 +91,103 @@ public static string TripleDot(this string sourceString, int maxLength)
sourceString.Substring(0, maxLength - 1) + '…' :
sourceString;
}

#region Escaping
internal static string Escape(this string value, params char[] forced)
{
var literal = new StringBuilder(value.Length);
foreach (var c in value)
{
switch (c)
{
case '\0': literal.Append("\\\0"); break;
case '\a': literal.Append("\\\a"); break;
case '\b': literal.Append("\\\b"); break;
case '\f': literal.Append("\\\f"); break;
case '\n': literal.Append("\\\n"); break;
case '\r': literal.Append("\\\r"); break;
case '\t': literal.Append("\\\t"); break;
case '\v': literal.Append("\\\v"); break;
case '\\': literal.Append("\\\\"); break;
default:
if (char.GetUnicodeCategory(c) != UnicodeCategory.Control)
{
if (forced is object && Array.IndexOf(forced, c) != -1)
{
literal.Append('\\');
literal.Append(c);
}
else literal.Append(c);
}
else
{
literal.Append("\\x");

var codepoint = (ushort) c;
if (codepoint <= byte.MaxValue)
literal.Append(codepoint.ToString("x2"));
else
literal.Append(codepoint.ToString("x4"));
}
break;
}
}
return literal.ToString();
}

internal static string Unescape(this string value, params char[] allowed)
{
if (string.IsNullOrEmpty(value)) return value;

var retval = new StringBuilder(value.Length);
for (int i = 0; i < value.Length;)
{
int j = value.IndexOf('\\', i);
if (j < 0 || j == value.Length - 1) j = value.Length;
retval.Append(value, i, j - i);

if (j >= value.Length) break;
var c = value[j + 1];
switch (c)
{
case '\\': retval.Append('\\'); break;
case '0': retval.Append('\0'); break;
case 'a': retval.Append('\a'); break;
case 'b': retval.Append('\b'); break;
case 'f': retval.Append('\f'); break;
case 'n': retval.Append('\n'); break;
case 'r': retval.Append('\r'); break;
case 't': retval.Append('\t'); break;
case 'v': retval.Append('\v'); break;
case 'x':
int k = 0;
const string Hex = "0123456789ABCDEFabcdef";
while (k < 4 && j + 2 + k < value.Length && Hex.Contains($"{value[j + 2 + k]}")) ++k;

if (k > 0 && ushort.TryParse(value.Substring(j + 2, k), NumberStyles.AllowHexSpecifier, null, out var codepoint))
retval.Append((char) codepoint);
else
retval.Append((char)0xFFFD);
j += k;
break;
default:
if (allowed is null || Array.IndexOf(allowed, c) != -1)
retval.Append(c);
else
retval.Append((char)0xFFFD);
break;
}
i = j + 2;
}
return retval.ToString();
}

public static string ToControlEscaped(this string value) => Escape(value, Array.Empty<char>());
public static string ToControlUnescaped(this string value) => Unescape(value, Array.Empty<char>());

internal static string ToStringLiteral(this string value) => Escape(value, '\"');
internal static string ToStringVerbatim(this string value) => Unescape(value, '\'', '\"', '?');
#endregion
}
}

109 changes: 40 additions & 69 deletions src/RhinoInside.Revit.GH/Types/GeometricElement.cs
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
namespace RhinoInside.Revit.GH.Types
{
using Convert.Display;
using Convert.DocObjects;
using Convert.Geometry;
using Convert.System.Drawing;
using External.DB;
@@ -471,52 +472,9 @@ static ObjectAttributes PeekAttributes(IDictionary<ARDB.ElementId, Guid> idMap,
return attributes;
}

/// <summary>
/// Decorates instance definition name using "Category::FamilyName::TypeName" when posible.
/// </summary>
/// <param name="element"></param>
/// <param name="description"></param>
/// <returns></returns>
protected static string GetBakeInstanceDefinitionName(ARDB.Element element, out string description)
static System.Drawing.Color NoBlack(System.Drawing.Color value)
{
const string PS = "::";
var uniqueId = FullUniqueId.Format(element.Document.GetPersistentGUID(), element.UniqueId);

var hidden = true;
var modelName = element.Document.GetTitle();
var familyName = "~";
var typeName = "~";
var categoryName = element.Category?.FullName();
if (string.IsNullOrWhiteSpace(categoryName)) categoryName = "~";

if (element is ARDB.ElementType type)
{
if (!string.IsNullOrWhiteSpace(type.FamilyName)) familyName = type.FamilyName;
if (!string.IsNullOrWhiteSpace(type.Name)) typeName = type.Name;

description = element.get_Parameter(ARDB.BuiltInParameter.ALL_MODEL_DESCRIPTION)?.AsString() ?? string.Empty;
hidden = type.Category?.CategoryType != ARDB.CategoryType.Model;
}
else if (element.Document.GetElement(element.GetTypeId()) is ARDB.ElementType elementType)
{
if (!string.IsNullOrWhiteSpace(elementType.FamilyName)) familyName = elementType.FamilyName;
if (!string.IsNullOrWhiteSpace(elementType.Name)) typeName = elementType.Name;

description = elementType.get_Parameter(ARDB.BuiltInParameter.ALL_MODEL_DESCRIPTION)?.AsString() ?? string.Empty;
hidden = elementType.Category?.CategoryType != ARDB.CategoryType.Model;
}
else
{
description = string.Empty;
}

var name = $"{(hidden ? "*" : "")}{modelName}{PS}{categoryName}{PS}{familyName}{PS}{typeName} {{{uniqueId}}}";

name = name.Replace(System.Environment.NewLine, "\\r\\n");
name = name.Replace("\r", "\\r");
name = name.Replace("\n", "\\n");

return name;
return (value.R == 0 && value.G == 0 && value.B == 0) ? System.Drawing.Color.FromArgb(value.A, 1, 1, 1) : value;
}

protected internal static bool BakeGeometryElement
@@ -557,7 +515,7 @@ geometryElementContent[0] is ARDB.GeometryInstance geometryInstance &&
}

// Get a Unique Instance Definition name.
var idef_name = GetBakeInstanceDefinitionName(element, out var idef_description);
var idef_name = NameConverter.EscapeName(element, out var idef_description);

// 2. Check if already exist
index = doc.InstanceDefinitions.Find(idef_name)?.Index ?? -1;
@@ -614,9 +572,23 @@ geometryElementContent[0] is ARDB.GeometryInstance geometryInstance &&
// Solve baseMaterial
var baseMaterial = Rhino.DocObjects.Material.DefaultMaterial;
if (geoAtt.MaterialSource == ObjectMaterialSource.MaterialFromLayer)
{
baseMaterial = doc.Materials[doc.Layers[geoAtt.LayerIndex].RenderMaterialIndex];
var objectColor = new Material(context.Category.Material).ObjectColor;
geoAtt.ColorSource = ObjectColorSource.ColorFromObject;
geoAtt.ObjectColor = NoBlack(baseMaterial.DiffuseColor);
}
else if (geoAtt.MaterialSource == ObjectMaterialSource.MaterialFromObject)
{
baseMaterial = doc.Materials[geoAtt.MaterialIndex];
var objectColor = new Material(context.Material).ObjectColor;
#if RHINO_8
geoAtt.ColorSource = ObjectColorSource.ColorFromMaterial;
#else
geoAtt.ColorSource = ObjectColorSource.ColorFromObject;
geoAtt.ObjectColor = NoBlack(baseMaterial.DiffuseColor);
#endif
}

// Create a new material for this brep
var brepMaterial = new Rhino.DocObjects.Material(baseMaterial);
@@ -630,7 +602,7 @@ geometryElementContent[0] is ARDB.GeometryInstance geometryInstance &&
if (faceMaterial.BakeElement(idMap, false, doc, att, out var materialGuid))
{
face.MaterialChannelIndex = brepMaterial.MaterialChannelIndexFromId(materialGuid, true);
face.PerFaceColor = faceMaterial.ObjectColor;
face.PerFaceColor = NoBlack(faceMaterial.ObjectColor);
}
}
else
@@ -643,30 +615,29 @@ geometryElementContent[0] is ARDB.GeometryInstance geometryInstance &&
geoAtt.MaterialIndex = doc.Materials.Add(brepMaterial);
geoAtt.MaterialSource = ObjectMaterialSource.MaterialFromObject;
}
else if (context.FaceMaterialId[0].IsValid())
else
{
var faceMaterial = new Material(element.Document, context.FaceMaterialId[0]);

if (faceMaterial.BakeElement(idMap, false, doc, att, out var materialGuid))
if (context.FaceMaterialId[0].IsValid())
{
geoAtt.MaterialIndex = doc.Materials.FindId(materialGuid).Index;
geoAtt.MaterialSource = ObjectMaterialSource.MaterialFromObject;

if (geo is Brep b)
{
foreach (var face in b.Faces)
face.PerFaceColor = faceMaterial.ObjectColor;
}
else if (geo is Mesh m)
var faceMaterial = new Material(element.Document, context.FaceMaterialId[0]);
if (faceMaterial.BakeElement(idMap, false, doc, att, out var materialGuid))
{
m.VertexColors.SetColors(Enumerable.Repeat(faceMaterial.ObjectColor, m.Vertices.Count).ToArray());
geoAtt.MaterialIndex = doc.Materials.FindId(materialGuid).Index;
geoAtt.MaterialSource = ObjectMaterialSource.MaterialFromObject;
#if RHINO_8
geoAtt.ColorSource = ObjectColorSource.ColorFromMaterial;
#else
geoAtt.ColorSource = ObjectColorSource.ColorFromObject;
geoAtt.ObjectColor = NoBlack(faceMaterial.ObjectColor);
#endif
if ((geo as Brep)?.TryGetExtrusion(out var extrusion) is true) geo = extrusion;
}
}
}
else
{
if (geo is Brep brepFrom && brepFrom.TryGetExtrusion(out var extrusion))
geo = extrusion;
else
{
if (geo is Brep brepFrom && brepFrom.TryGetExtrusion(out var extrusion))
geo = extrusion;
}
}
}

@@ -748,7 +719,7 @@ out Guid guid

return false;
}
#endregion
#endregion

#region ModelContent
#if RHINO_8
@@ -796,7 +767,7 @@ geometryElementContent[0] is ARDB.GeometryInstance geometryInstance &&

var attributes = new ModelInstanceDefinition.Attributes()
{
Path = GetBakeInstanceDefinitionName(element, out var description),
Path = NameConverter.EscapeName(element, out var description),
Notes = description
};

@@ -936,7 +907,7 @@ internal override ModelContent ToModelContent(IDictionary<ARDB.ElementId, ModelC
return null;
}
#endif
#endregion
#endregion

#region IHostElementAccess
GraphicalElement IHostElementAccess.HostElement => Value is ARDB.Element element ?
27 changes: 25 additions & 2 deletions src/RhinoInside.Revit.GH/Types/Materials/Material.cs
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
using Grasshopper.Kernel;
using Rhino;
using Rhino.DocObjects;
using Rhino.Render;
using ARDB = Autodesk.Revit.DB;
#if RHINO_8
using Grasshopper.Rhinoceros;
@@ -109,9 +110,31 @@ out Guid guid
{
if (asset.BakeRenderMaterial(overwrite, doc, material.Name, out var renderMaterialId))
{
if (Rhino.Render.RenderContent.FromId(doc, renderMaterialId) is Rhino.Render.RenderMaterial renderMaterial)
if (RenderContent.FromId(doc, renderMaterialId) is RenderMaterial renderMaterial)
{
renderMaterial.SimulateMaterial(ref mat, Rhino.Render.RenderTexture.TextureGeneration.Allow);
#if RHINO_8
try
{
renderMaterial.BeginChange(RenderContent.ChangeContexts.Program);

if (!material.UseRenderAppearanceForShading)
{
var slot = renderMaterial.TextureChildSlotName(RenderMaterial.StandardChildSlots.Diffuse);
if (!renderMaterial.ChildSlotOn(slot))
{
var diffuse = RenderContent.Create(ContentUuids.SingleColorTextureType, renderMaterial, slot, default, doc) as RenderTexture;
diffuse.Name = material.Name;
diffuse.Fields.Set("color-one", renderMaterial.Fields.GetField(RenderMaterial.BasicMaterialParameterNames.Diffuse).GetValue<Rhino.Display.Color4f>());
renderMaterial.SetChildSlotAmount(slot, 100.0, RenderContent.ChangeContexts.Program);
renderMaterial.SetChildSlotOn(slot, true, RenderContent.ChangeContexts.Program);
}
}

renderMaterial.Fields.Set(RenderMaterial.BasicMaterialParameterNames.Diffuse, material.Color.ToColor());
}
finally { renderMaterial.EndChange(); }
#endif
renderMaterial.SimulateMaterial(ref mat, RenderTexture.TextureGeneration.Allow);

if (mat.Name != material.Name)
{
Loading

0 comments on commit c364c74

Please sign in to comment.