output_inst_t* FPackage::GetOutputInst(const struct FGuid OutputUid) const
{
	for (int32 IdxGraph=0 ; IdxGraph<Graphs.Num() ; ++IdxGraph)
	{
		Substance::List<graph_inst_t*>::TIterator
			InstanceIt(Graphs[IdxGraph]->LoadedInstances.itfront());

		for (; InstanceIt ; ++InstanceIt)
		{
			for (int32 IdxOut=0 ; IdxOut<(*InstanceIt)->Outputs.Num() ; ++IdxOut)
			{
				if (OutputUid == (*InstanceIt)->Outputs[IdxOut].OutputGuid)
				{
					return &(*InstanceIt)->Outputs[IdxOut];
				}
			}
		}
	}

	return NULL;
}
void SDetailsViewBase::QueryCustomDetailLayout(FDetailLayoutBuilderImpl& CustomDetailLayout)
{
	FPropertyEditorModule& ParentPlugin = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");

	// Get the registered classes that customize details
	FCustomDetailLayoutNameMap& GlobalCustomLayoutNameMap = ParentPlugin.ClassNameToDetailLayoutNameMap;

	UStruct* BaseStruct = GetBaseStruct();

	// All the current customization instances need to be deleted when it is safe
	CustomizationClassInstancesPendingDelete = CustomizationClassInstances;

	CustomizationClassInstances.Empty();

	//Ask for generic details not specific to an object being viewed 
	if (GenericLayoutDelegate.IsBound())
	{
		// Create a new instance of the custom detail layout for the current class
		TSharedRef<IDetailCustomization> CustomizationInstance = GenericLayoutDelegate.Execute();

		// Ask for details immediately
		CustomizationInstance->CustomizeDetails(CustomDetailLayout);

		// Save the instance from destruction until we refresh
		CustomizationClassInstances.Add(CustomizationInstance);
	}


	// Sort them by query order.  @todo not good enough
	struct FCompareFDetailLayoutCallback
	{
		FORCEINLINE bool operator()(const FDetailLayoutCallback& A, const FDetailLayoutCallback& B) const
		{
			return A.Order < B.Order;
		}
	};

	TMap< TWeakObjectPtr<UStruct>, FDetailLayoutCallback*> FinalCallbackMap;

	for (auto ClassIt = ClassesWithProperties.CreateConstIterator(); ClassIt; ++ClassIt)
	{
		// Check the instanced map first
		FDetailLayoutCallback* Callback = InstancedClassToDetailLayoutMap.Find(*ClassIt);

		if (!Callback)
		{
			// callback wasn't found in the per instance map, try the global instances instead
			Callback = GlobalCustomLayoutNameMap.Find((*ClassIt)->GetFName());
		}

		if (Callback)
		{
			FinalCallbackMap.Add(*ClassIt, Callback);
		}
	}


	FinalCallbackMap.ValueSort(FCompareFDetailLayoutCallback());

	TSet<UStruct*> QueriedClasses;

	if (FinalCallbackMap.Num() > 0)
	{
		// Ask each class that we have properties for to customize its layout
		for (auto LayoutIt(FinalCallbackMap.CreateConstIterator()); LayoutIt; ++LayoutIt)
		{
			const TWeakObjectPtr<UStruct> WeakClass = LayoutIt.Key();

			if (WeakClass.IsValid())
			{
				UStruct* Class = WeakClass.Get();

				FClassInstanceToPropertyMap& InstancedPropertyMap = ClassToPropertyMap.FindChecked(Class->GetFName());
				for (FClassInstanceToPropertyMap::TIterator InstanceIt(InstancedPropertyMap); InstanceIt; ++InstanceIt)
				{
					FName Key = InstanceIt.Key();
					CustomDetailLayout.SetCurrentCustomizationClass(CastChecked<UClass>(Class), Key);

					const FOnGetDetailCustomizationInstance& DetailDelegate = LayoutIt.Value()->DetailLayoutDelegate;

					if (DetailDelegate.IsBound())
					{
						QueriedClasses.Add(Class);

						// Create a new instance of the custom detail layout for the current class
						TSharedRef<IDetailCustomization> CustomizationInstance = DetailDelegate.Execute();

						// Ask for details immediately
						CustomizationInstance->CustomizeDetails(CustomDetailLayout);

						// Save the instance from destruction until we refresh
						CustomizationClassInstances.Add(CustomizationInstance);
					}
				}
			}
		}
	}

	// Ensure that the base class and its parents are always queried
	TSet<UStruct*> ParentClassesToQuery;
	if (BaseStruct && !QueriedClasses.Contains(BaseStruct))
	{
		ParentClassesToQuery.Add(BaseStruct);
		ClassesWithProperties.Add(BaseStruct);
	}

	// Find base classes of queried classes that were not queried and add them to the query list
	// this supports cases where a parent class has no properties but still wants to add customization
	for (auto QueriedClassIt = ClassesWithProperties.CreateConstIterator(); QueriedClassIt; ++QueriedClassIt)
	{
		UStruct* ParentStruct = (*QueriedClassIt)->GetSuperStruct();

		while (ParentStruct && ParentStruct->IsA(UClass::StaticClass()) && !QueriedClasses.Contains(ParentStruct) && !ClassesWithProperties.Contains(ParentStruct))
		{
			ParentClassesToQuery.Add(ParentStruct);
			ParentStruct = ParentStruct->GetSuperStruct();

		}
	}

	// Query extra base classes
	for (auto ParentIt = ParentClassesToQuery.CreateConstIterator(); ParentIt; ++ParentIt)
	{
		if (Cast<UClass>(*ParentIt))
		{
			QueryLayoutForClass(CustomDetailLayout, *ParentIt);
		}
	}
}