Index: NoesisBlueprint/Private/K2Node_NoesisAssignAndNotify.cpp
===================================================================
--- NoesisBlueprint/Private/K2Node_NoesisAssignAndNotify.cpp	(revision 12539)
+++ NoesisBlueprint/Private/K2Node_NoesisAssignAndNotify.cpp	(working copy)
@@ -351,258 +351,40 @@
 			UEdGraphPin* VariableSetPin = FindPin(GetVarNameString());
 			UEdGraphPin* VariableGetPin = FindPin(GetVariableOutputPinName());
 
-			// Set node
-			UK2Node_VariableSet* SetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableSet>(this, SourceGraph);
-			SetNode->VariableReference = VariableReference;
-			SetNode->AllocateDefaultPins();
-			UEdGraphPin* SetNodeExecPin = SetNode->GetExecPin();
-			UEdGraphPin* SetNodeThenPin = SetNode->FindPin(K2Schema->PN_Then);
-			UEdGraphPin* SetNodeSelfPin = K2Schema->FindSelfPin(*SetNode, EGPD_Input);
-			UEdGraphPin* SetNodeVariableSetPin = SetNode->FindPin(GetVarNameString());
-			UEdGraphPin* SetNodeVariableGetPin = SetNode->FindPin(GetVariableOutputPinName());
+			// CallFunction node
+			UK2Node_CallFunction* CallFunctionNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
+			CallFunctionNode->FunctionReference.SetExternalMember(TEXT("NoesisSetWithNotify"), UNoesisFunctionLibrary::StaticClass());
+			CallFunctionNode->AllocateDefaultPins();
+			UEdGraphPin* CallFunctionNodeExecPin = CallFunctionNode->GetExecPin();
+			UEdGraphPin* CallFunctionNodeThenPin = CallFunctionNode->FindPin(K2Schema->PN_Then);
+			UEdGraphPin* CallFunctionNodeSelfPin = K2Schema->FindSelfPin(*CallFunctionNode, EGPD_Input);
+			CallFunctionNodeSelfPin->DefaultObject = UNoesisFunctionLibrary::StaticClass()->GetDefaultObject();
+			UEdGraphPin* CallFunctionNodePropertyPin = CallFunctionNode->FindPin(TEXT("Property"));
+			UEdGraphPin* CallFunctionNodeValuePin = CallFunctionNode->FindPin(TEXT("Value"));
 
-			// Notify node
-			UK2Node_CallFunction* NotifyNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-			if (VariableProperty->IsA<FArrayProperty>())
-			{
-				NotifyNode->FunctionReference.SetExternalMember(TEXT("NotifyArrayChanged"), UNoesisFunctionLibrary::StaticClass());
-			}
-			else
-			{
-				NotifyNode->FunctionReference.SetExternalMember(TEXT("NotifyChanged"), UNoesisFunctionLibrary::StaticClass());
-			}
-			NotifyNode->AllocateDefaultPins();
-			UEdGraphPin* NotifyNodeExecPin = NotifyNode->GetExecPin();
-			UEdGraphPin* NotifyNodeThenPin = NotifyNode->FindPin(K2Schema->PN_Then);
-			UEdGraphPin* NotifyNodeSelfPin = K2Schema->FindSelfPin(*NotifyNode, EGPD_Input);
-			NotifyNodeSelfPin->DefaultObject = UNoesisFunctionLibrary::StaticClass()->GetDefaultObject();
-			UEdGraphPin* NotifyNodeOwnerPin = NotifyNode->FindPin(TEXT("Owner"));
-			UEdGraphPin* NotifyNodePropertyNamePin = NotifyNode->FindPin(TEXT("PropertyName"));
+			// VariableGet node
+			UK2Node_VariableGet* VariableGetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);
+			VariableGetNode->VariableReference = VariableReference;
+			VariableGetNode->AllocateDefaultPins();
+			UEdGraphPin* VariableGetNodeSelfPin = K2Schema->FindSelfPin(*VariableGetNode, EGPD_Input);
+			UEdGraphPin* VariableGetNodeVariablePin = VariableGetNode->FindPin(GetVarNameString());
 
