Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BHoM_UI/Caller/Compile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ protected virtual void CompileOutputSetters()
for (int index = 0; index < OutputParams.Count; index++)
{
ParamInfo param = OutputParams[index];
Func<IDataAccessor, object, int, bool> function = Engine.UI.Compute.OutputAccessor(accessorType, param.DataType);
Func<IDataAccessor, object, int, bool> function = Engine.UI.Compute.OutputAccessor(accessorType, param.DataType, QuantitiesAsDouble);
m_CompiledSetters.Add(function);
}
}
Expand Down
2 changes: 2 additions & 0 deletions BHoM_UI/Caller/Core.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public abstract partial class Caller

public virtual int GroupIndex { get; protected set; } = 1;

public virtual bool QuantitiesAsDouble { get; protected set; } = true;

public List<ParamInfo> InputParams { get; protected set; } = new List<ParamInfo>();

public List<ParamInfo> OutputParams { get; protected set; } = new List<ParamInfo>();
Expand Down
2 changes: 1 addition & 1 deletion BHoM_UI/Caller/Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ protected virtual bool PushOutputs(object result)
Type originalOutputType = OutputType(m_OriginalItem, i);
if (originalOutputType != null && originalOutputType.IsGenericType)
{
m_CompiledSetters[i] = Engine.UI.Compute.OutputAccessor(m_DataAccessor.GetType(), output.GetType());
m_CompiledSetters[i] = Engine.UI.Compute.OutputAccessor(m_DataAccessor.GetType(), output.GetType(), QuantitiesAsDouble);
m_CompiledSetters[i](m_DataAccessor, output, 0);
}
else
Expand Down
2 changes: 2 additions & 0 deletions BHoM_UI/Components/Engine/Modify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class ModifyCaller : Caller

public override string Description { get; protected set; } = "Modify a BHoM object";

public override bool QuantitiesAsDouble { get; protected set; } = false;


/*************************************/
/**** Constructors ****/
Expand Down
2 changes: 2 additions & 0 deletions BHoM_UI/Components/oM/CreateObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class CreateObjectCaller : Caller

public override string Description { get; protected set; } = "Creates an instance of a selected type of BHoM object";

public override bool QuantitiesAsDouble { get; protected set; } = false;


/*************************************/
/**** Constructors ****/
Expand Down
9 changes: 7 additions & 2 deletions UI_Engine/Compute/OutputAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,16 @@ public static partial class Compute
/**** Public Methods ****/
/*************************************/