-			// Compare node
-			UK2Node_CallFunction* CompareNode = nullptr;
-			UEdGraphPin* CompareNodeExecPin = nullptr;
-			UEdGraphPin* CompareNodeThenPin = nullptr;
-			UEdGraphPin* CompareNodeFirstInputPin = nullptr;
-			UEdGraphPin* CompareNodeSecondInputPin = nullptr;
-			UEdGraphPin* CompareNodeReturnValuePin = nullptr;
-			if (VariableProperty->IsA<FIntProperty>())
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_IntInt"), UKismetMathLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetMathLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
-			}
-			else if (VariableProperty->IsA<FFloatProperty>())
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_FloatFloat"), UKismetMathLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetMathLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
-			}
-			else if (VariableProperty->IsA<FBoolProperty>())
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_BoolBool"), UKismetMathLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetMathLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
-			}
-			else if (VariableProperty->IsA<FStrProperty>())
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_StrStr"), UKismetStringLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetStringLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
-			}
-			else if (VariableProperty->IsA<FTextProperty>())
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_TextText"), UKismetTextLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetStringLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
-			}
-			else if (VariableProperty->IsA<FObjectProperty>())
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_ObjectObject"), UKismetMathLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetMathLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
-			}
-			else if (FStructProperty* StructProperty = CastField<FStructProperty>(VariableProperty))
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NoesisStruct_NotEqual"), UNoesisFunctionLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UNoesisFunctionLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
+			// Connect the Get and Call Function nodes
+			VariableGetNodeVariablePin->MakeLinkTo(CallFunctionNodePropertyPin);
 
-				CompareNodeFirstInputPin->PinType = VariableSetPin->PinType;
-				CompareNodeSecondInputPin->PinType = VariableSetPin->PinType;
-			}
-			else if (FByteProperty* ByteProperty = CastField<FByteProperty>(VariableProperty))
-			{
-				CompareNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
-				CompareNode->FunctionReference.SetExternalMember(TEXT("NotEqual_ByteByte"), UKismetMathLibrary::StaticClass());
-				CompareNode->AllocateDefaultPins();
-				CompareNodeExecPin = CompareNode->GetExecPin();
-				CompareNodeThenPin = CompareNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* CompareNodeSelfPin = K2Schema->FindSelfPin(*CompareNode, EGPD_Input);
-				CompareNodeSelfPin->DefaultObject = UKismetMathLibrary::StaticClass()->GetDefaultObject();
-				CompareNodeFirstInputPin = CompareNode->FindPin(TEXT("A"));
-				CompareNodeSecondInputPin = CompareNode->FindPin(TEXT("B"));
-				CompareNodeReturnValuePin = CompareNode->FindPin(TEXT("ReturnValue"));
+			// Input pin types
+			K2Schema->ConvertPropertyToPinType(VariableProperty, CallFunctionNodePropertyPin->PinType);
+			K2Schema->ConvertPropertyToPinType(VariableProperty, CallFunctionNodeValuePin->PinType);
 
-				if (ByteProperty->Enum)
-				{
-					CompareNodeFirstInputPin->PinType = VariableSetPin->PinType;
-					CompareNodeSecondInputPin->PinType = VariableSetPin->PinType;
-				}
-			}
-			else if (FArrayProperty* ArrayProperty = CastField<FArrayProperty>(VariableProperty))
-			{
+			// Execution routing
+			CompilerContext.MovePinLinksToIntermediate(*ExecPin, *CallFunctionNodeExecPin);
+			CompilerContext.MovePinLinksToIntermediate(*ThenPin, *CallFunctionNodeThenPin);
 
-			}
+			// Input and output routing
+			CompilerContext.MovePinLinksToIntermediate(*SelfPin, *VariableGetNodeSelfPin);
+			CompilerContext.MovePinLinksToIntermediate(*VariableGetPin, *VariableGetNodeVariablePin);
+			CompilerContext.MovePinLinksToIntermediate(*VariableSetPin, *CallFunctionNodeValuePin);
 
-			if (CompareNode)
-			{
-				// Get node
-				UK2Node_VariableGet* GetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);
-				GetNode->VariableReference = VariableReference;
-				GetNode->AllocateDefaultPins();
-				UEdGraphPin* GetNodeExecPin = GetNode->GetExecPin();
-				UEdGraphPin* GetNodeThenPin = GetNode->FindPin(K2Schema->PN_Then);
-				UEdGraphPin* GetNodeSelfPin = K2Schema->FindSelfPin(*GetNode, EGPD_Input);
-				UEdGraphPin* GetNodeVariableGetPin = GetNode->FindPin(GetVarNameString());
-
-				// Branch node
-				UK2Node_IfThenElse* BranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);
-				BranchNode->AllocateDefaultPins();
-				UEdGraphPin* BranchNodeExecPin = BranchNode->GetExecPin();
-				UEdGraphPin* BranchNodeThenPin = BranchNode->GetThenPin();
-				UEdGraphPin* BranchNodeElsePin = BranchNode->GetElsePin();
-				UEdGraphPin* BranchNodeConditionPin = BranchNode->GetConditionPin();
-
-				// Execution routing
-				if (GetNodeExecPin)
-				{
-					CompilerContext.MovePinLinksToIntermediate(*ExecPin, *GetNodeExecPin);
-					if (CompareNodeExecPin)
-					{
-						GetNodeThenPin->MakeLinkTo(CompareNodeExecPin);
-						CompareNodeThenPin->MakeLinkTo(BranchNodeExecPin);
-					}
-					else
-					{
-						GetNodeThenPin->MakeLinkTo(BranchNodeExecPin);
-					}
-				}
-				else if (CompareNodeExecPin)
-				{
-					CompilerContext.MovePinLinksToIntermediate(*ExecPin, *CompareNodeExecPin);
-					CompareNodeThenPin->MakeLinkTo(BranchNodeExecPin);
-				}
-				else
-				{
-					CompilerContext.MovePinLinksToIntermediate(*ExecPin, *BranchNodeExecPin);
-				}
-				BranchNodeThenPin->MakeLinkTo(SetNodeExecPin);
-				CompilerContext.CopyPinLinksToIntermediate(*ThenPin, *BranchNodeElsePin);
-				SetNodeThenPin->MakeLinkTo(NotifyNodeExecPin);
-				CompilerContext.CopyPinLinksToIntermediate(*ThenPin, *NotifyNodeThenPin);
-
-				// Data routing
-				CompilerContext.CopyPinLinksToIntermediate(*VariableSetPin, *CompareNodeFirstInputPin);
-				GetNodeVariableGetPin->MakeLinkTo(CompareNodeSecondInputPin);
-				CompareNodeReturnValuePin->MakeLinkTo(BranchNodeConditionPin);
-				CompilerContext.CopyPinLinksToIntermediate(*VariableSetPin, *SetNodeVariableSetPin);
-				CompilerContext.MovePinLinksToIntermediate(*VariableGetPin, *SetNodeVariableGetPin);
-				NotifyNodePropertyNamePin->DefaultValue = GetVarNameString();
-
-				// Self assignment
-				CompilerContext.CopyPinLinksToIntermediate(*SelfPin, *GetNodeSelfPin);
-				CompilerContext.CopyPinLinksToIntermediate(*SelfPin, *SetNodeSelfPin);
-				if (SelfPin->LinkedTo.Num())
-				{
-					CompilerContext.CopyPinLinksToIntermediate(*SelfPin, *NotifyNodeOwnerPin);
-				}
-				else
-				{
-					// Self node
-					UK2Node_Self* SelfNode = CompilerContext.SpawnIntermediateNode<UK2Node_Self>(this, SourceGraph);
-					SelfNode->AllocateDefaultPins();
-					UEdGraphPin* SelfNodeSelfPin = K2Schema->FindSelfPin(*SelfNode, EGPD_Output);
-					SelfNodeSelfPin->MakeLinkTo(NotifyNodeOwnerPin);
-				}
-			}
-			else
-			{
-				// Execution routing
-				CompilerContext.MovePinLinksToIntermediate(*ExecPin, *SetNodeExecPin);
-				SetNodeThenPin->MakeLinkTo(NotifyNodeExecPin);
-				CompilerContext.CopyPinLinksToIntermediate(*ThenPin, *NotifyNodeThenPin);
-
-				// Data routing
-				CompilerContext.CopyPinLinksToIntermediate(*VariableSetPin, *SetNodeVariableSetPin);
-				CompilerContext.MovePinLinksToIntermediate(*VariableGetPin, *SetNodeVariableGetPin);
-				NotifyNodePropertyNamePin->DefaultValue = GetVarNameString();
-
-				// Self assignment
-				CompilerContext.CopyPinLinksToIntermediate(*SelfPin, *SetNodeSelfPin);
-				if (SelfPin->LinkedTo.Num())
-				{
-					CompilerContext.CopyPinLinksToIntermediate(*SelfPin, *NotifyNodeOwnerPin);
-				}
-				else
-				{
-					// Self node
-					UK2Node_Self* SelfNode = CompilerContext.SpawnIntermediateNode<UK2Node_Self>(this, SourceGraph);
-					SelfNode->AllocateDefaultPins();
-					UEdGraphPin* SelfNodeSelfPin = K2Schema->FindSelfPin(*SelfNode, EGPD_Output);
-					SelfNodeSelfPin->MakeLinkTo(NotifyNodeOwnerPin);
-				}
-			}
-
 			BreakAllNodeLinks();
 		}
 	}