public static Func<IDataAccessor, object, int, bool> OutputAccessor(Type accessorType, Type dataType)
public static Func<IDataAccessor, object, int, bool> OutputAccessor(Type accessorType, Type dataType, bool quantitiesAsDouble = true)
{
UnderlyingType subType = dataType.UnderlyingType();
string methodName = (subType.Depth == 0) ? "SetDataItem" : (subType.Depth == 1) ? "SetDataList" : "SetDataTree";
MethodInfo method = accessorType.GetMethod(methodName).MakeGenericMethod(subType.Type.IsByRef ? subType.Type.GetElementType() : subType.Type);

Type type = subType.Type;
if (quantitiesAsDouble && typeof(BH.oM.Quantities.IQuantity).IsAssignableFrom(type))
type = typeof(double);

MethodInfo method = accessorType.GetMethod(methodName).MakeGenericMethod(type.IsByRef ? type.GetElementType() : type);

ParameterExpression lambdaInput1 = Expression.Parameter(typeof(IDataAccessor), "accessor");
ParameterExpression lambdaInput2 = Expression.Parameter(typeof(object), "data");
Expand Down
102 changes: 87 additions & 15 deletions UI_Engine/Query/OutputParams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.Engine.Base;
using BH.Engine.Reflection;
using BH.oM.Base;
using BH.oM.Base.Attributes;
using BH.oM.Base.Reflection;
using BH.oM.Quantities.Attributes;
using BH.oM.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
Expand Down Expand Up @@ -66,7 +71,8 @@ public static List<ParamInfo> OutputParams(List<object> objects)

private static List<ParamInfo> OutputFromSingleGroup(IGrouping<Type, object> group)
{
if (typeof(IDictionary).IsAssignableFrom(group.Key) || group.Key == typeof(CustomObject))
if (typeof(IDictionary).IsAssignableFrom(group.Key)
|| typeof(IDynamicObject).IsAssignableFrom(group.Key))
{
return OutputFromMultipleGroups(new List<IGrouping<Type, object>> { group });
}
Expand All @@ -87,14 +93,15 @@ private static List<ParamInfo> OutputFromSingleGroup(IGrouping<Type, object> gro
private static List<ParamInfo> OutputFromMultipleGroups(IEnumerable<IGrouping<Type, object>> groups)
{
Dictionary<string, List<Type>> properties = new Dictionary<string, List<Type>>();
Dictionary<string, string> descriptions = new Dictionary<string, string>();

// Collect the properties types and names
foreach (var group in groups)
{
if (typeof(IDictionary).IsAssignableFrom(group.Key))
CollectOutputTypes(group.Cast<IDictionary>(), ref properties);
else if (group.Key == typeof(CustomObject))
CollectOutputTypes(group.Cast<CustomObject>(), ref properties);
else if (typeof(IDynamicObject).IsAssignableFrom(group.Key))
CollectOutputTypes(group.Cast<IDynamicObject>(), ref properties, ref descriptions);
else
CollectOutputTypes(group.Key, ref properties);
}
Expand All @@ -105,9 +112,12 @@ private static List<ParamInfo> OutputFromMultipleGroups(IEnumerable<IGrouping<Ty
{
IEnumerable<Type> uniqueTypes = kvp.Value.Distinct();
Type commonType = uniqueTypes.Count() > 1 ? typeof(object) : uniqueTypes.FirstOrDefault();
string description = descriptions.ContainsKey(kvp.Key) ? descriptions[kvp.Key] : commonType.IDescription();

outputParams.Add(new ParamInfo
{
DataType = commonType ?? typeof(object),
Description = description,
Name = kvp.Key,
Kind = ParamKind.Output
});
Expand Down Expand Up @@ -136,6 +146,18 @@ private static void CollectOutputTypes(IEnumerable<IDictionary> objects, ref Dic
properties[key].Add(dic[key].GetType() ?? null);
}
}
else if (types[0].IsEnum)
{
foreach (Enum key in dic.Keys.OfType<Enum>())
{
string stringKey = key.IToText();
if (key != null & !properties.ContainsKey(stringKey))
properties[stringKey] = new List<Type>();

if (dic[key] != null)
properties[stringKey].Add(dic[key].GetType() ?? null);
}
}
else
{
properties["Keys"] = new List<Type> { typeof(List<>).MakeGenericType(new Type[] { types[0] }) };
Expand All @@ -146,21 +168,71 @@ private static void CollectOutputTypes(IEnumerable<IDictionary> objects, ref Dic

/*************************************/

private static void CollectOutputTypes(IEnumerable<CustomObject> objects, ref Dictionary<string, List<Type>> properties)
private static void CollectOutputTypes(IEnumerable<IDynamicObject> objects, ref Dictionary<string, List<Type>> properties, ref Dictionary<string, string> descriptions)
{
foreach (KeyValuePair<string, object> prop in objects.SelectMany(x => x.CustomData))
foreach (IDynamicObject obj in objects)
{
if (!properties.ContainsKey(prop.Key))
properties[prop.Key] = new List<Type>();
if (prop.Value != null)
properties[prop.Key].Add(prop.Value.GetType() ?? null);
object result;

if (obj is IDynamicPropertyProvider)
{
bool success = BH.Engine.Base.Compute.TryRunExtensionMethod(obj, "GetProperties", new object[] { }, out result);

if (success && result is List<Property>)
{
foreach (var prop in result as List<Property>)
{
if (!properties.ContainsKey(prop.Name))
{
properties[prop.Name] = new List<Type>();
descriptions[prop.Name] = prop.Description;
}

properties[prop.Name].Add(prop.Type);
}
}
}
else
{
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
if (prop.GetCustomAttribute<DynamicPropertyAttribute>() != null
&& typeof(IDictionary).IsAssignableFrom(prop.PropertyType)
&& prop.PropertyType.GenericTypeArguments.First().IsEnum)
{
IDictionary dic = prop.GetValue(obj) as IDictionary;

string typeDescription = prop.GetCustomAttribute<QuantityAttribute>()?.Description();
if (string.IsNullOrEmpty(typeDescription))
typeDescription = dic.GetType().GenericTypeArguments[1].Description();

foreach (Enum key in dic.Keys.OfType<Enum>().OrderBy(x => x))
{
string stringKey = key.IToText();
if (key != null & !properties.ContainsKey(stringKey))
{
properties[stringKey] = new List<Type>();
descriptions[stringKey] = key.IDescription() + "\n" + typeDescription;
}

if (dic[key] != null)
properties[stringKey].Add(dic[key].GetType() ?? null);
}
}
else
{
if (!properties.ContainsKey(prop.Name))
{
properties[prop.Name] = new List<Type>();
descriptions[prop.Name] = prop.Description();
}

properties[prop.Name].Add(prop.PropertyType);
}
}
}
}
if (!properties.ContainsKey("Name"))
properties["Name"] = new List<Type> { typeof(string) };
if (!properties.ContainsKey("Tags"))
properties["Tags"] = new List<Type> { typeof(HashSet<string>) };
if (!properties.ContainsKey("BHoM_Guid"))
properties["BHoM_Guid"] = new List<Type> { typeof(Guid) };

}

/*************************************/
Expand Down
5 changes: 5 additions & 0 deletions UI_Engine/UI_Engine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Quantities_oM">
<HintPath>$(ProgramData)\BHoM\Assemblies\Quantities_oM.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Reflection_Engine">
<HintPath>$(ProgramData)\BHoM\Assemblies\Reflection_Engine.dll</HintPath>
<Private>False</Private>
Expand Down