Index: NoesisRuntime/Classes/NoesisFunctionLibrary.h
===================================================================
--- NoesisRuntime/Classes/NoesisFunctionLibrary.h	(revision 12539)
+++ NoesisRuntime/Classes/NoesisFunctionLibrary.h	(working copy)
@@ -41,6 +41,11 @@
 	UFUNCTION(BlueprintCallable, Category = "NoesisGUI", meta = (HidePin = "Target"))
 	static UObject* LoadXaml(class UNoesisXaml* Xaml);
 
+	UFUNCTION(BlueprintCallable, CustomThunk, meta = (BlueprintInternalUseOnly = "true", CustomStructureParam = "Property,Value"), Category = "Noesis")
+	static void NoesisSetWithNotify(const int32& Property, const int32& Value);
+
+	DECLARE_FUNCTION(execNoesisSetWithNotify);
+
 	UFUNCTION(BlueprintCallable, CustomThunk, meta = (BlueprintInternalUseOnly = "true", CustomStructureParam = "A,B"), Category = "Noesis|Struct")
 	static bool NoesisStruct_NotEqual(const FGenericStruct& A, const FGenericStruct& B);
 
Index: NoesisRuntime/Private/NoesisFunctionLibrary.cpp
===================================================================
--- NoesisRuntime/Private/NoesisFunctionLibrary.cpp	(revision 12539)
+++ NoesisRuntime/Private/NoesisFunctionLibrary.cpp	(working copy)
@@ -87,6 +87,61 @@
 	return nullptr;
 }
 
+DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisSetWithNotify)
+{
+	// Step to get the property
+	Stack.MostRecentProperty = nullptr;
+	Stack.MostRecentPropertyAddress = nullptr;
+	Stack.StepCompiledIn<FProperty>(NULL);
+	UObject* Object = (UObject*)Stack.MostRecentPropertyContainer;
+	FProperty* Property = Stack.MostRecentProperty;
+	void* PropertyAddress = Stack.MostRecentPropertyAddress;
+
+	// Sanity checks
+	check(Object != nullptr);
+	check(Property != nullptr);
+	check(PropertyAddress != nullptr);
+	check(Property->ContainerPtrToValuePtr<void>(Object) == PropertyAddress);
+
+	// Allocate and initialize the return value
+	const int32 PropertySize = Property->GetSize();
+	void* StorageSpace = FMemory_Alloca(PropertySize);
+	Property->InitializeValue(StorageSpace);
+
+	// Step to get the value
+	Stack.MostRecentProperty = nullptr;
+	Stack.MostRecentPropertyAddress = nullptr;
+	Stack.StepCompiledIn<FProperty>(StorageSpace);
+	FProperty* ValueProperty = Stack.MostRecentProperty;
+	void* ValueAddress = Stack.MostRecentPropertyAddress;
+
+	// More sanity checks
+	check(ValueProperty == nullptr || ValueProperty->IsA(Property->GetClass()));
+	check(ValueAddress == nullptr || Property->Identical(StorageSpace, ValueAddress));
+
+	P_FINISH;
+	P_NATIVE_BEGIN;
+	if (!Property->Identical(PropertyAddress, StorageSpace, PPF_None))
+	{
+		Property->SetValue_InContainer(Object, StorageSpace);
+		if (Property->IsA<FArrayProperty>())
+		{
+			NoesisNotifyArrayPropertyPostReset(PropertyAddress);
+		}
+		else if (Property->IsA<FMapProperty>())
+		{
+			NoesisNotifyMapPropertyPostReset(PropertyAddress);
+		}
+		else
+		{
+			NoesisNotifyPropertyChanged(Object, Property->GetFName());
+		}
+	}
+	P_NATIVE_END;
+
+	Property->DestroyValue(StorageSpace);
+}
+
 DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisStruct_NotEqual)
 {
 	Stack.StepCompiledIn<FStructProperty>(NULL);
