From 7c4da7d51a7bb148bb3812a74303fc20a70cb576 Mon Sep 17 00:00:00 2001 From: "dukecg@gmail.com" Date: Thu, 15 Mar 2018 21:32:04 +1100 Subject: [PATCH 01/20] added ue4 defaults to gitignore --- .gitignore | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6c99720..a2f1d22 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,77 @@ -Source/Noesis/NoesisSDK/* +# Visual Studio 2015 user specific files +.vs/ + +# Visual Studio 2015 database file +*.VC.db + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +*.ipa + +# These project files can be generated by the engine +*.xcodeproj +*.xcworkspace +*.sln +*.suo +*.opensdf +*.sdf +*.VC.db +*.VC.opendb + +# Precompiled Assets +SourceArt/**/*.png +SourceArt/**/*.tga + +# Binary Files +Binaries/* + +# Builds +Build/* + +# Whitelist PakBlacklist-.txt files +!Build/*/ +Build/*/** +!Build/*/PakBlacklist*.txt + +# Don't ignore icon files in Build +!Build/**/*.ico + +# Built data for maps +*_BuiltData.uasset + +# Configuration files generated by the Editor +Saved/* + +# Compiled source files for the engine to use +Intermediate/* + +# Cache files for the editor to use +DerivedDataCache/* + +Source/Noesis/NoesisSDK/* \ No newline at end of file From 38c1acebd4c7f1a268844115e24e63f11c81de25 Mon Sep 17 00:00:00 2001 From: "dukecg@gmail.com" Date: Sat, 17 Mar 2018 01:06:05 +1100 Subject: [PATCH 02/20] add notify property changed csv thingy --- Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h | 4 ++++ Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h b/Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h index b34ca7c..34dc48e 100644 --- a/Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h +++ b/Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h @@ -23,6 +23,10 @@ class NOESISRUNTIME_API UNoesisFunctionLibrary : public UBlueprintFunctionLibrar UFUNCTION(BlueprintCallable, Category = "NoesisGUI", meta = (HidePin = "Target")) static void NotifyChanged(UObject* Owner, FName PropertyName); + /* Comma seperated property names. */ + UFUNCTION(BlueprintCallable, Category = "NoesisGUI", meta = (HidePin = "Target")) + static void NotifyChanges(UObject* Owner, FName PropertyNames); + UFUNCTION(BlueprintCallable, Category = "NoesisGUI", meta = (HidePin = "Target")) static void NotifyArrayChanged(UObject* Owner, FName PropertyName); diff --git a/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp b/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp index 9e78aed..17f8264 100644 --- a/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp +++ b/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp @@ -28,6 +28,15 @@ void UNoesisFunctionLibrary::NotifyChanged(UObject* Owner, FName PropertyName) NoesisNotifyPropertyChanged(Owner, PropertyName); } +void UNoesisFunctionLibrary::NotifyChanges(UObject* Owner, FName PropertyNames) +{ + TArray Names; + PropertyNames.ToString().ParseIntoArray(Names, TEXT(",")); + + for (auto& Name : Names) + NoesisNotifyArrayPropertyChanged(Owner, FName(*Name)); +} + void UNoesisFunctionLibrary::NotifyArrayChanged(UObject* Owner, FName PropertyName) { NoesisNotifyArrayPropertyChanged(Owner, PropertyName); From 361a215c49b522f7e30752b88160301cbdc86a0e Mon Sep 17 00:00:00 2001 From: RPG3D Date: Wed, 7 Feb 2018 16:51:02 +0800 Subject: [PATCH 03/20] avoid crash when texture param is nullptr --- Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp index 9b62a7a..fac6b54 100644 --- a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp +++ b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp @@ -204,7 +204,7 @@ FRHICommandList* FNoesisRenderDevice::ThreadLocal_GetRHICmdList() Noesis::Ptr FNoesisRenderDevice::CreateTexture(UTexture* InTexture) { - if (!InTexture->Resource) + if (!InTexture || !InTexture->Resource) return nullptr; FNoesisTexture* Texture = nullptr; From d66011119e644bbfe35a58920f170ae1310ea55c Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Tue, 24 Jul 2018 11:10:41 +0200 Subject: [PATCH 04/20] Plugin updated to 4.20 --- NoesisGUI.uplugin | 2 +- Source/Noesis/Noesis.Build.cs | 42 +++++++++++-------- Source/Noesis/NoesisSDK.h | 4 +- .../NoesisBlueprintCompilerContext.cpp | 2 +- .../Private/NoesisEditorPrivatePCH.h | 2 +- Source/NoesisRuntime/Classes/NoesisInstance.h | 2 +- .../NoesisRuntime/Private/NoesisInstance.cpp | 16 ++++--- .../Private/NoesisRuntimeModule.cpp | 10 +++++ .../Private/NoesisRuntimePrivatePCH.h | 4 +- .../Private/Render/NoesisRenderDevice.cpp | 3 +- 10 files changed, 51 insertions(+), 36 deletions(-) diff --git a/NoesisGUI.uplugin b/NoesisGUI.uplugin index d306126..4a2b629 100644 --- a/NoesisGUI.uplugin +++ b/NoesisGUI.uplugin @@ -10,7 +10,7 @@ "DocsURL": "http://www.noesisengine.com/docs", "MarketplaceURL": "", "SupportURL": "http://www.noesisengine.com/forums", - "EngineVersion": "4.19.0", + "EngineVersion": "4.20.0", "CanContainContent": true, "Installed": true, "Modules": [ diff --git a/Source/Noesis/Noesis.Build.cs b/Source/Noesis/Noesis.Build.cs index c6b12fe..9eca2db 100644 --- a/Source/Noesis/Noesis.Build.cs +++ b/Source/Noesis/Noesis.Build.cs @@ -17,6 +17,7 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) string NoesisBasePath = ModuleDirectory + "/NoesisSDK/"; string NoesisIncludePath = NoesisBasePath + "Include/"; + PublicIncludePaths.Add(ModuleDirectory); PublicIncludePaths.Add(NoesisIncludePath); // Let's try to make sure the right version of the SDK is in the right place. @@ -66,10 +67,13 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); - string BaseTargetPath; + string BaseTargetPath = ""; if (Target.LinkType == TargetLinkType.Monolithic) { - BaseTargetPath = DirectoryReference.FromFile(Target.ProjectFile).ToString(); + if (Target.ProjectFile != null) + { + BaseTargetPath = DirectoryReference.FromFile(Target.ProjectFile).ToString(); + } } else { @@ -79,21 +83,6 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) string NoesisDllPath = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll"; string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll"; - try - { - if (!System.IO.Directory.Exists(BaseTargetPath + "/Binaries/Win64")) - { - System.IO.Directory.CreateDirectory(BaseTargetPath + "/Binaries/Win64"); - } - System.IO.File.Copy(ModuleDirectory + NoesisDllPath, BaseTargetPath + NoesisDllTargetPath, true); - } - catch (IOException Exception) - { - if (Exception.HResult != -2147024864) // 0x80070020: The process cannot access the file ... because it is being used by another process. - { - throw; - } - } if (Target.LinkType == TargetLinkType.Monolithic) { RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath); @@ -102,6 +91,25 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) { RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath); } + + if (BaseTargetPath != "") + { + try + { + if (!System.IO.Directory.Exists(BaseTargetPath + "/Binaries/Win64")) + { + System.IO.Directory.CreateDirectory(BaseTargetPath + "/Binaries/Win64"); + } + System.IO.File.Copy(ModuleDirectory + NoesisDllPath, BaseTargetPath + NoesisDllTargetPath, true); + } + catch (IOException Exception) + { + if (Exception.HResult != -2147024864) // 0x80070020: The process cannot access the file ... because it is being used by another process. + { + throw; + } + } + } } else if (Target.Platform == UnrealTargetPlatform.Mac) { diff --git a/Source/Noesis/NoesisSDK.h b/Source/Noesis/NoesisSDK.h index 1940e14..6ccd81d 100644 --- a/Source/Noesis/NoesisSDK.h +++ b/Source/Noesis/NoesisSDK.h @@ -7,7 +7,7 @@ #ifdef PLATFORM_WINDOWS #if PLATFORM_WINDOWS -#include "AllowWindowsPlatformTypes.h" +#include "Windows/AllowWindowsPlatformTypes.h" #endif #endif @@ -15,6 +15,6 @@ #ifdef PLATFORM_WINDOWS #if PLATFORM_WINDOWS -#include "HideWindowsPlatformTypes.h" +#include "Windows/HideWindowsPlatformTypes.h" #endif #endif diff --git a/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp b/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp index a1f52f1..91c068b 100644 --- a/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp +++ b/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp @@ -6,7 +6,7 @@ #include "NoesisBlueprintCompilerContext.h" // UnrealEd includes -#include "KismetReinstanceUtilities.h" +#include "Kismet2/KismetReinstanceUtilities.h" FNoesisBlueprintCompilerContext::FNoesisBlueprintCompilerContext(UNoesisBlueprint* NoesisBlueprint, FCompilerResultsLog& Results, const FKismetCompilerOptions& CompilerOptions, TArray* ObjLoaded) : Super(NoesisBlueprint, Results, CompilerOptions, ObjLoaded) diff --git a/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h b/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h index e36a818..8e66150 100644 --- a/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h +++ b/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h @@ -66,7 +66,7 @@ THIRD_PARTY_INCLUDES_END #include "AssetRegistryModule.h" // EditorStyle includes -#include "EditorStyleSettings.h" +#include "Classes/EditorStyleSettings.h" // KismetCompiler includes #include "KismetCompiler.h" diff --git a/Source/NoesisRuntime/Classes/NoesisInstance.h b/Source/NoesisRuntime/Classes/NoesisInstance.h index bc9cb7b..dfdb324 100644 --- a/Source/NoesisRuntime/Classes/NoesisInstance.h +++ b/Source/NoesisRuntime/Classes/NoesisInstance.h @@ -107,7 +107,7 @@ class NOESISRUNTIME_API UNoesisInstance : public UUserWidget // UUserWidget interface virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; - virtual void NativePaint(FPaintContext& InContext) const override; + virtual int32 NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; //virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const override; virtual FReply NativeOnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) override; virtual FReply NativeOnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& KeyEvent) override; diff --git a/Source/NoesisRuntime/Private/NoesisInstance.cpp b/Source/NoesisRuntime/Private/NoesisInstance.cpp index d9a921a..897ca23 100644 --- a/Source/NoesisRuntime/Private/NoesisInstance.cpp +++ b/Source/NoesisRuntime/Private/NoesisInstance.cpp @@ -11,9 +11,6 @@ // RenderCore includes #include "RenderingThread.h" -// Renderer includes -#include "Private/PostProcess/SceneRenderTargets.h" - // UtilityShaders includes #include "ClearQuad.h" @@ -548,9 +545,9 @@ void UNoesisInstance::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) Update(AbsolutePosition.X, AbsolutePosition.Y, AbsoluteSize.X, AbsoluteSize.Y); } -void UNoesisInstance::NativePaint(FPaintContext& InContext) const +int32 UNoesisInstance::NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const { - Super::NativePaint(InContext); + int32 MaxLayer = Super::NativePaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled); if (XamlView) { @@ -560,8 +557,7 @@ void UNoesisInstance::NativePaint(FPaintContext& InContext) const NoesisInstance->DrawOffscreen_RenderThread(RHICmdList, 0, 0); }); - const FSlateRect& MyClippingRect = InContext.MyCullingRect; - FSlateWindowElementList& OutDrawElements = InContext.OutDrawElements; + const FSlateRect& MyClippingRect = MyCullingRect; NoesisSlateElement->Left = MyClippingRect.Left; NoesisSlateElement->Top = MyClippingRect.Top; @@ -574,11 +570,13 @@ void UNoesisInstance::NativePaint(FPaintContext& InContext) const FVector2D BottomRight(MyClippingRect.Right + 1, MyClippingRect.Bottom + 1); FSlateClippingZone Clip(TopLeft, TopRight, BottomLeft, BottomRight); OutDrawElements.PushClip(Clip); - FSlateDrawElement::MakeCustom(OutDrawElements, InContext.LayerId, NoesisSlateElement); + FSlateDrawElement::MakeCustom(OutDrawElements, LayerId, NoesisSlateElement); OutDrawElements.PopClip(); - InContext.MaxLayer = InContext.LayerId; + MaxLayer = FMath::Max(MaxLayer, LayerId); } + + return MaxLayer; } FReply UNoesisInstance::NativeOnKeyChar(const FGeometry& MyGeometry, const FCharacterEvent& CharacterEvent) diff --git a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp index ef56ced..82b6539 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp +++ b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp @@ -231,6 +231,11 @@ class NoesisTextBoxVirtualKeyboardEntry : public IVirtualKeyboardEntry return Keyboard_Default; } + virtual FVirtualKeyboardOptions GetVirtualKeyboardOptions() const + { + return FVirtualKeyboardOptions(); + } + virtual bool IsMultilineEntry() const override { return IsMultiline; @@ -279,6 +284,11 @@ class NoesisPasswordBoxVirtualKeyboardEntry : public IVirtualKeyboardEntry return Keyboard_Password; } + virtual FVirtualKeyboardOptions GetVirtualKeyboardOptions() const + { + return FVirtualKeyboardOptions(); + } + virtual bool IsMultilineEntry() const override { return false; diff --git a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h index b3d3291..ae82219 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h +++ b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h @@ -24,7 +24,7 @@ #include "ShaderParameterUtils.h" // CoreUObject includes -#include "UObjectGlobals.h" +#include "UObject/UObjectGlobals.h" // UMG includes #include "Blueprint/UserWidget.h" @@ -46,7 +46,7 @@ #include "RenderingThread.h" // SlateCore includes -#include "SLeafWidget.h" +#include "Widgets/SLeafWidget.h" #include "Rendering/DrawElements.h" // ApplicationCore includes diff --git a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp index fac6b54..b14e973 100644 --- a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp +++ b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp @@ -407,13 +407,12 @@ void FNoesisRenderDevice::ResolveRenderTarget(Noesis::RenderTarget* Surface, con uint32 ResolveMaxX = Tile.x + Tile.width; uint32 ResolveMaxY = CurrentRenderTarget->Texture->ShaderResourceTexture->GetSizeY() - Tile.y; - bool PreserveRenderTargetContents = false; FResolveParams ResolveParams; ResolveParams.Rect.X1 = ResolveMinX; ResolveParams.Rect.Y1 = ResolveMinY; ResolveParams.Rect.X2 = ResolveMaxX; ResolveParams.Rect.Y2 = ResolveMaxY; - RHICmdList->CopyToResolveTarget(CurrentRenderTarget->ColorTarget, CurrentRenderTarget->Texture->ShaderResourceTexture, PreserveRenderTargetContents, ResolveParams); + RHICmdList->CopyToResolveTarget(CurrentRenderTarget->ColorTarget, CurrentRenderTarget->Texture->ShaderResourceTexture, ResolveParams); } } From 7ff833ee7616f1a3cf1f97bcd49bdaab26b1f75b Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Wed, 25 Jul 2018 13:53:03 +0200 Subject: [PATCH 05/20] Resolve fix --- Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp index b14e973..1f125ba 100644 --- a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp +++ b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp @@ -412,6 +412,10 @@ void FNoesisRenderDevice::ResolveRenderTarget(Noesis::RenderTarget* Surface, con ResolveParams.Rect.Y1 = ResolveMinY; ResolveParams.Rect.X2 = ResolveMaxX; ResolveParams.Rect.Y2 = ResolveMaxY; + ResolveParams.DestRect.X1 = ResolveMinX; + ResolveParams.DestRect.Y1 = ResolveMinY; + ResolveParams.DestRect.X2 = ResolveMaxX; + ResolveParams.DestRect.Y2 = ResolveMaxY; RHICmdList->CopyToResolveTarget(CurrentRenderTarget->ColorTarget, CurrentRenderTarget->Texture->ShaderResourceTexture, ResolveParams); } } From 1372292d5fcc3add477fc9a26f7f6cf25013b08c Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Wed, 25 Jul 2018 13:53:51 +0200 Subject: [PATCH 06/20] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46e4473..a4a0b21 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NoesisGUI Unreal Engine 4.19 Plugin +# NoesisGUI Unreal Engine 4.20 Plugin ## Introduction From c598f9a61863c3e80e351552150d93c29e1ebfac Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Thu, 26 Jul 2018 11:33:26 +0200 Subject: [PATCH 07/20] Added UE4 defaults to .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a2f1d22..dd82421 100644 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,4 @@ Intermediate/* # Cache files for the editor to use DerivedDataCache/* -Source/Noesis/NoesisSDK/* \ No newline at end of file +Source/Noesis/NoesisSDK/* From 450b2be35aa680aed5976bb40f372b3d6792622b Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Wed, 1 Aug 2018 11:43:28 +0200 Subject: [PATCH 08/20] Epic Games Launcher engine installation is no longer supported --- InstallPlugin.py | 12 ++---------- README.md | 4 +++- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/InstallPlugin.py b/InstallPlugin.py index 62ac153..b124cac 100644 --- a/InstallPlugin.py +++ b/InstallPlugin.py @@ -299,23 +299,15 @@ def buildPlugin(platforms): if not installerEngineInstall: if not arguments: build("UE4Editor", ["Development"], [hostPlatform]) - build("UE4Game", ["Development", "Shipping"], [hostPlatform]) else: if buildPlatforms: if hostPlatform in buildPlatforms: build("UE4Editor", ["Development"], [hostPlatform]) - build("UE4Game", ["Development", "Shipping"], buildPlatforms) else: print("No valid platforms specified. Exiting...") else: - print("Launcher engine installation detected. Using BuildPlugin") - if not arguments: - buildPlugin([hostPlatform]) - else: - if buildPlatforms: - buildPlugin(buildPlatforms) - else: - print("No valid platforms specified. Exiting...") + print("Launcher engine installation detected. This configuration is no longer supported. Please install as a project plugin.") + exit(1) if engineInstall: if installerEngineInstall: diff --git a/README.md b/README.md index a4a0b21..7f3e1f8 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ In order to use NoesisGUI in your UE4 project, you're going to need: The plugin works with versions of Unreal Engine installed trough the Epic Games Launcher as well as those built by yourself from the source code in GitHub. -You can use the NoesisGUI Unreal Engine plugin as either an Engine plugin or a Project (Game) plugin. For more information about Unreal Engine Plugins, please refer to the [Plugins](https://docs.unrealengine.com/latest/INT/Programming/Plugins/index.html) documentation. +With versions of Unreal Engine built from the source code in GitHub you can use the NoesisGUI Unreal Engine plugin as either an Engine plugin or a Project (Game) plugin. However, if you're using an Epic Games Launcher version of the engine, you can only install the plugin as a Project plugin. For more information about Unreal Engine Plugins, please refer to the [Plugins](https://docs.unrealengine.com/latest/INT/Programming/Plugins/index.html) documentation. ### Prerequisites @@ -69,6 +69,8 @@ You can use the NoesisGUI Unreal Engine plugin as either an Engine plugin or a P 3. Install the plugin by executing `InstallPlugin.bat` from the Command Prompt on Windows or `InstallPlugin.command` from the Terminal on Mac. If you're targeting more than one platform, you can pass them as arguments like this: `InstallPlugin.command Mac IOS`. The installer uses the same platform names as Unreal. The valid platform names are `Win64`, `Mac`, `IOS`, `Android`, `PS4` and `XboxOne`. The host platform (`Win64` or `Mac`) is always built, as those binaries are required to run the editor. If you've installed the plugin as a project plugin the installer will enable it automatically by adding it to your `.uproject` file, as described in [Enabling and configuring the plugin](#enabling-and-configuring-the-plugin). IMPORTANT: You will need to perform this step every time you update Unreal Engine or get a new version of this plugin or the NoesisGUI SDK. +4. Even after these steps, sometimes the Editor will warn you that the modules NoesisRuntime and NoesisEditor are out of date when you try to launch it. This may happen if you're running a configuration other than Development or if you've changed to a different engine version. Just click accept so the modules are rebuilt to target the correct version of Unreal Engine. + ## Directory structure If all the steps so far have been successful, your Unreal Engine install should contain the following directories. Please note that only the directories relevant to the NoesisGUI plugin are listed here, and that your installation may contain additional files and directories that have been omitted here for clarity. From 7fc758f8d34010c1e8947017f6f206fe5bf73aa5 Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Thu, 2 Aug 2018 23:22:11 +0200 Subject: [PATCH 09/20] Set SRGB flag to false by default on imported textures --- Source/NoesisEditor/Private/NoesisXamlFactory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp index 3f4de3c..c220d8c 100644 --- a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp +++ b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp @@ -453,6 +453,7 @@ void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, if (Texture != NULL) { Texture->LODGroup = TEXTUREGROUP_UI; + Texture->SRGB = false; void FixPremultipliedPNGTexture(UTexture2D*); FixPremultipliedPNGTexture(Texture); From deff2f5baa17aa7f92d88d2a3a02aae50e886278 Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Fri, 3 Aug 2018 01:13:27 +0200 Subject: [PATCH 10/20] Allow textures to be recreated by destroying the thumbnail renderers when any property is edited --- .../Private/NoesisEditorModule.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/Source/NoesisEditor/Private/NoesisEditorModule.cpp b/Source/NoesisEditor/Private/NoesisEditorModule.cpp index 3260c55..85a6770 100644 --- a/Source/NoesisEditor/Private/NoesisEditorModule.cpp +++ b/Source/NoesisEditor/Private/NoesisEditorModule.cpp @@ -122,11 +122,22 @@ void OnObjectReimported(UFactory* ImportFactory, UObject* InObject) void OnObjectPropertyChanged(UObject* Object, struct FPropertyChangedEvent& Event) { - static FName LODGroup = "LODGroup"; - if (Object->IsA() && Event.Property && Event.Property->GetFName() == LODGroup) + static uint32 ReentryGuard = 0; + if (!ReentryGuard) { - UTexture2D* Texture = (UTexture2D*)Object; - FixPremultipliedPNGTexture(Texture); + ReentryGuard = 1; + for (TObjectIterator It; It; ++It) + { + UNoesisXaml* Xaml = *It; + Xaml->DestroyThumbnailRenderData(); + } + + if (Object->IsA()) + { + UTexture2D* Texture = (UTexture2D*)Object; + FixPremultipliedPNGTexture(Texture); + } + ReentryGuard = 0; } } From 1cdc7dd47ac3565146de3c5df02b4a41812c2faa Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Fri, 3 Aug 2018 01:15:01 +0200 Subject: [PATCH 11/20] Removed logging that could pop up in normal circumstances --- Source/NoesisRuntime/Private/NoesisTypeClass.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Source/NoesisRuntime/Private/NoesisTypeClass.cpp b/Source/NoesisRuntime/Private/NoesisTypeClass.cpp index fa99fc1..5d82642 100644 --- a/Source/NoesisRuntime/Private/NoesisTypeClass.cpp +++ b/Source/NoesisRuntime/Private/NoesisTypeClass.cpp @@ -2344,17 +2344,11 @@ void NoesisNotifyPropertyChanged(UObject* Owner, FName PropertyName) #if DO_CHECK // Skip in shipping build if (!Wrapper->GetClassType()->FindProperty(PropertySymbol)) { - UE_LOG(LogNoesis, Error, TEXT("Couldn't resolve property %s::%s"), *Owner->GetClass()->GetFName().ToString(), *PropertyName.ToString()); + UE_LOG(LogNoesis, Warning, TEXT("Couldn't resolve property %s::%s"), *Owner->GetClass()->GetFName().ToString(), *PropertyName.ToString()); } #endif Wrapper->NotifyPropertyChanged(PropertySymbol); } -#if DO_CHECK // Skip in shipping build - else - { - UE_LOG(LogNoesis, Error, TEXT("Couldn't resolve class %s"), *Owner->GetClass()->GetFName().ToString()); - } -#endif } void NoesisNotifyArrayPropertyChanged(UObject* Owner, FName ArrayPropertyName) @@ -2377,16 +2371,10 @@ void NoesisNotifyArrayPropertyChanged(UObject* Owner, FName ArrayPropertyName) #if DO_CHECK // Skip in shipping build else { - UE_LOG(LogNoesis, Error, TEXT("Couldn't resolve property %s::%s"), *Owner->GetClass()->GetFName().ToString(), *ArrayPropertyName.ToString()); + UE_LOG(LogNoesis, Warning, TEXT("Couldn't resolve property %s::%s"), *Owner->GetClass()->GetFName().ToString(), *ArrayPropertyName.ToString()); } #endif } -#if DO_CHECK // Skip in shipping build - else - { - UE_LOG(LogNoesis, Error, TEXT("Couldn't resolve class %s"), *Owner->GetClass()->GetFName().ToString()); - } -#endif } void NoesisNotifyArrayPropertyAdd(void* ArrayPointer) From e8f655e7c57ab5bb3f6a0e5b378a997310211439 Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Fri, 12 Oct 2018 12:31:57 +0200 Subject: [PATCH 12/20] Non-PCH build fix --- Source/NoesisRuntime/Private/NoesisInstance.cpp | 5 +++++ Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp | 2 ++ Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h | 2 -- Source/NoesisRuntime/Public/NoesisRuntimeModule.h | 4 ++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/NoesisRuntime/Private/NoesisInstance.cpp b/Source/NoesisRuntime/Private/NoesisInstance.cpp index 897ca23..af734dc 100644 --- a/Source/NoesisRuntime/Private/NoesisInstance.cpp +++ b/Source/NoesisRuntime/Private/NoesisInstance.cpp @@ -5,6 +5,10 @@ #include "NoesisInstance.h" +// Core includes +#include "Stats/Stats.h" +#include "Stats/Stats2.h" + // Engine includes #include "SceneUtils.h" @@ -23,6 +27,7 @@ #include "Framework/Application/SlateApplication.h" // NoesisRuntime includes +#include "NoesisRuntimeModule.h" #include "NoesisBlueprintGeneratedClass.h" #include "Render/NoesisRenderDevice.h" #include "NoesisTypeClass.h" diff --git a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp index 82b6539..96e112a 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp +++ b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp @@ -9,6 +9,8 @@ #include "CoreMinimal.h" #include "Misc/CoreDelegates.h" #include "Modules/ModuleManager.h" +#include "Stats/Stats.h" +#include "Stats/Stats2.h" // ApplicationCore includes #include "HAL/PlatformApplicationMisc.h" diff --git a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h index ae82219..c3c45f3 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h +++ b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h @@ -73,5 +73,3 @@ #include "NoesisRuntimeClasses.h" #include "NoesisRuntimeModule.h" - -DECLARE_STATS_GROUP(TEXT("Noesis"), STATGROUP_Noesis, STATCAT_Advanced); diff --git a/Source/NoesisRuntime/Public/NoesisRuntimeModule.h b/Source/NoesisRuntime/Public/NoesisRuntimeModule.h index f913007..51b5fcd 100644 --- a/Source/NoesisRuntime/Public/NoesisRuntimeModule.h +++ b/Source/NoesisRuntime/Public/NoesisRuntimeModule.h @@ -8,9 +8,13 @@ // Core includes #include "CoreMinimal.h" #include "Modules/ModuleInterface.h" +#include "Stats/Stats.h" +#include "Stats/Stats2.h" DECLARE_LOG_CATEGORY_EXTERN(LogNoesis, VeryVerbose, All); +DECLARE_STATS_GROUP(TEXT("Noesis"), STATGROUP_Noesis, STATCAT_Advanced); + #define NOESISGUI_MODULE_NAME "NoesisRuntime" class NOESISRUNTIME_API INoesisRuntimeModuleInterface : public IModuleInterface From 147f80c6913c98267c9fdf1ae04b6608c44f1213 Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Mon, 19 Nov 2018 23:24:29 +0100 Subject: [PATCH 13/20] Plugin updated to 4.21 --- NoesisGUI.uplugin | 2 +- README.md | 2 +- Source/NoesisRuntime/Classes/NoesisStructs.h | 34 +++++++------- Source/NoesisRuntime/NoesisRuntime.Build.cs | 3 +- .../NoesisRuntime/Private/NoesisInstance.cpp | 34 +++++++++----- .../Private/NoesisResourceProvider.cpp | 8 +++- .../Private/NoesisRuntimeModule.cpp | 19 ++++++++ .../NoesisRuntime/Private/NoesisTypeClass.cpp | 44 ++++++++++++------- 8 files changed, 95 insertions(+), 51 deletions(-) diff --git a/NoesisGUI.uplugin b/NoesisGUI.uplugin index 4a2b629..94a9a13 100644 --- a/NoesisGUI.uplugin +++ b/NoesisGUI.uplugin @@ -10,7 +10,7 @@ "DocsURL": "http://www.noesisengine.com/docs", "MarketplaceURL": "", "SupportURL": "http://www.noesisengine.com/forums", - "EngineVersion": "4.20.0", + "EngineVersion": "4.21.0", "CanContainContent": true, "Installed": true, "Modules": [ diff --git a/README.md b/README.md index 7f3e1f8..52e281c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NoesisGUI Unreal Engine 4.20 Plugin +# NoesisGUI Unreal Engine 4.21 Plugin ## Introduction diff --git a/Source/NoesisRuntime/Classes/NoesisStructs.h b/Source/NoesisRuntime/Classes/NoesisStructs.h index cacc8c1..d860780 100644 --- a/Source/NoesisRuntime/Classes/NoesisStructs.h +++ b/Source/NoesisRuntime/Classes/NoesisStructs.h @@ -28,7 +28,7 @@ struct FNoesisSize UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float Height; - FNoesisSize() {} + FNoesisSize() : Width(0.f), Height(0.f) {} FNoesisSize(const Noesis::Size& Size); @@ -52,7 +52,7 @@ struct FNoesisRect UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float Height; - FNoesisRect() {} + FNoesisRect() : X(0.f), Y(0.f), Width(0.f), Height(0.f) {} FNoesisRect(const Noesis::Rect& Rect); @@ -70,7 +70,7 @@ struct FNoesisPoint UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float Y; - FNoesisPoint() {} + FNoesisPoint() : X(0.f), Y(0.f) {} FNoesisPoint(const Noesis::Point& Point); @@ -94,7 +94,7 @@ struct FNoesisCornerRadius UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float BottomLeft; - FNoesisCornerRadius() {} + FNoesisCornerRadius() : TopLeft(0.f), TopRight(0.f), BottomRight(0.f), BottomLeft(0.f) {} FNoesisCornerRadius(const Noesis::CornerRadius& CornerRadius); @@ -118,7 +118,7 @@ struct FNoesisThickness UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float Bottom; - FNoesisThickness() {} + FNoesisThickness() : Left(0.f), Top(0.f), Right(0.f), Bottom(0.f) {} FNoesisThickness(const Noesis::Thickness& Thickness); @@ -142,7 +142,7 @@ struct FNoesisColor UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float Alpha; - FNoesisColor() {} + FNoesisColor() : Red(0.f), Green(0.f), Blue(0.f), Alpha(0.f) {} FNoesisColor(const Noesis::Color& Color); @@ -160,7 +160,7 @@ struct FNoesisSizei UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") int32 Height; - FNoesisSizei() {} + FNoesisSizei() : Width(0), Height(0) {} FNoesisSizei(const Noesis::Sizei& Size); @@ -184,7 +184,7 @@ struct FNoesisRecti UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") int32 Height; - FNoesisRecti() {} + FNoesisRecti() : X(0), Y(0), Width(0), Height(0) {} FNoesisRecti(const Noesis::Recti& Rect); @@ -202,7 +202,7 @@ struct FNoesisPointi UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") int32 Y; - FNoesisPointi() {} + FNoesisPointi() : X(0), Y(0) {} FNoesisPointi(const Noesis::Pointi& Point); @@ -220,7 +220,7 @@ struct FNoesisDuration UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") int32 Milliseconds; - FNoesisDuration() {} + FNoesisDuration() : DurationType(ENoesisDurationType::Automatic), Milliseconds(0) {} FNoesisDuration(const Noesis::Duration& Duration); @@ -295,7 +295,7 @@ struct FNoesisTimeSpan UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") int32 Milliseconds; - FNoesisTimeSpan() {} + FNoesisTimeSpan() : Days(0), Hours(0), Minutes(0), Seconds(0), Milliseconds(0) {} FNoesisTimeSpan(const Noesis::TimeSpan& TimeSpan); @@ -319,7 +319,7 @@ struct FNoesisManipulationDelta UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") FNoesisPoint Translation; - FNoesisManipulationDelta() {} + FNoesisManipulationDelta() : Expansion(), Rotation(0.f), Scale(0.f), Translation() {} FNoesisManipulationDelta(const Noesis::ManipulationDelta& ManipulationDelta); @@ -340,7 +340,7 @@ struct FNoesisManipulationVelocities UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") FNoesisPoint LinearVelocity; - FNoesisManipulationVelocities() {} + FNoesisManipulationVelocities() : AngularVelocity(0.f), ExpansionVelocity(), LinearVelocity() {} FNoesisManipulationVelocities(const Noesis::ManipulationVelocities& ManipulationVelocities); @@ -355,7 +355,7 @@ struct FNoesisInertiaExpansionBehavior UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float DesiredDeceleration; - FNoesisInertiaExpansionBehavior() {} + FNoesisInertiaExpansionBehavior() : DesiredDeceleration(0.f) {} FNoesisInertiaExpansionBehavior(const Noesis::InertiaExpansionBehavior& InertiaExpansionBehavior); @@ -370,7 +370,7 @@ struct FNoesisInertiaRotationBehavior UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float DesiredDeceleration; - FNoesisInertiaRotationBehavior() {} + FNoesisInertiaRotationBehavior() : DesiredDeceleration(0) {} FNoesisInertiaRotationBehavior(const Noesis::InertiaRotationBehavior& InertiaRotationBehavior); @@ -385,7 +385,7 @@ struct FNoesisInertiaTranslationBehavior UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") float DesiredDeceleration; - FNoesisInertiaTranslationBehavior() {} + FNoesisInertiaTranslationBehavior() : DesiredDeceleration(0) {} FNoesisInertiaTranslationBehavior(const Noesis::InertiaTranslationBehavior& InertiaTranslationBehavior); @@ -403,7 +403,7 @@ struct FNoesisGeneratorPosition UPROPERTY(BlueprintReadOnly, Category = "NoesisGUI") int32 Offset; - FNoesisGeneratorPosition() {} + FNoesisGeneratorPosition() : Index(0), Offset(0) {} FNoesisGeneratorPosition(const Noesis::GeneratorPosition& GeneratorPosition); diff --git a/Source/NoesisRuntime/NoesisRuntime.Build.cs b/Source/NoesisRuntime/NoesisRuntime.Build.cs index c27bc0a..f080f7f 100644 --- a/Source/NoesisRuntime/NoesisRuntime.Build.cs +++ b/Source/NoesisRuntime/NoesisRuntime.Build.cs @@ -38,7 +38,8 @@ public NoesisRuntime(ReadOnlyTargetRules Target) : base(Target) "InputCore", "UMG", "ApplicationCore", - "Slate" + "Slate", + "Projects" } ); diff --git a/Source/NoesisRuntime/Private/NoesisInstance.cpp b/Source/NoesisRuntime/Private/NoesisInstance.cpp index af734dc..a676163 100644 --- a/Source/NoesisRuntime/Private/NoesisInstance.cpp +++ b/Source/NoesisRuntime/Private/NoesisInstance.cpp @@ -9,15 +9,13 @@ #include "Stats/Stats.h" #include "Stats/Stats2.h" + // Engine includes #include "SceneUtils.h" // RenderCore includes #include "RenderingThread.h" -// UtilityShaders includes -#include "ClearQuad.h" - // ApplicationCore includes #include "HAL/PlatformApplicationMisc.h" #include "GenericPlatform/ITextInputMethodSystem.h" @@ -59,6 +57,7 @@ class FNoesisSlateElement : public ICustomSlateElement // End of ICustomSlateElement interface class UNoesisInstance* NoesisInstance; + FTexture2DRHIRef DepthStencilTarget; float Left; float Top; @@ -75,8 +74,27 @@ void FNoesisSlateElement::DrawRenderThread(FRHICommandListImmediate& RHICmdList, { if (NoesisInstance) { + FTexture2DRHIRef ColorTarget = *(FTexture2DRHIRef*)InWindowBackBuffer; + if (!DepthStencilTarget.IsValid() || DepthStencilTarget->GetSizeX() != ColorTarget->GetSizeX() || DepthStencilTarget->GetSizeY() != ColorTarget->GetSizeY() || DepthStencilTarget->GetNumSamples() != ColorTarget->GetNumSamples()) + { + DepthStencilTarget.SafeRelease(); + uint32 SizeX = ColorTarget->GetSizeX(); + uint32 SizeY = ColorTarget->GetSizeY(); + uint8 Format = (uint8)PF_DepthStencil; + uint32 NumMips = 1; + uint32 NumSamples = ColorTarget->GetNumSamples(); + uint32 TargetableTextureFlags = (uint32)TexCreate_DepthStencilTargetable; + FRHIResourceCreateInfo CreateInfo; + CreateInfo.ClearValueBinding = FClearValueBinding(0.f, 0); + DepthStencilTarget = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, NumSamples, TargetableTextureFlags, CreateInfo); + } + FRHIRenderTargetView ColorView(ColorTarget, 0, -1, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore); + FRHIDepthRenderTargetView DepthStencilView(DepthStencilTarget, ERenderTargetLoadAction::ENoAction, ERenderTargetStoreAction::ENoAction, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::ENoAction, + FExclusiveDepthStencil::DepthNop_StencilWrite); + FRHISetRenderTargetsInfo Info(1, &ColorView, DepthStencilView); + // Clear the stencil buffer + RHICmdList.SetRenderTargetsAndClear(Info); RHICmdList.SetViewport(Left, Top, 0.0f, Right, Bottom, 1.0f); - DrawClearQuad(RHICmdList, false, FLinearColor::Black, false, 0.0f, true, 0); NoesisInstance->Draw_RenderThread(RHICmdList, 0, 0); } } @@ -568,15 +586,7 @@ int32 UNoesisInstance::NativePaint(const FPaintArgs& Args, const FGeometry& Allo NoesisSlateElement->Top = MyClippingRect.Top; NoesisSlateElement->Right = MyClippingRect.Right; NoesisSlateElement->Bottom = MyClippingRect.Bottom; - // Push an unaligned clip zone to force Slate to create a stencil buffer - FVector2D TopLeft(MyClippingRect.Left - 1, MyClippingRect.Top - 1); - FVector2D TopRight(MyClippingRect.Right, MyClippingRect.Top); - FVector2D BottomLeft(MyClippingRect.Left, MyClippingRect.Bottom); - FVector2D BottomRight(MyClippingRect.Right + 1, MyClippingRect.Bottom + 1); - FSlateClippingZone Clip(TopLeft, TopRight, BottomLeft, BottomRight); - OutDrawElements.PushClip(Clip); FSlateDrawElement::MakeCustom(OutDrawElements, LayerId, NoesisSlateElement); - OutDrawElements.PopClip(); MaxLayer = FMath::Max(MaxLayer, LayerId); } diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp index 6fd5f01..81443aa 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp +++ b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp @@ -63,7 +63,9 @@ void FNoesisResourceProvider::ScanFolder(const char* InFolder) { for (auto TypefaceEntry : Font->CompositeFont.DefaultTypeface.Fonts) { - RegisterFont(InFolder, TypefaceEntry.Name.GetPlainANSIString()); + ANSICHAR TypefaceName[NAME_SIZE]; + TypefaceEntry.Name.GetPlainANSIString(TypefaceName); + RegisterFont(InFolder, TypefaceName); } } } @@ -75,7 +77,9 @@ Noesis::Ptr FNoesisResourceProvider::OpenFont(const char* InFold { for (auto TypefaceEntry : Font->CompositeFont.DefaultTypeface.Fonts) { - if (FCStringAnsi::Strcmp(TypefaceEntry.Name.GetPlainANSIString(), InFilename) == 0) + ANSICHAR TypefaceName[NAME_SIZE]; + TypefaceEntry.Name.GetPlainANSIString(TypefaceName); + if (FCStringAnsi::Strcmp(TypefaceName, InFilename) == 0) { const FFontData* FontData = &TypefaceEntry.Font; const UFontFace* FontFace = Cast(FontData->GetFontFaceAsset()); diff --git a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp index 96e112a..bcfc0bc 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp +++ b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp @@ -12,6 +12,9 @@ #include "Stats/Stats.h" #include "Stats/Stats2.h" +// ShaderCore includes +#include "ShaderCore.h" + // ApplicationCore includes #include "HAL/PlatformApplicationMisc.h" @@ -19,6 +22,9 @@ #include "Widgets/Input/IVirtualKeyboardEntry.h" #include "Framework/Application/SlateApplication.h" +// Projects includes +#include "Interfaces/IPluginManager.h" + // NoesisRuntime includes #include "NoesisResourceProvider.h" #include "Render/NoesisRenderDevice.h" @@ -218,6 +224,12 @@ class NoesisTextBoxVirtualKeyboardEntry : public IVirtualKeyboardEntry } } + virtual void SetSelectionFromVirtualKeyboard(int InSelStart, int SelEnd) override + { + TextBox->SetSelectionStart(InSelStart); + TextBox->SetSelectionLength(SelEnd - InSelStart); + } + virtual FText GetText() const override { return FText::FromString(InitialText); @@ -271,6 +283,10 @@ class NoesisPasswordBoxVirtualKeyboardEntry : public IVirtualKeyboardEntry } } + virtual void SetSelectionFromVirtualKeyboard(int InSelStart, int SelEnd) override + { + } + virtual FText GetText() const override { return FText::FromString(InitialText); @@ -387,6 +403,9 @@ class FNoesisRuntimeModule : public INoesisRuntimeModuleInterface PostEngineInitDelegateHandle = FCoreDelegates::OnPostEngineInit.AddStatic(OnPostEngineInit); NsGetKernel()->GetReflectionRegistry()->SetFallbackHandler(&NoesisReflectionRegistryCallback); + + FString PluginShaderDir = FPaths::Combine(IPluginManager::Get().FindPlugin(TEXT("NoesisGUI"))->GetBaseDir(), TEXT("Shaders")); + AddShaderSourceDirectoryMapping(TEXT("/Plugin/NoesisGUI"), PluginShaderDir); } virtual void ShutdownModule() override diff --git a/Source/NoesisRuntime/Private/NoesisTypeClass.cpp b/Source/NoesisRuntime/Private/NoesisTypeClass.cpp index 5d82642..038e471 100644 --- a/Source/NoesisRuntime/Private/NoesisTypeClass.cpp +++ b/Source/NoesisRuntime/Private/NoesisTypeClass.cpp @@ -56,6 +56,12 @@ class NoesisObjectWrapper; class NoesisStructWrapper; class NoesisEnumWrapper; +const char* GetPersistentName(FString Name) +{ + NsSymbol Symbol(TCHARToNsString(*Name)); + return Symbol.GetStr(); +} + FString RegisterNameFromPath(FString Path) { static FString ProjectName = FApp::GetProjectName(); @@ -2088,18 +2094,19 @@ Noesis::TypeClass* NoesisCreateTypeClassForUClass(UClass* Class) { ClassName = Class->GetPathName(); } - FName AnsiClassName(TCHARToNsString(*RegisterNameFromPath(ClassName)).c_str()); - RegisterNameMap.Add(AnsiClassName.ToString(), Class->GetPathName()); + FString AnsiClassName(TCHARToNsString(*RegisterNameFromPath(ClassName)).c_str()); + RegisterNameMap.Add(AnsiClassName, Class->GetPathName()); + const char* PersistentClassName = GetPersistentName(AnsiClassName); Noesis::TypeClass* TypeClass = nullptr; if (auto TypeClassPtr = ClassMap.Find(Class)) { - check(!FCStringAnsi::Strcmp(AnsiClassName.GetPlainANSIString(), TypeClassPtr->Value)); + check(!FCStringAnsi::Strcmp(PersistentClassName, TypeClassPtr->Value)); TypeClass = TypeClassPtr->Key; } if (!TypeClass) { - TypeClass = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(AnsiClassName.GetPlainANSIString()), &UClassTypeCreator, &UClassTypeFiller)); - ClassMap.Add(Class, MakeTuple(TypeClass, AnsiClassName.GetPlainANSIString())); + TypeClass = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentClassName), &UClassTypeCreator, &UClassTypeFiller)); + ClassMap.Add(Class, MakeTuple(TypeClass, PersistentClassName)); #if WITH_EDITOR if (UBlueprint* Blueprint = Cast(Class->ClassGeneratedBy)) @@ -2133,8 +2140,9 @@ void UEnumTypeFiller(Noesis::Type* Type) for (int32 Index = 0; Index != Enum->NumEnums(); ++Index) { const FString EnumValueName = Enum->GetDisplayNameTextByIndex(Index).ToString(); - FName AnsiEnumValueName(TCHARToNsString(*EnumValueName).c_str()); - TypeEnum->AddValue(NsSymbol(AnsiEnumValueName.GetPlainANSIString()), (int)Enum->GetValueByIndex(Index)); + FString AnsiEnumValueName(TCHARToNsString(*EnumValueName).c_str()); + const char* PersistentEnumValueName = GetPersistentName(AnsiEnumValueName); + TypeEnum->AddValue(NsSymbol(PersistentEnumValueName), (int)Enum->GetValueByIndex(Index)); } } @@ -2151,21 +2159,22 @@ Noesis::BaseComponent* CallbackCreateEnumConverter(NsSymbol Id) Noesis::TypeEnum* NoesisCreateTypeEnumForUEnum(UEnum* Enum) { FString EnumName = Enum->GetPathName(); - FName AnsiEnumName(TCHARToNsString(*RegisterNameFromPath(EnumName)).c_str()); - RegisterNameMap.Add(AnsiEnumName.ToString(), EnumName); + FString AnsiEnumName(TCHARToNsString(*RegisterNameFromPath(EnumName)).c_str()); + const char* PersistentEnumName = GetPersistentName(AnsiEnumName); + RegisterNameMap.Add(AnsiEnumName, EnumName); Noesis::TypeEnum* TypeEnum = nullptr; if (auto TypeEnumPtr = EnumMap.Find(Enum)) { - check(!FCStringAnsi::Strcmp(AnsiEnumName.GetPlainANSIString(), TypeEnumPtr->Value)); + check(!FCStringAnsi::Strcmp(PersistentEnumName, TypeEnumPtr->Value)); TypeEnum = TypeEnumPtr->Key; } if (!TypeEnum) { - TypeEnum = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(AnsiEnumName.GetPlainANSIString()), &UEnumTypeCreator, &UEnumTypeFiller)); + TypeEnum = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentEnumName), &UEnumTypeCreator, &UEnumTypeFiller)); NsSymbol EnumConverterId = Noesis::IdOf("Converter", TypeEnum); NsGetKernel()->GetComponentFactory()->RegisterComponent(EnumConverterId, NsSymbol::Null(), &CallbackCreateEnumConverter); - EnumMap.Add(Enum, MakeTuple(TypeEnum, AnsiEnumName.GetPlainANSIString())); + EnumMap.Add(Enum, MakeTuple(TypeEnum, PersistentEnumName)); ConverterIdMap.Add(EnumConverterId.GetId(), (NoesisTypeEnum*)TypeEnum); } @@ -2239,18 +2248,19 @@ void AssignStruct(void* BasePointer, UStructProperty* StructProperty, Noesis::Ba Noesis::TypeClass* NoesisCreateTypeClassForUStruct(UScriptStruct* Class) { FString ClassName = Class->GetPathName(); - FName AnsiClassName(TCHARToNsString(*RegisterNameFromPath(ClassName)).c_str()); - RegisterNameMap.Add(AnsiClassName.ToString(), ClassName); + FString AnsiClassName(TCHARToNsString(*RegisterNameFromPath(ClassName)).c_str()); + const char* PersistentClassName = GetPersistentName(AnsiClassName); + RegisterNameMap.Add(AnsiClassName, ClassName); Noesis::TypeClass* TypeClass = nullptr; if (auto TypeClassPtr = ClassMap.Find(Class)) { - check(!FCStringAnsi::Strcmp(AnsiClassName.GetPlainANSIString(), TypeClassPtr->Value)); + check(!FCStringAnsi::Strcmp(PersistentClassName, TypeClassPtr->Value)); TypeClass = TypeClassPtr->Key; } if (!TypeClass) { - TypeClass = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(AnsiClassName.GetPlainANSIString()), &UClassTypeCreator, &UStructTypeFiller)); - ClassMap.Add(Class, MakeTuple(TypeClass, AnsiClassName.GetPlainANSIString())); + TypeClass = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentClassName), &UClassTypeCreator, &UStructTypeFiller)); + ClassMap.Add(Class, MakeTuple(TypeClass, PersistentClassName)); } return TypeClass; From b473f17600cbf8290f82a2d3b2521f9bc6a27694 Mon Sep 17 00:00:00 2001 From: hcpizzi Date: Fri, 23 Nov 2018 18:35:06 +0100 Subject: [PATCH 14/20] Fixes to Renderer usage --- Source/NoesisRuntime/Classes/NoesisInstance.h | 4 +- .../NoesisRuntime/Private/NoesisInstance.cpp | 118 +++++++++++------- Source/NoesisRuntime/Private/NoesisXaml.cpp | 22 +--- 3 files changed, 76 insertions(+), 68 deletions(-) diff --git a/Source/NoesisRuntime/Classes/NoesisInstance.h b/Source/NoesisRuntime/Classes/NoesisInstance.h index dfdb324..6a70501 100644 --- a/Source/NoesisRuntime/Classes/NoesisInstance.h +++ b/Source/NoesisRuntime/Classes/NoesisInstance.h @@ -80,8 +80,6 @@ class NOESISRUNTIME_API UNoesisInstance : public UUserWidget void ExecuteConsoleCommand(FString Command, class APlayerController* SpecificPlayer); void Update(float InLeft, float InTop, float InWidth, float InHeight); - void DrawOffscreen_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIParamRef BackBuffer, FTexture2DRHIParamRef DepthStencilTarget); - void Draw_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIParamRef BackBuffer, FTexture2DRHIParamRef DepthStencilTarget); FVector2D GetSize() const; @@ -103,6 +101,8 @@ class NOESISRUNTIME_API UNoesisInstance : public UUserWidget // UWidget interface virtual void SetDesignerFlags(EWidgetDesignFlags::Type NewFlags) override; // End of UWidget interface + + void DrawThumbnail(FIntRect ViewportRect, const FTexture2DRHIRef& BackBuffer); #endif // WITH_EDITOR // UUserWidget interface diff --git a/Source/NoesisRuntime/Private/NoesisInstance.cpp b/Source/NoesisRuntime/Private/NoesisInstance.cpp index a676163..5f37960 100644 --- a/Source/NoesisRuntime/Private/NoesisInstance.cpp +++ b/Source/NoesisRuntime/Private/NoesisInstance.cpp @@ -50,29 +50,30 @@ DECLARE_CYCLE_STAT(TEXT("NoesisInstance::NativeOnMouseButtonDoubleClick"), STAT_ class FNoesisSlateElement : public ICustomSlateElement { public: - FNoesisSlateElement(class UNoesisInstance* InNoesisInstance); + FNoesisSlateElement(Noesis::Ptr InRenderer); // ICustomSlateElement interface virtual void DrawRenderThread(FRHICommandListImmediate& RHICmdList, const void* InWindowBackBuffer) override; // End of ICustomSlateElement interface - class UNoesisInstance* NoesisInstance; + Noesis::Ptr Renderer; FTexture2DRHIRef DepthStencilTarget; float Left; float Top; float Right; float Bottom; + bool FlipYAxis; }; -FNoesisSlateElement::FNoesisSlateElement(class UNoesisInstance* InNoesisInstance) - : NoesisInstance(InNoesisInstance) +FNoesisSlateElement::FNoesisSlateElement(Noesis::Ptr InRenderer) + : Renderer(InRenderer) { } void FNoesisSlateElement::DrawRenderThread(FRHICommandListImmediate& RHICmdList, const void* InWindowBackBuffer) { - if (NoesisInstance) + if (Renderer) { FTexture2DRHIRef ColorTarget = *(FTexture2DRHIRef*)InWindowBackBuffer; if (!DepthStencilTarget.IsValid() || DepthStencilTarget->GetSizeX() != ColorTarget->GetSizeX() || DepthStencilTarget->GetSizeY() != ColorTarget->GetSizeY() || DepthStencilTarget->GetNumSamples() != ColorTarget->GetNumSamples()) @@ -95,7 +96,11 @@ void FNoesisSlateElement::DrawRenderThread(FRHICommandListImmediate& RHICmdList, // Clear the stencil buffer RHICmdList.SetRenderTargetsAndClear(Info); RHICmdList.SetViewport(Left, Top, 0.0f, Right, Bottom, 1.0f); - NoesisInstance->Draw_RenderThread(RHICmdList, 0, 0); + SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_Draw); + SCOPED_DRAW_EVENT(RHICmdList, NoesisDraw); + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); + Renderer->Render(FlipYAxis); + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); } } @@ -267,8 +272,17 @@ void UNoesisInstance::InitInstance() if (XamlView) { - Noesis::IRenderer* Renderer = XamlView->GetRenderer(); - Renderer->Init(FNoesisRenderDevice::Get()); + Noesis::Ptr Renderer(XamlView->GetRenderer()); + + ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FNoesisInstance_InitRenderer, + Noesis::Ptr, Renderer, Renderer, + { + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); + Renderer->Init(FNoesisRenderDevice::Get()); + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); + }); + + NoesisSlateElement = MakeShared(Renderer); StartTime = GetTimeSeconds(); @@ -277,8 +291,6 @@ void UNoesisInstance::InitInstance() Xaml->PreviewGotKeyboardFocus() += Noesis::MakeDelegate(this, &UNoesisInstance::OnPreviewGotKeyboardFocus); Xaml->PreviewLostKeyboardFocus() += Noesis::MakeDelegate(this, &UNoesisInstance::OnPreviewLostKeyboardFocus); - - NoesisSlateElement = MakeShared(this); } } @@ -364,36 +376,6 @@ void UNoesisInstance::Update(float InLeft, float InTop, float InWidth, float InH } } -void UNoesisInstance::DrawOffscreen_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIParamRef BackBuffer, FTexture2DRHIParamRef DepthStencilTarget) -{ - SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_DrawOffscreen); - if (XamlView) - { - SCOPED_DRAW_EVENT(RHICmdList, NoesisDrawOffscreen); - FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); - Noesis::IRenderer* Renderer = XamlView->GetRenderer(); - Renderer->UpdateRenderTree(); - if (Renderer->NeedsOffscreen()) - { - Renderer->RenderOffscreen(); - } - FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); - } -} - -void UNoesisInstance::Draw_RenderThread(FRHICommandListImmediate& RHICmdList, FTexture2DRHIParamRef BackBuffer, FTexture2DRHIParamRef DepthStencilTarget) -{ - SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_Draw); - if (XamlView) - { - SCOPED_DRAW_EVENT(RHICmdList, NoesisDraw); - FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); - Noesis::IRenderer* Renderer = XamlView->GetRenderer(); - Renderer->Render(FlipYAxis); - FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); - } -} - FVector2D UNoesisInstance::GetSize() const { if (Xaml) @@ -498,17 +480,18 @@ void UNoesisInstance::TermInstance() { if (XamlView) { - Noesis::IRenderer* Renderer = XamlView->GetRenderer(); - Renderer->Shutdown(); + Noesis::Ptr Renderer(XamlView->GetRenderer()); XamlView.Reset(); Xaml.Reset(); // Pass the slate element to the render thread so that it's deleted after it's shown for the last time - ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER + ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER ( SafeDeleteNoesisSlateElement, + Noesis::Ptr, Renderer, Renderer, FNoesisSlateElementPtr, NoesisSlateElement, NoesisSlateElement, { + Renderer->Shutdown(); NoesisSlateElement.Reset(); } ); @@ -555,6 +538,40 @@ void UNoesisInstance::SetDesignerFlags(EWidgetDesignFlags::Type NewFlags) // Enable native events in editor Super::SetDesignerFlags((EWidgetDesignFlags::Type)(NewFlags & ~EWidgetDesignFlags::Designing)); } + +void UNoesisInstance::DrawThumbnail(FIntRect ViewportRect, const FTexture2DRHIRef& BackBuffer) +{ + Update(ViewportRect.Min.X, ViewportRect.Min.Y, ViewportRect.Max.X - ViewportRect.Min.X, ViewportRect.Max.Y - ViewportRect.Min.Y); + + Noesis::Ptr Renderer(XamlView->GetRenderer()); + + ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER( + FNoesisXamlThumbnailRendererDrawCommand, + Noesis::Ptr, Renderer, Renderer, + bool, FlipYAxis, FlipYAxis, + const FTexture2DRHIRef&, BackBuffer, BackBuffer, + { + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); + Renderer->UpdateRenderTree(); + if (Renderer->NeedsOffscreen()) + { + Renderer->RenderOffscreen(); + } + + uint32 SizeX = BackBuffer->GetSizeX(); + uint32 SizeY = BackBuffer->GetSizeY(); + uint8 Format = (uint8)PF_DepthStencil; + uint32 NumMips = BackBuffer->GetNumMips(); + uint32 NumSamples = BackBuffer->GetNumSamples(); + uint32 TargetableTextureFlags = (uint32)TexCreate_DepthStencilTargetable; + FRHIResourceCreateInfo CreateInfo; + CreateInfo.ClearValueBinding = FClearValueBinding(0.f, 0); + FTexture2DRHIRef DepthStencilTarget = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, NumSamples, TargetableTextureFlags, CreateInfo); + SetRenderTarget(RHICmdList, BackBuffer, DepthStencilTarget); + Renderer->Render(FlipYAxis); + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); + }); +} #endif // WITH_EDITOR void UNoesisInstance::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) @@ -574,10 +591,20 @@ int32 UNoesisInstance::NativePaint(const FPaintArgs& Args, const FGeometry& Allo if (XamlView) { + Noesis::Ptr Renderer(XamlView->GetRenderer()); + ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FNoesisInstance_DrawOffscreen, - UNoesisInstance*, NoesisInstance, (UNoesisInstance*)this, + Noesis::Ptr, Renderer, Renderer, { - NoesisInstance->DrawOffscreen_RenderThread(RHICmdList, 0, 0); + SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_DrawOffscreen); + SCOPED_DRAW_EVENT(RHICmdList, NoesisDrawOffscreen); + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); + Renderer->UpdateRenderTree(); + if (Renderer->NeedsOffscreen()) + { + Renderer->RenderOffscreen(); + } + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); }); const FSlateRect& MyClippingRect = MyCullingRect; @@ -586,6 +613,7 @@ int32 UNoesisInstance::NativePaint(const FPaintArgs& Args, const FGeometry& Allo NoesisSlateElement->Top = MyClippingRect.Top; NoesisSlateElement->Right = MyClippingRect.Right; NoesisSlateElement->Bottom = MyClippingRect.Bottom; + NoesisSlateElement->FlipYAxis = FlipYAxis; FSlateDrawElement::MakeCustom(OutDrawElements, LayerId, NoesisSlateElement); MaxLayer = FMath::Max(MaxLayer, LayerId); diff --git a/Source/NoesisRuntime/Private/NoesisXaml.cpp b/Source/NoesisRuntime/Private/NoesisXaml.cpp index ce8b3ec..3bd83ab 100644 --- a/Source/NoesisRuntime/Private/NoesisXaml.cpp +++ b/Source/NoesisRuntime/Private/NoesisXaml.cpp @@ -121,27 +121,7 @@ void UNoesisXaml::RenderThumbnail(FIntRect ViewportRect, const FTexture2DRHIRef& if (ThumbnailRenderInstance) { - ThumbnailRenderInstance->Update(ViewportRect.Min.X, ViewportRect.Min.Y, ViewportRect.Max.X - ViewportRect.Min.X, ViewportRect.Max.Y - ViewportRect.Min.Y); - - ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER( - FNoesisXamlThumbnailRendererDrawCommand, - UNoesisInstance*, NoesisInstance, ThumbnailRenderInstance, - const FTexture2DRHIRef&, BackBuffer, BackBuffer, - { - NoesisInstance->DrawOffscreen_RenderThread(RHICmdList, 0, 0); - - uint32 SizeX = BackBuffer->GetSizeX(); - uint32 SizeY = BackBuffer->GetSizeY(); - uint8 Format = (uint8)PF_DepthStencil; - uint32 NumMips = BackBuffer->GetNumMips(); - uint32 NumSamples = BackBuffer->GetNumSamples(); - uint32 TargetableTextureFlags = (uint32)TexCreate_DepthStencilTargetable; - FRHIResourceCreateInfo CreateInfo; - CreateInfo.ClearValueBinding = FClearValueBinding(0.f, 0); - FTexture2DRHIRef DepthStencilTarget = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, NumSamples, TargetableTextureFlags, CreateInfo); - SetRenderTarget(RHICmdList, BackBuffer, DepthStencilTarget); - NoesisInstance->Draw_RenderThread(RHICmdList, BackBuffer, DepthStencilTarget); - }); + ThumbnailRenderInstance->DrawThumbnail(ViewportRect, BackBuffer); } } From 5af541f218d93c86eb8ef9c32a3df3d1173d9d77 Mon Sep 17 00:00:00 2001 From: GeorgeR Date: Sun, 6 Jan 2019 22:52:17 +1100 Subject: [PATCH 15/20] fun stuff --- .../Private/NoesisXamlFactory.cpp | 13 +++++- .../Private/NoesisResourceProvider.cpp | 43 +++++++++++++++++-- .../NoesisResourceProvider.h | 12 ++++++ 3 files changed, 63 insertions(+), 5 deletions(-) rename Source/NoesisRuntime/{Private => Public}/NoesisResourceProvider.h (79%) diff --git a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp index c220d8c..c138d50 100644 --- a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp +++ b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp @@ -12,6 +12,8 @@ #include "NoesisEditorModule.h" #include "NoesisEditorUserSettings.h" +#include "NoesisResourceProvider.h" + UNoesisXamlFactory::UNoesisXamlFactory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { @@ -132,6 +134,7 @@ void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, UPackage* XamlPackage = NULL; FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; + XamlObjectPath = FNoesisResourceProvider::ProcessPath(XamlObjectPath, EResourceType::RT_Xaml); UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); if (!ExistingXaml) @@ -267,10 +270,12 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, if (SubFace->family_name && FCStringAnsi::Strcmp(SubFace->family_name, StringCast(*FamilyName).Get()) == 0) { FString FontFaceName = ObjectTools::SanitizeObjectName(FPaths::GetBaseFilename(FPaths::GetBaseFilename(FilenameOrDirectory))); + FontFaceName = "FF_" + FontFaceName; UPackage* FontFacePackage = NULL; FString FontFaceObjectPath = FontPackagePath / FontFaceName + TEXT(".") + FontFaceName; + FontFaceObjectPath = FNoesisResourceProvider::ProcessPath(FontFaceObjectPath, EResourceType::RT_FontFace); UFontFace* ExistingFontFace = LoadObject(NULL, *FontFaceObjectPath); if (!ExistingFontFace) @@ -341,8 +346,10 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, { UPackage* FontPackage = NULL; - FString FontName = ObjectTools::SanitizeObjectName(FamilyName + TEXT("_Font")); + //FString FontName = ObjectTools::SanitizeObjectName(FamilyName + TEXT("_Font")); + FString FontName = "F_" + ObjectTools::SanitizeObjectName(FamilyName); FString FontObjectPath = FontPackagePath / FontName + TEXT(".") + FontName; + FontObjectPath = FNoesisResourceProvider::ProcessPath(FontObjectPath, EResourceType::RT_Font); UFont* ExistingFont = LoadObject(NULL, *FontObjectPath); if (!ExistingFont) @@ -427,9 +434,12 @@ void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, FString TextureName; ExtractPaths(ImagePath, Path, BasePackageName, ProjectURIRoot, TexturePath, FileName, PackagePath, TextureName); + TextureName = "T_" + TextureName; + UPackage* TexturePackage = NULL; FString TextureObjectPath = PackagePath / TextureName + TEXT(".") + TextureName; + TextureObjectPath = FNoesisResourceProvider::ProcessPath(TextureObjectPath, EResourceType::RT_Texture); UTexture2D* ExistingTexture = LoadObject(NULL, *TextureObjectPath); if (!ExistingTexture) @@ -561,6 +571,7 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, UPackage* XamlPackage = NULL; FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; + XamlObjectPath = FNoesisResourceProvider::ProcessPath(XamlObjectPath, EResourceType::RT_Xaml); UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); if (!ExistingXaml) diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp index 81443aa..caa1a4d 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp +++ b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp @@ -20,7 +20,7 @@ UNoesisXaml* FNoesisResourceProvider::GetXaml(FString XamlPath) { - return LoadObject(nullptr, XamlPath[0] == TEXT('/') ? *XamlPath : *(FString(TEXT("/")) + XamlPath)); + return LoadObject(nullptr, *ProcessPath(TCHAR_TO_ANSI(*XamlPath), EResourceType::RT_Xaml)); } Noesis::Ptr FNoesisResourceProvider::LoadXaml(const char* Path) @@ -36,7 +36,7 @@ Noesis::Ptr FNoesisResourceProvider::LoadXaml(const char* Path) UTexture2D* FNoesisResourceProvider::GetTexture(FString TexturePath) { - return LoadObject(nullptr, TexturePath[0] == TEXT('/') ? *TexturePath : *(FString(TEXT("/")) + TexturePath)); + return LoadObject(nullptr, *ProcessPath(TCHAR_TO_ANSI(*TexturePath), EResourceType::RT_Texture)); } Noesis::TextureInfo FNoesisResourceProvider::GetTextureInfo(const char* Path) @@ -58,7 +58,7 @@ Noesis::Ptr FNoesisResourceProvider::LoadTexture(const char* Pa void FNoesisResourceProvider::ScanFolder(const char* InFolder) { - UFont* Font = LoadObject(nullptr, InFolder[0] == '/' ? *NsStringToFString(InFolder) : *(FString(TEXT("/")) + NsStringToFString(InFolder))); + UFont* Font = LoadObject(nullptr, *ProcessPath(InFolder, EResourceType::RT_Font)); if (Font) { for (auto TypefaceEntry : Font->CompositeFont.DefaultTypeface.Fonts) @@ -72,7 +72,7 @@ void FNoesisResourceProvider::ScanFolder(const char* InFolder) Noesis::Ptr FNoesisResourceProvider::OpenFont(const char* InFolder, const char* InFilename) const { - UFont* Font = LoadObject(nullptr, InFolder[0] == '/' ? *NsStringToFString(InFolder) : *(FString(TEXT("/")) + NsStringToFString(InFolder))); + UFont* Font = LoadObject(nullptr, *ProcessPath(InFolder, EResourceType::RT_Font)); if (Font) { for (auto TypefaceEntry : Font->CompositeFont.DefaultTypeface.Fonts) @@ -113,3 +113,38 @@ Noesis::Ptr FNoesisResourceProvider::OpenFont(const char* InFold } return Noesis::Ptr(); } + +FString FNoesisResourceProvider::ProcessPath(const char* Path, EResourceType ResourceType) +{ + FString Result = NsStringToFString(Path); + + auto BasePath = FPaths::GetPath(Result); + BasePath = BasePath[0] == '/' ? BasePath : "/" + BasePath; + BasePath += "/"; + + auto FileName = FPaths::GetBaseFilename(Result); + Result = BasePath + FileName + "." + FileName; + + /* NOTE: This is surely sub-optimal */ + auto LoadedObject = LoadObject(nullptr, *Result); + if (LoadedObject == nullptr) + { + if (ResourceType == EResourceType::RT_FontFace) + FileName = "FF_" + FileName; + else if (ResourceType == EResourceType::RT_Font) + FileName = "F_" + FileName; + else if (ResourceType == EResourceType::RT_Texture) + FileName = "T_" + FileName; + else if (ResourceType == EResourceType::RT_Xaml) + FileName = "XAML_" + FileName; + + Result = BasePath + FileName + "." + FileName; + } + + return Result; +} + +FString FNoesisResourceProvider::ProcessPath(const FString& Path, EResourceType ResourceType /*= EResourceType::RT_Unknown*/) +{ + return ProcessPath(TCHAR_TO_ANSI(*Path), ResourceType); +} diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.h b/Source/NoesisRuntime/Public/NoesisResourceProvider.h similarity index 79% rename from Source/NoesisRuntime/Private/NoesisResourceProvider.h rename to Source/NoesisRuntime/Public/NoesisResourceProvider.h index cae5e7e..67f6a7b 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.h +++ b/Source/NoesisRuntime/Public/NoesisResourceProvider.h @@ -11,6 +11,15 @@ // Noesis includes #include "NoesisSDK.h" +enum class EResourceType +{ + RT_Unknown = 0, + RT_FontFace, + RT_Font, + RT_Texture, + RT_Xaml +}; + class FNoesisResourceProvider : public Noesis::XamlProvider, public Noesis::TextureProvider, public Noesis::CachedFontProvider { public: @@ -31,4 +40,7 @@ class FNoesisResourceProvider : public Noesis::XamlProvider, public Noesis::Text virtual void ScanFolder(const char* Folder) override; virtual Noesis::Ptr OpenFont(const char* Folder, const char* Filename) const override; // End of CachedFontProvider interface + + NOESISRUNTIME_API static FString ProcessPath(const FString& Path, EResourceType ResourceType = EResourceType::RT_Unknown); + NOESISRUNTIME_API static FString ProcessPath(const char* Path, EResourceType ResourceType = EResourceType::RT_Unknown); }; From b6eb8635823463217a9d4f0d65419819e16bbab9 Mon Sep 17 00:00:00 2001 From: GeorgeR Date: Tue, 8 Jan 2019 19:42:39 +1100 Subject: [PATCH 16/20] added resource resolver for user defined resource path resolution --- .../NoesisEditor/Classes/NoesisXamlFactory.h | 29 ++++++++++- .../Private/NoesisXamlFactory.cpp | 50 +++++++++---------- .../Classes/NoesisResourceResolver.h | 38 ++++++++++++++ Source/NoesisRuntime/Classes/NoesisSettings.h | 12 +++++ .../Private/NoesisResourceProvider.cpp | 22 ++++++-- .../Private/NoesisResourceProvider.h | 5 ++ .../Private/NoesisResourceResolver.cpp | 22 ++++++++ .../NoesisRuntime/Private/NoesisSettings.cpp | 18 +++++++ 8 files changed, 165 insertions(+), 31 deletions(-) create mode 100644 Source/NoesisRuntime/Classes/NoesisResourceResolver.h create mode 100644 Source/NoesisRuntime/Private/NoesisResourceResolver.cpp diff --git a/Source/NoesisEditor/Classes/NoesisXamlFactory.h b/Source/NoesisEditor/Classes/NoesisXamlFactory.h index 397e0a5..b9a99db 100644 --- a/Source/NoesisEditor/Classes/NoesisXamlFactory.h +++ b/Source/NoesisEditor/Classes/NoesisXamlFactory.h @@ -8,12 +8,39 @@ // Generated header include #include "NoesisXamlFactory.generated.h" +class UNoesisResourceResolver; + +struct FXamlDescriptor +{ + FString Path; + UNoesisXaml* Xaml; +}; + +struct FFontDescriptor +{ + FString Family; + UFont* Font; +}; + +struct FImageDescriptor +{ + FString Path; + UTexture2D* Texture; +}; + UCLASS() class NOESISEDITOR_API UNoesisXamlFactory : public UFactory { GENERATED_UCLASS_BODY() // UFactory interface - virtual UObject* FactoryCreateBinary(UClass* Class, UObject* Parent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn) override; + virtual UObject* FactoryCreateBinary(UClass* Class, UObject* Parent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn) override; // End of UFactory interface + +protected: + void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& XamlDescriptors); + void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& FontDescriptors); + void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& ImageDescriptors); + + UNoesisResourceResolver* GetResourceResolver(); }; diff --git a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp index c220d8c..f6383ca 100644 --- a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp +++ b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp @@ -11,6 +11,8 @@ // NoesisEditor includes #include "NoesisEditorModule.h" #include "NoesisEditorUserSettings.h" +#include "NoesisSettings.h" +#include "NoesisResourceResolver.h" UNoesisXamlFactory::UNoesisXamlFactory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) @@ -95,12 +97,6 @@ TArray ScanKeyword(FString Text, FString Keyword) return Strings; } -struct FXamlDescriptor -{ - FString Path; - UNoesisXaml* Xaml; -}; - TArray ParseForXamls(FString XamlText) { TArray XamlDescriptors; @@ -115,7 +111,7 @@ TArray ParseForXamls(FString XamlText) return XamlDescriptors; } -void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& XamlDescriptors) +void UNoesisXamlFactory::ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& XamlDescriptors) { auto XamlFact = NewObject(); XamlFact->AddToRoot(); @@ -128,10 +124,10 @@ void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, FString XamlName; ExtractPaths(XamlDescriptor.Path, Path, BasePackageName, ProjectURIRoot, XamlPath, FileName, PackagePath, XamlName); - UPackage* XamlPackage = NULL; FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; + XamlObjectPath = GetResourceResolver()->ResolvePath(XamlObjectPath, ENoesisResourceType::NRT_Xaml); UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); if (!ExistingXaml) @@ -167,12 +163,6 @@ void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, XamlFact->RemoveFromRoot(); } -struct FFontDescriptor -{ - FString Family; - UFont* Font; -}; - TArray ParseForFonts(FString XamlText) { TArray FontDescriptors; @@ -195,7 +185,7 @@ unsigned long StreamRead(FT_Stream Stream, unsigned long Offset, unsigned char* void StreamClose(FT_Stream) {} -void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& FontDescriptors) +void UNoesisXamlFactory::ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& FontDescriptors) { TSet UniqueFontFamilies; for (auto FontDescriptor : FontDescriptors) @@ -219,9 +209,10 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, FString FamilyName; TArray Fonts; FT_Library FTLibrary; + UNoesisResourceResolver* ResourceResolver; - ScanFolderForFonts(FString InFontPackagePath, FString InFamilyName) - : FontPackagePath(InFontPackagePath), FamilyName(InFamilyName) + ScanFolderForFonts(FString InFontPackagePath, FString InFamilyName, UNoesisResourceResolver* InResourceResolver) + : FontPackagePath(InFontPackagePath), FamilyName(InFamilyName), ResourceResolver(InResourceResolver) { int32 Error = FT_Init_FreeType(&FTLibrary); checkf(Error == 0, TEXT("Could not init Freetype")); @@ -230,6 +221,7 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, ~ScanFolderForFonts() { FT_Done_FreeType(FTLibrary); + ResourceResolver = nullptr; } virtual bool Visit(const TCHAR* FilenameOrDirectory, bool IsDirectory) override @@ -267,10 +259,12 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, if (SubFace->family_name && FCStringAnsi::Strcmp(SubFace->family_name, StringCast(*FamilyName).Get()) == 0) { FString FontFaceName = ObjectTools::SanitizeObjectName(FPaths::GetBaseFilename(FPaths::GetBaseFilename(FilenameOrDirectory))); + FontFaceName = "FF_" + FontFaceName; UPackage* FontFacePackage = NULL; FString FontFaceObjectPath = FontPackagePath / FontFaceName + TEXT(".") + FontFaceName; + FontFaceObjectPath = ResourceResolver->ResolvePath(FontFaceObjectPath, ENoesisResourceType::NRT_FontFace); UFontFace* ExistingFontFace = LoadObject(NULL, *FontFaceObjectPath); if (!ExistingFontFace) @@ -334,15 +328,16 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, FString FontPackageName; ExtractPaths(BaseUri, Path, BasePackageName, ProjectURIRoot, FontFilePath, FontFileName, FontPackagePath, FontPackageName); - ScanFolderForFonts Visitor(FontPackagePath, FamilyName); + ScanFolderForFonts Visitor(FontPackagePath, FamilyName, GetResourceResolver()); PlatformFile.IterateDirectory(*FontFilePath, Visitor); if (Visitor.Fonts.Num()) { UPackage* FontPackage = NULL; - FString FontName = ObjectTools::SanitizeObjectName(FamilyName + TEXT("_Font")); + FString FontName = GetResourceResolver()->ResolveName(FamilyName, ENoesisResourceType::NRT_Font); FString FontObjectPath = FontPackagePath / FontName + TEXT(".") + FontName; + FontObjectPath = GetResourceResolver()->ResolvePath(FontObjectPath, ENoesisResourceType::NRT_Font); UFont* ExistingFont = LoadObject(NULL, *FontObjectPath); if (!ExistingFont) @@ -378,12 +373,6 @@ void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, } } -struct FImageDescriptor -{ - FString Path; - UTexture2D* Texture; -}; - TArray ParseForImages(FString XamlText) { TArray ImageDescriptors; @@ -406,7 +395,7 @@ TArray ParseForImages(FString XamlText) return ImageDescriptors; } -void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& ImageDescriptors) +void UNoesisXamlFactory::ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& ImageDescriptors) { auto TextureFact = NewObject(); TextureFact->AddToRoot(); @@ -427,9 +416,12 @@ void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, FString TextureName; ExtractPaths(ImagePath, Path, BasePackageName, ProjectURIRoot, TexturePath, FileName, PackagePath, TextureName); + TextureName = "T_" + TextureName; + UPackage* TexturePackage = NULL; FString TextureObjectPath = PackagePath / TextureName + TEXT(".") + TextureName; + TextureObjectPath = GetResourceResolver()->ResolvePath(TextureObjectPath, ENoesisResourceType::NRT_Texture); UTexture2D* ExistingTexture = LoadObject(NULL, *TextureObjectPath); if (!ExistingTexture) @@ -561,6 +553,7 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, UPackage* XamlPackage = NULL; FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; + XamlObjectPath = GetResourceResolver()->ResolvePath(XamlObjectPath, ENoesisResourceType::NRT_Xaml); UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); if (!ExistingXaml) @@ -625,3 +618,8 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, return NoesisXaml; } + +UNoesisResourceResolver* UNoesisXamlFactory::GetResourceResolver() +{ + return GetMutableDefault()->GetResourceResolver(); +} diff --git a/Source/NoesisRuntime/Classes/NoesisResourceResolver.h b/Source/NoesisRuntime/Classes/NoesisResourceResolver.h new file mode 100644 index 0000000..fce7416 --- /dev/null +++ b/Source/NoesisRuntime/Classes/NoesisResourceResolver.h @@ -0,0 +1,38 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NoesisGUI - http://www.noesisengine.com +// Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved. +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Core includes +#include "CoreMinimal.h" + +// Noesis includes +#include "NoesisSDK.h" + +// Generated header include +#include "NoesisResourceResolver.generated.h" + +UENUM() +enum class ENoesisResourceType : uint8 +{ + NRT_Unknown = 0, + NRT_FontFace, + NRT_Font, + NRT_Texture, + NRT_Xaml +}; + +UCLASS(BlueprintType, Blueprintable) +class NOESISRUNTIME_API UNoesisResourceResolver : public UObject +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, BlueprintPure) + virtual FString ResolveName(const FString& Name, const ENoesisResourceType ResourceType = ENoesisResourceType::NRT_Unknown) const; + + UFUNCTION(BlueprintCallable, BlueprintPure) + virtual FString ResolvePath(const FString& Path, const ENoesisResourceType ResourceType = ENoesisResourceType::NRT_Unknown) const; +}; diff --git a/Source/NoesisRuntime/Classes/NoesisSettings.h b/Source/NoesisRuntime/Classes/NoesisSettings.h index 4255ad1..55fdc02 100644 --- a/Source/NoesisRuntime/Classes/NoesisSettings.h +++ b/Source/NoesisRuntime/Classes/NoesisSettings.h @@ -14,6 +14,8 @@ // Generated header include #include "NoesisSettings.generated.h" +class UNoesisResourceResolver; + UENUM() enum class ENoesisOffscreenSampleCount : uint8 { @@ -84,4 +86,14 @@ class NOESISRUNTIME_API UNoesisSettings : public UObject /** Restores the color of UI PNG texture texels with an alpha value of zero. */ UPROPERTY(EditAnywhere, Config, Category = "Editor Settings", DisplayName = "Fix for premultiplied alpha UI textures") bool RestoreUITexturePNGPremultipliedAlpha; + + /** A custom resource resolver */ + UPROPERTY(EditAnywhere, Config, Category = "Noesis Settings") + TSoftClassPtr ResourceResolverClass; + + UNoesisResourceResolver* GetResourceResolver(); + +protected: + UPROPERTY() + UNoesisResourceResolver* ResourceResolverInstance; }; diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp index 81443aa..235f43d 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp +++ b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp @@ -17,10 +17,13 @@ // NoesisRuntime includes #include "NoesisXaml.h" #include "NoesisSupport.h" +#include "NoesisResourceResolver.h" UNoesisXaml* FNoesisResourceProvider::GetXaml(FString XamlPath) { - return LoadObject(nullptr, XamlPath[0] == TEXT('/') ? *XamlPath : *(FString(TEXT("/")) + XamlPath)); + FString Path = XamlPath[0] == TEXT('/') ? *XamlPath : *(FString(TEXT("/")) + XamlPath); + Path = GetResourceResolver()->ResolvePath(Path, ENoesisResourceType::NRT_Xaml); + return LoadObject(nullptr, *Path); } Noesis::Ptr FNoesisResourceProvider::LoadXaml(const char* Path) @@ -36,7 +39,9 @@ Noesis::Ptr FNoesisResourceProvider::LoadXaml(const char* Path) UTexture2D* FNoesisResourceProvider::GetTexture(FString TexturePath) { - return LoadObject(nullptr, TexturePath[0] == TEXT('/') ? *TexturePath : *(FString(TEXT("/")) + TexturePath)); + FString Path = TexturePath[0] == TEXT('/') ? *TexturePath : *(FString(TEXT("/")) + TexturePath); + Path = GetResourceResolver()->ResolvePath(Path, ENoesisResourceType::NRT_Texture); + return LoadObject(nullptr, *Path); } Noesis::TextureInfo FNoesisResourceProvider::GetTextureInfo(const char* Path) @@ -58,7 +63,9 @@ Noesis::Ptr FNoesisResourceProvider::LoadTexture(const char* Pa void FNoesisResourceProvider::ScanFolder(const char* InFolder) { - UFont* Font = LoadObject(nullptr, InFolder[0] == '/' ? *NsStringToFString(InFolder) : *(FString(TEXT("/")) + NsStringToFString(InFolder))); + FString Path = InFolder[0] == '/' ? *NsStringToFString(InFolder) : *(FString(TEXT("/")) + NsStringToFString(InFolder)); + Path = GetResourceResolver()->ResolvePath(Path, ENoesisResourceType::NRT_Font); + UFont* Font = LoadObject(nullptr, *Path); if (Font) { for (auto TypefaceEntry : Font->CompositeFont.DefaultTypeface.Fonts) @@ -72,7 +79,9 @@ void FNoesisResourceProvider::ScanFolder(const char* InFolder) Noesis::Ptr FNoesisResourceProvider::OpenFont(const char* InFolder, const char* InFilename) const { - UFont* Font = LoadObject(nullptr, InFolder[0] == '/' ? *NsStringToFString(InFolder) : *(FString(TEXT("/")) + NsStringToFString(InFolder))); + FString Path = InFolder[0] == '/' ? *NsStringToFString(InFolder) : *(FString(TEXT("/")) + NsStringToFString(InFolder)); + Path = GetResourceResolver()->ResolvePath(Path, ENoesisResourceType::NRT_Font); + UFont* Font = LoadObject(nullptr, *Path); if (Font) { for (auto TypefaceEntry : Font->CompositeFont.DefaultTypeface.Fonts) @@ -113,3 +122,8 @@ Noesis::Ptr FNoesisResourceProvider::OpenFont(const char* InFold } return Noesis::Ptr(); } + +UNoesisResourceResolver* FNoesisResourceProvider::GetResourceResolver() const +{ + return GetMutableDefault()->GetResourceResolver(); +} diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.h b/Source/NoesisRuntime/Private/NoesisResourceProvider.h index cae5e7e..06df357 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.h +++ b/Source/NoesisRuntime/Private/NoesisResourceProvider.h @@ -8,6 +8,8 @@ // Core includes #include "CoreMinimal.h" +class UNoesisResourceResolver; + // Noesis includes #include "NoesisSDK.h" @@ -31,4 +33,7 @@ class FNoesisResourceProvider : public Noesis::XamlProvider, public Noesis::Text virtual void ScanFolder(const char* Folder) override; virtual Noesis::Ptr OpenFont(const char* Folder, const char* Filename) const override; // End of CachedFontProvider interface + +protected: + UNoesisResourceResolver* GetResourceResolver() const; }; diff --git a/Source/NoesisRuntime/Private/NoesisResourceResolver.cpp b/Source/NoesisRuntime/Private/NoesisResourceResolver.cpp new file mode 100644 index 0000000..0eb0eca --- /dev/null +++ b/Source/NoesisRuntime/Private/NoesisResourceResolver.cpp @@ -0,0 +1,22 @@ +#include "NoesisResourceResolver.h" + +#if WITH_EDITOR +#include "ObjectTools.h" +#endif + +FString UNoesisResourceResolver::ResolveName(const FString& Name, const ENoesisResourceType ResourceType /*= ENoesisResourceType::NRT_Unknown*/) const +{ +#if WITH_EDITOR + if (ResourceType == ENoesisResourceType::NRT_Font) + return ObjectTools::SanitizeObjectName(Name + TEXT("_Font")); +#endif + + return Name; +} + +FString UNoesisResourceResolver::ResolvePath(const FString& Path, const ENoesisResourceType ResourceType /*= ENoesisResourceType::NRT_Unknown*/) const +{ + // Do nothing for default implementation + return Path; +} + diff --git a/Source/NoesisRuntime/Private/NoesisSettings.cpp b/Source/NoesisRuntime/Private/NoesisSettings.cpp index 1208d9f..ec6970e 100644 --- a/Source/NoesisRuntime/Private/NoesisSettings.cpp +++ b/Source/NoesisRuntime/Private/NoesisSettings.cpp @@ -5,10 +5,28 @@ #include "NoesisSettings.h" +#include "NoesisResourceResolver.h" + UNoesisSettings::UNoesisSettings(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { OffscreenTextureSampleCount = ENoesisOffscreenSampleCount::One; GlyphTextureSize = ENoesisGlyphCacheDimensions::x1024; GlyphMeshThreshold = 96; + + ResourceResolverClass = UNoesisResourceResolver::StaticClass(); +} + +UNoesisResourceResolver* UNoesisSettings::GetResourceResolver() +{ + if (ResourceResolverInstance != nullptr) + return ResourceResolverInstance; + + if (ResourceResolverClass == nullptr) + ResourceResolverClass = UNoesisResourceResolver::StaticClass(); + + ResourceResolverInstance = NewObject(this, ResourceResolverClass.Get()); + check(ResourceResolverInstance); + + return ResourceResolverInstance; } From 02566c30acb88e0f8e2f4ae9e5c61ffa482dd68f Mon Sep 17 00:00:00 2001 From: GeorgeR Date: Tue, 15 Jan 2019 20:26:32 +1100 Subject: [PATCH 17/20] added missing include --- Source/NoesisRuntime/Private/NoesisResourceProvider.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp index 235f43d..add0a28 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp +++ b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp @@ -18,6 +18,7 @@ #include "NoesisXaml.h" #include "NoesisSupport.h" #include "NoesisResourceResolver.h" +#include "NoesisSettings.h" UNoesisXaml* FNoesisResourceProvider::GetXaml(FString XamlPath) { From 78f32b41e616f793f7a08fd79443783bd18676c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Feb 2019 19:01:09 +0100 Subject: [PATCH 18/20] Support for Noesis SDK 2.2.0b5 --- Source/Noesis/Noesis.Build.cs | 15 +- Source/Noesis/Noesis_APL.xml | 3 + .../Private/NoesisEditorPrivatePCH.h | 1 + .../Private/NoesisXamlFactory.cpp | 584 ++++++------------ Source/NoesisRuntime/Classes/NoesisXaml.h | 3 + .../Private/NoesisFunctionLibrary.cpp | 88 +-- .../NoesisRuntime/Private/NoesisInstance.cpp | 29 +- .../Private/NoesisInteractivity.cpp | 86 +++ .../Private/NoesisRuntimeModule.cpp | 136 ++-- .../Private/NoesisRuntimePrivatePCH.h | 1 + .../NoesisRuntime/Private/NoesisSupport.cpp | 2 +- .../NoesisRuntime/Private/NoesisTypeClass.cpp | 361 +++++------ Source/NoesisRuntime/Private/NoesisXaml.cpp | 2 +- .../Private/Render/NoesisRenderDevice.cpp | 34 +- .../Public/NoesisRuntimeModule.h | 6 + Source/NoesisRuntime/Public/NoesisTypeClass.h | 18 +- 16 files changed, 617 insertions(+), 752 deletions(-) create mode 100644 Source/NoesisRuntime/Private/NoesisInteractivity.cpp diff --git a/Source/Noesis/Noesis.Build.cs b/Source/Noesis/Noesis.Build.cs index 9eca2db..21be35b 100644 --- a/Source/Noesis/Noesis.Build.cs +++ b/Source/Noesis/Noesis.Build.cs @@ -1,4 +1,4 @@ -//////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// // NoesisGUI - http://www.noesisengine.com // Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved. //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -16,13 +16,15 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) string NoesisBasePath = ModuleDirectory + "/NoesisSDK/"; string NoesisIncludePath = NoesisBasePath + "Include/"; + string NoesisInteractivityIncludePath = NoesisBasePath + "Src/Packages/App/Interactivity/Include/"; PublicIncludePaths.Add(ModuleDirectory); PublicIncludePaths.Add(NoesisIncludePath); + PublicIncludePaths.Add(NoesisInteractivityIncludePath); // Let's try to make sure the right version of the SDK is in the right place. - const string RequiredRevision = "(r6972)"; - const string RequiredVersionName = "2.1.0f1"; + const string RequiredRevision = "(r7619)"; + const string RequiredVersionName = "2.2.0b5"; if (!Directory.Exists(NoesisBasePath)) { throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName); @@ -132,6 +134,8 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) { string NoesisLibPath = NoesisBasePath + "Bin/android_arm/"; PublicLibraryPaths.Add(NoesisLibPath); + string NoesisLib64Path = NoesisBasePath + "Bin/android_arm64/"; + PublicLibraryPaths.Add(NoesisLib64Path); PublicAdditionalLibraries.Add("Noesis"); string NoesisAplPath = "/Noesis_APL.xml"; @@ -148,5 +152,10 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); } + else if (Target.Platform == UnrealTargetPlatform.HTML5) + { + string NoesisLibPath = NoesisBasePath + "Bin/wasm/"; + PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.bc"); + } } } diff --git a/Source/Noesis/Noesis_APL.xml b/Source/Noesis/Noesis_APL.xml index ae81c5b..cc410e2 100644 --- a/Source/Noesis/Noesis_APL.xml +++ b/Source/Noesis/Noesis_APL.xml @@ -5,6 +5,9 @@ + + + diff --git a/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h b/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h index 8e66150..f1ed399 100644 --- a/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h +++ b/Source/NoesisEditor/Private/NoesisEditorPrivatePCH.h @@ -22,6 +22,7 @@ #include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetStringLibrary.h" #include "EditorFramework/AssetImportData.h" +#include "Sound/SoundWave.h" // UnrealEd includes #include "AutomatedAssetImportData.h" diff --git a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp index c220d8c..3af025d 100644 --- a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp +++ b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp @@ -64,129 +64,6 @@ void ExtractPaths(FString FileUri, FString BaseFilePath, FString BasePackage, FS FPaths::CollapseRelativeDirectories(FilePath); } -TArray ScanKeyword(FString Text, FString Keyword) -{ - TArray Strings; - - int32 TextLen = Text.Len(); - int32 KeywordIndex = INDEX_NONE; - while ((KeywordIndex = Text.Find(Keyword, ESearchCase::IgnoreCase, ESearchDir::FromStart, KeywordIndex)) != INDEX_NONE) - { - int32 StartIndex = KeywordIndex; - while (StartIndex >= 0 && Text[StartIndex] != TEXT('\"') && Text[StartIndex] != TEXT('\'') && Text[StartIndex] != TEXT('>')) - { - --StartIndex; - } - - int32 EndIndex = KeywordIndex; - while (EndIndex < TextLen && Text[EndIndex] != TEXT('\"') && Text[EndIndex] != TEXT('\'') && Text[EndIndex] != TEXT('<')) - { - ++EndIndex; - } - - if (StartIndex >= 0 && EndIndex < TextLen) - { - Strings.Add(Text.Left(EndIndex).RightChop(StartIndex + 1)); - } - - KeywordIndex = EndIndex + 1; - } - - return Strings; -} - -struct FXamlDescriptor -{ - FString Path; - UNoesisXaml* Xaml; -}; - -TArray ParseForXamls(FString XamlText) -{ - TArray XamlDescriptors; - - TArray Strings = ScanKeyword(XamlText, TEXT(".xaml")); - for (auto String : Strings) - { - FXamlDescriptor& XamlDescriptor = *new(XamlDescriptors)FXamlDescriptor; - XamlDescriptor.Path = String; - } - - return XamlDescriptors; -} - -void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& XamlDescriptors) -{ - auto XamlFact = NewObject(); - XamlFact->AddToRoot(); - - for (auto& XamlDescriptor : XamlDescriptors) - { - FString XamlPath; - FString FileName; - FString PackagePath; - FString XamlName; - ExtractPaths(XamlDescriptor.Path, Path, BasePackageName, ProjectURIRoot, XamlPath, FileName, PackagePath, XamlName); - - - UPackage* XamlPackage = NULL; - - FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; - UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); - - if (!ExistingXaml) - { - const FString Suffix(TEXT("")); - - XamlPackage = CreatePackage(NULL, *(PackagePath / XamlName)); - } - else - { - XamlPackage = ExistingXaml->GetOutermost(); - XamlPackage->FullyLoad(); - ExistingXaml->DestroyThumbnailRenderData(); - } - - FString FullFilename = XamlPath / FileName; - FPaths::MakeStandardFilename(FullFilename); - bool Cancelled = false; - UNoesisXaml* Xaml = (UNoesisXaml*)XamlFact->ImportObject(UNoesisXaml::StaticClass(), XamlPackage, *XamlName, RF_Standalone | RF_Public, FullFilename, nullptr, Cancelled); - - if (Xaml != NULL) - { - // Notify the asset registry - FAssetRegistryModule::AssetCreated(Xaml); - - // Set the dirty flag so this package will get saved later - XamlPackage->SetDirtyFlag(true); - } - - XamlDescriptor.Xaml = Xaml; - } - - XamlFact->RemoveFromRoot(); -} - -struct FFontDescriptor -{ - FString Family; - UFont* Font; -}; - -TArray ParseForFonts(FString XamlText) -{ - TArray FontDescriptors; - - TArray Strings = ScanKeyword(XamlText, TEXT("#")); - for (auto String : Strings) - { - FFontDescriptor& FontDescriptor = *new(FontDescriptors)FFontDescriptor; - FontDescriptor.Family = String; - } - - return FontDescriptors; -} - unsigned long StreamRead(FT_Stream Stream, unsigned long Offset, unsigned char* Buffer, unsigned long Count) { FMemory::Memcpy(Buffer, (uint8*)Stream->descriptor.pointer + Offset, Count); @@ -195,281 +72,176 @@ unsigned long StreamRead(FT_Stream Stream, unsigned long Offset, unsigned char* void StreamClose(FT_Stream) {} -void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& FontDescriptors) +UFont* ImportFontFamily(FString Path, FString Family, FString BasePackageName, FString ProjectURIRoot) { - TSet UniqueFontFamilies; - for (auto FontDescriptor : FontDescriptors) - { - UniqueFontFamilies.Add(FontDescriptor.Family); - } + FString BaseUri, FamilyName; + Family.Split(TEXT("#"), &BaseUri, &FamilyName); - FontDescriptors.Empty(); + IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); - for (auto Family : UniqueFontFamilies) + class ScanFolderForFonts : public IPlatformFile::FDirectoryVisitor { - FString BaseUri, FamilyName; - Family.Split(TEXT("#"), &BaseUri, &FamilyName); - - IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); + public: + FString FontPackagePath; + FString FamilyName; + TArray Fonts; + FT_Library FTLibrary; - class ScanFolderForFonts : public IPlatformFile::FDirectoryVisitor + ScanFolderForFonts(FString InFontPackagePath, FString InFamilyName) + : FontPackagePath(InFontPackagePath), FamilyName(InFamilyName) { - public: - FString FontPackagePath; - FString FamilyName; - TArray Fonts; - FT_Library FTLibrary; - - ScanFolderForFonts(FString InFontPackagePath, FString InFamilyName) - : FontPackagePath(InFontPackagePath), FamilyName(InFamilyName) - { - int32 Error = FT_Init_FreeType(&FTLibrary); - checkf(Error == 0, TEXT("Could not init Freetype")); - } + int32 Error = FT_Init_FreeType(&FTLibrary); + checkf(Error == 0, TEXT("Could not init Freetype")); + } - ~ScanFolderForFonts() - { - FT_Done_FreeType(FTLibrary); - } + ~ScanFolderForFonts() + { + FT_Done_FreeType(FTLibrary); + } - virtual bool Visit(const TCHAR* FilenameOrDirectory, bool IsDirectory) override + virtual bool Visit(const TCHAR* FilenameOrDirectory, bool IsDirectory) override + { + if (!IsDirectory) { - if (!IsDirectory) + FString Extension = FPaths::GetExtension(FilenameOrDirectory).ToLower(); + if (Extension == TEXT("ttf") || Extension == TEXT("otf")) { - FString Extension = FPaths::GetExtension(FilenameOrDirectory).ToLower(); - if (Extension == TEXT("ttf") || Extension == TEXT("otf")) + TArray FileData; + if (FFileHelper::LoadFileToArray(FileData, FilenameOrDirectory)) { - TArray FileData; - if (FFileHelper::LoadFileToArray(FileData, FilenameOrDirectory)) + FT_StreamRec Stream; + FMemory::Memset(&Stream, 0, sizeof(Stream)); + Stream.descriptor.pointer = FileData.GetData(); + Stream.size = FileData.Num(); + Stream.read = &StreamRead; + Stream.close = &StreamClose; + + FT_Open_Args Args; + FMemory::Memset(&Args, 0, sizeof(Args)); + Args.flags = FT_OPEN_STREAM; + Args.stream = &Stream; + + FT_Face Face; + FT_Error Error = FT_Open_Face(FTLibrary, &Args, -1, &Face); + if (Error == 0) { - FT_StreamRec Stream; - FMemory::Memset(&Stream, 0, sizeof(Stream)); - Stream.descriptor.pointer = FileData.GetData(); - Stream.size = FileData.Num(); - Stream.read = &StreamRead; - Stream.close = &StreamClose; - - FT_Open_Args Args; - FMemory::Memset(&Args, 0, sizeof(Args)); - Args.flags = FT_OPEN_STREAM; - Args.stream = &Stream; - - FT_Face Face; - FT_Error Error = FT_Open_Face(FTLibrary, &Args, -1, &Face); - if (Error == 0) + for (FT_Long FaceIndex = 0; FaceIndex < Face->num_faces; FaceIndex++) { - for (FT_Long FaceIndex = 0; FaceIndex < Face->num_faces; FaceIndex++) + FT_Face SubFace; + Error = FT_Open_Face(FTLibrary, &Args, FaceIndex, &SubFace); + if (Error == 0) { - FT_Face SubFace; - Error = FT_Open_Face(FTLibrary, &Args, FaceIndex, &SubFace); - if (Error == 0) + if (SubFace->family_name && FCStringAnsi::Strcmp(SubFace->family_name, StringCast(*FamilyName).Get()) == 0) { - if (SubFace->family_name && FCStringAnsi::Strcmp(SubFace->family_name, StringCast(*FamilyName).Get()) == 0) - { - FString FontFaceName = ObjectTools::SanitizeObjectName(FPaths::GetBaseFilename(FPaths::GetBaseFilename(FilenameOrDirectory))); - - UPackage* FontFacePackage = NULL; + FString FontFaceName = ObjectTools::SanitizeObjectName(FPaths::GetBaseFilename(FPaths::GetBaseFilename(FilenameOrDirectory))); - FString FontFaceObjectPath = FontPackagePath / FontFaceName + TEXT(".") + FontFaceName; - UFontFace* ExistingFontFace = LoadObject(NULL, *FontFaceObjectPath); + UPackage* FontFacePackage = NULL; - if (!ExistingFontFace) - { - const FString Suffix(TEXT("")); + FString FontFaceObjectPath = FontPackagePath / FontFaceName + TEXT(".") + FontFaceName; + UFontFace* ExistingFontFace = LoadObject(NULL, *FontFaceObjectPath); - FontFacePackage = CreatePackage(NULL, *(FontPackagePath / FontFaceName)); - } - else - { - FontFacePackage = ExistingFontFace->GetOutermost(); - FontFacePackage->FullyLoad(); - } + if (!ExistingFontFace) + { + const FString Suffix(TEXT("")); - auto FontFaceFactory = NewObject(); - FontFaceFactory->AddToRoot(); + FontFacePackage = CreatePackage(NULL, *(FontPackagePath / FontFaceName)); + } + else + { + FontFacePackage = ExistingFontFace->GetOutermost(); + FontFacePackage->FullyLoad(); + } - UAutomatedAssetImportData* AutomatedAssetImportData = NewObject(); - FontFaceFactory->SetAutomatedAssetImportData(AutomatedAssetImportData); + auto FontFaceFactory = NewObject(); + FontFaceFactory->AddToRoot(); - bool Cancelled = false; - UFontFace* FontFace = (UFontFace*)FontFaceFactory->ImportObject(UFontFace::StaticClass(), FontFacePackage, *FontFaceName, RF_Standalone | RF_Public, FilenameOrDirectory, TEXT(""), Cancelled); + UAutomatedAssetImportData* AutomatedAssetImportData = NewObject(); + FontFaceFactory->SetAutomatedAssetImportData(AutomatedAssetImportData); - if (FontFace != NULL) - { - FontFace->LoadingPolicy = EFontLoadingPolicy::Inline; + bool Cancelled = false; + UFontFace* FontFace = (UFontFace*)FontFaceFactory->ImportObject(UFontFace::StaticClass(), FontFacePackage, *FontFaceName, RF_Standalone | RF_Public, FilenameOrDirectory, TEXT(""), Cancelled); - // Notify the asset registry - FAssetRegistryModule::AssetCreated(FontFace); + if (FontFace != NULL) + { + FontFace->LoadingPolicy = EFontLoadingPolicy::Inline; - // Set the dirty flag so this package will get saved later - FontFacePackage->SetDirtyFlag(true); - } + // Notify the asset registry + FAssetRegistryModule::AssetCreated(FontFace); - FontFaceFactory->RemoveFromRoot(); + // Set the dirty flag so this package will get saved later + FontFacePackage->SetDirtyFlag(true); + } - // Add a default typeface referencing the newly created font face - FTypefaceEntry& DefaultTypefaceEntry = Fonts[Fonts.AddDefaulted()]; - DefaultTypefaceEntry.Name = SubFace->style_name; - DefaultTypefaceEntry.Font = FFontData(FontFace); + FontFaceFactory->RemoveFromRoot(); - } + // Add a default typeface referencing the newly created font face + FTypefaceEntry& DefaultTypefaceEntry = Fonts[Fonts.AddDefaulted()]; + DefaultTypefaceEntry.Name = SubFace->style_name; + DefaultTypefaceEntry.Font = FFontData(FontFace); - FT_Done_Face(SubFace); } - } - FT_Done_Face(Face); + FT_Done_Face(SubFace); + } } + + FT_Done_Face(Face); } } } - - return true; } - }; - - FString FontFilePath; - FString FontFileName; - FString FontPackagePath; - FString FontPackageName; - ExtractPaths(BaseUri, Path, BasePackageName, ProjectURIRoot, FontFilePath, FontFileName, FontPackagePath, FontPackageName); - - ScanFolderForFonts Visitor(FontPackagePath, FamilyName); - PlatformFile.IterateDirectory(*FontFilePath, Visitor); - if (Visitor.Fonts.Num()) - { - UPackage* FontPackage = NULL; - - FString FontName = ObjectTools::SanitizeObjectName(FamilyName + TEXT("_Font")); - FString FontObjectPath = FontPackagePath / FontName + TEXT(".") + FontName; - UFont* ExistingFont = LoadObject(NULL, *FontObjectPath); - - if (!ExistingFont) - { - const FString Suffix(TEXT("")); - - FontPackage = CreatePackage(NULL, *(FontPackagePath / FontName)); - } - else - { - FontPackage = ExistingFont->GetOutermost(); - FontPackage->FullyLoad(); - } - - UFontFactory* FontFactory = NewObject(); - FontFactory->bEditAfterNew = false; - - UFont* Font = Cast(FontFactory->FactoryCreateNew(UFont::StaticClass(), FontPackage, *FontName, RF_Standalone | RF_Public, nullptr, nullptr)); - if (Font) - { - Font->FontCacheType = EFontCacheType::Runtime; - - FAssetRegistryModule::AssetCreated(Font); - FontPackage->MarkPackageDirty(); - - Font->CompositeFont.DefaultTypeface.Fonts = Visitor.Fonts; - - FFontDescriptor& FontDescriptor = *new(FontDescriptors)FFontDescriptor; - FontDescriptor.Family = Family; - FontDescriptor.Font = Font; - } + return true; } - } -} - -struct FImageDescriptor -{ - FString Path; - UTexture2D* Texture; -}; + }; -TArray ParseForImages(FString XamlText) -{ - TArray ImageDescriptors; + FString FontFilePath; + FString FontFileName; + FString FontPackagePath; + FString FontPackageName; + ExtractPaths(BaseUri, Path, BasePackageName, ProjectURIRoot, FontFilePath, FontFileName, FontPackagePath, FontPackageName); - TArray Strings; - auto TextureFact = NewObject(); - for (auto Format : TextureFact->Formats) - { - int32 Index; - Format.FindChar(TEXT(';'), Index); - Strings += ScanKeyword(XamlText, FString(TEXT(".")) + Format.Left(Index)); - } + ScanFolderForFonts Visitor(FontPackagePath, FamilyName); + PlatformFile.IterateDirectory(*FontFilePath, Visitor); - for (auto String : Strings) + if (Visitor.Fonts.Num()) { - FImageDescriptor& ImageDescriptor = *new(ImageDescriptors)FImageDescriptor; - ImageDescriptor.Path = String; - } - - return ImageDescriptors; -} + UPackage* FontPackage = NULL; -void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& ImageDescriptors) -{ - auto TextureFact = NewObject(); - TextureFact->AddToRoot(); + FString FontName = ObjectTools::SanitizeObjectName(FamilyName + TEXT("_Font")); + FString FontObjectPath = FontPackagePath / FontName + TEXT(".") + FontName; + UFont* ExistingFont = LoadObject(NULL, *FontObjectPath); - TSet UniqueImagePaths; - for (auto ImageDescriptor : ImageDescriptors) - { - UniqueImagePaths.Add(ImageDescriptor.Path); - } - - ImageDescriptors.Empty(); - - for (auto ImagePath : UniqueImagePaths) - { - FString TexturePath; - FString FileName; - FString PackagePath; - FString TextureName; - ExtractPaths(ImagePath, Path, BasePackageName, ProjectURIRoot, TexturePath, FileName, PackagePath, TextureName); - - UPackage* TexturePackage = NULL; - - FString TextureObjectPath = PackagePath / TextureName + TEXT(".") + TextureName; - UTexture2D* ExistingTexture = LoadObject(NULL, *TextureObjectPath); - - if (!ExistingTexture) + if (!ExistingFont) { const FString Suffix(TEXT("")); - TexturePackage = CreatePackage(NULL, *(PackagePath / TextureName)); + FontPackage = CreatePackage(NULL, *(FontPackagePath / FontName)); } else { - TexturePackage = ExistingTexture->GetOutermost(); - TexturePackage->FullyLoad(); + FontPackage = ExistingFont->GetOutermost(); + FontPackage->FullyLoad(); } - TextureFact->SuppressImportOverwriteDialog(); - - FString FullFilename = TexturePath / FileName; - bool Cancelled = false; - UTexture2D* Texture = (UTexture2D*)TextureFact->ImportObject(UTexture2D::StaticClass(), TexturePackage, *TextureName, RF_Standalone | RF_Public, FullFilename, nullptr, Cancelled); + UFontFactory* FontFactory = NewObject(); + FontFactory->bEditAfterNew = false; - if (Texture != NULL) + UFont* Font = Cast(FontFactory->FactoryCreateNew(UFont::StaticClass(), FontPackage, *FontName, RF_Standalone | RF_Public, nullptr, nullptr)); + if (Font) { - Texture->LODGroup = TEXTUREGROUP_UI; - Texture->SRGB = false; - void FixPremultipliedPNGTexture(UTexture2D*); - FixPremultipliedPNGTexture(Texture); + Font->FontCacheType = EFontCacheType::Runtime; - // Notify the asset registry - FAssetRegistryModule::AssetCreated(Texture); + FAssetRegistryModule::AssetCreated(Font); + FontPackage->MarkPackageDirty(); - // Set the dirty flag so this package will get saved later - TexturePackage->SetDirtyFlag(true); - } + Font->CompositeFont.DefaultTypeface.Fonts = Visitor.Fonts; - FImageDescriptor& ImageDescriptor = *new(ImageDescriptors)FImageDescriptor; - ImageDescriptor.Path = ImagePath; - ImageDescriptor.Texture = Texture; + return Font; + } } - TextureFact->RemoveFromRoot(); + return nullptr; } UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn) @@ -505,50 +277,6 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, FString XamlText = NsStringToFString((const char*)Buffer); - TArray Comments; - FRegexPattern CommentPattern(TEXT("")); - FRegexMatcher CommentMatcher(CommentPattern, XamlText); - - while (CommentMatcher.FindNext()) - { - Comments.Add(XamlText.Left(CommentMatcher.GetMatchEnding()).RightChop(CommentMatcher.GetMatchBeginning())); - } - - for (auto Comment : Comments) - { - XamlText = XamlText.Replace(*Comment, TEXT("")); - } - - TArray XamlDescriptors = ParseForXamls(XamlText); - ImportXamls(BasePackageName, ProjectURIRoot, Directory, XamlDescriptors); - for (auto XamlDescriptor : XamlDescriptors) - { - if (!XamlDescriptor.Xaml) - { - UE_LOG(LogNoesisEditor, Log, TEXT("Error importing XAML file %s: Referenced XAML file %s not found."), *GetCurrentFilename(), *XamlDescriptor.Path); - } - } - - TArray FontDescriptors = ParseForFonts(XamlText); - ImportFonts(BasePackageName, ProjectURIRoot, Directory, FontDescriptors); - for (auto FontDescriptor : FontDescriptors) - { - if (!FontDescriptor.Font) - { - UE_LOG(LogNoesisEditor, Log, TEXT("Error importing XAML file %s: Referenced font family %s not found."), *GetCurrentFilename(), *FontDescriptor.Family); - } - } - - TArray ImageDescriptors = ParseForImages(XamlText); - ImportImages(BasePackageName, ProjectURIRoot, Directory, ImageDescriptors); - for (auto ImageDescriptor : ImageDescriptors) - { - if (!ImageDescriptor.Texture) - { - UE_LOG(LogNoesisEditor, Log, TEXT("Error importing XAML file %s: Referenced image file %s not found."), *GetCurrentFilename(), *ImageDescriptor.Path); - } - } - UNoesisXaml* NoesisXaml = nullptr; { @@ -583,35 +311,75 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, } } - for (auto XamlDescriptor : XamlDescriptors) - { - if (XamlDescriptor.Xaml) - { - FString XamlPath = XamlDescriptor.Xaml->GetPathName(); - XamlText = XamlText.Replace(*XamlDescriptor.Path, *XamlPath); - NoesisXaml->Xamls.Add(XamlDescriptor.Xaml); - } - } + NsString Text = TCHARToNsString(*XamlText); - for (auto FontDescriptor : FontDescriptors) + Noesis::MemoryStream XamlStream(Text.c_str(), Text.length()); + TArray Dependencies; + auto DependencyCallback = [](void* UserData, const char* URI) { - if (FontDescriptor.Font) + TArray& Dependencies = *(TArray*)UserData; + Dependencies.AddUnique(URI); + }; + Noesis::GUI::GetXamlDependencies(&XamlStream, &Dependencies, DependencyCallback); + + FAssetToolsModule& AssetToolsModule = FModuleManager::Get().LoadModuleChecked("AssetTools"); + UAutomatedAssetImportData* AutomatedAssetImportData = NewObject(); + AutomatedAssetImportData->bReplaceExisting = true; + for (auto& Dependency : Dependencies) + { + NsString::size_type hashPos = Dependency.find('#'); + if (hashPos != NsString::npos) { - FString FontPath = FontDescriptor.Font->GetPathName(); - FString Uri, Family; - ensure(FontDescriptor.Family.Split(TEXT("#"), &Uri, &Family)); - XamlText = XamlText.Replace(*FontDescriptor.Family, *(FontPath / TEXT("#") + Family)); - NoesisXaml->Fonts.Add(FontDescriptor.Font); - } - } + FString Family = NsStringToFString(Dependency.c_str()); + UFont* Font = ImportFontFamily(Directory, Family, BasePackageName, ProjectURIRoot); - for (auto ImageDescriptor : ImageDescriptors) - { - if (ImageDescriptor.Texture) + if (Font) + { + FString FontPath = Font->GetPathName(); + XamlText = XamlText.Replace(*Family, *(FontPath / TEXT("#") + NsStringToFString(Dependency.c_str() + hashPos + 1))); + NoesisXaml->Fonts.Add(Font); + } + } + else { - FString ImagePath = ImageDescriptor.Texture->GetPathName(); - XamlText = XamlText.Replace(*ImageDescriptor.Path, *ImagePath); - NoesisXaml->Textures.Add(ImageDescriptor.Texture); + FString DependencyPath; + FString FileName; + FString PackagePath; + FString DependencyName; + ExtractPaths(Dependency.c_str(), Directory, BasePackageName, ProjectURIRoot, DependencyPath, FileName, PackagePath, DependencyName); + + AutomatedAssetImportData->Filenames.Empty(1); + AutomatedAssetImportData->Filenames.Add(DependencyPath / FileName); + AutomatedAssetImportData->DestinationPath = PackagePath; + TArray Assets = AssetToolsModule.Get().ImportAssetsAutomated(AutomatedAssetImportData); + + + for (auto Asset : Assets) + { + if (UTexture2D* Texture = Cast(Asset)) + { + Texture->LODGroup = TEXTUREGROUP_UI; + Texture->SRGB = false; + void FixPremultipliedPNGTexture(UTexture2D*); + FixPremultipliedPNGTexture(Texture); + + FString ImagePath = Texture->GetPathName(); + XamlText = XamlText.Replace(*NsStringToFString(Dependency.c_str()), *ImagePath); + NoesisXaml->Textures.Add(Texture); + } + else if (UNoesisXaml* Xaml = Cast(Asset)) + { + FString XamlPath = Xaml->GetPathName(); + XamlText = XamlText.Replace(*NsStringToFString(Dependency.c_str()), *XamlPath); + NoesisXaml->Xamls.Add(Xaml); + } + else if (USoundWave* Sound = Cast(Asset)) + { + FString SoundPath = Sound->GetPathName(); + XamlText = XamlText.Replace(*NsStringToFString(Dependency.c_str()), *SoundPath); + NoesisXaml->Sounds.Add(Sound); + } + } } } diff --git a/Source/NoesisRuntime/Classes/NoesisXaml.h b/Source/NoesisRuntime/Classes/NoesisXaml.h index 96fd522..fc5ec3d 100644 --- a/Source/NoesisRuntime/Classes/NoesisXaml.h +++ b/Source/NoesisRuntime/Classes/NoesisXaml.h @@ -31,6 +31,9 @@ class NOESISRUNTIME_API UNoesisXaml : public UObject UPROPERTY() TArray Fonts; + UPROPERTY() + TArray Sounds; + Noesis::Ptr LoadXaml(); void LoadComponent(Noesis::BaseComponent* Component); diff --git a/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp b/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp index 021cef2..6af31d7 100644 --- a/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp +++ b/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp @@ -38,7 +38,7 @@ void UNoesisFunctionLibrary::TrySetDataContext(UObject* Element, UObject* DataCo UNoesisBaseComponent* BaseComponent = Cast(Element); if (BaseComponent) { - Noesis::FrameworkElement* NoesisElement = NsDynamicCast(BaseComponent->NoesisComponent.GetPtr()); + Noesis::FrameworkElement* NoesisElement = Noesis::DynamicCast(BaseComponent->NoesisComponent.GetPtr()); if (NoesisElement) { @@ -96,10 +96,9 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Add) P_FINISH; P_NATIVE_BEGIN; *(int32*)RESULT_PARAM = UKismetArrayLibrary::GenericArray_Add(ArrayAddr, ArrayProperty, NewItemPtr); + NoesisNotifyArrayPropertyPostAdd(ArrayAddr); P_NATIVE_END; InnerProp->DestroyValue(StorageSpace); - - NoesisNotifyArrayPropertyAdd(ArrayAddr); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_AddUnique) @@ -124,19 +123,17 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_AddUnique) Stack.StepCompiledIn(StorageSpace); void* NewItemPtr = (Stack.MostRecentPropertyAddress != NULL && Stack.MostRecentProperty->GetClass() == InnerProp->GetClass()) ? Stack.MostRecentPropertyAddress : StorageSpace; - FScriptArrayHelper ArrayHelper = FScriptArrayHelper::CreateHelperFormInnerProperty(InnerProp, ArrayAddr); - int32 ArrayNum = ArrayHelper.Num(); - P_FINISH; P_NATIVE_BEGIN; + FScriptArrayHelper ArrayHelper = FScriptArrayHelper::CreateHelperFormInnerProperty(InnerProp, ArrayAddr); + int32 ArrayNum = ArrayHelper.Num(); *(int32*)RESULT_PARAM = UKismetArrayLibrary::GenericArray_AddUnique(ArrayAddr, ArrayProperty, NewItemPtr); - P_NATIVE_END; - InnerProp->DestroyValue(StorageSpace); - if (ArrayHelper.Num() != ArrayNum) { - NoesisNotifyArrayPropertyAdd(ArrayAddr); + NoesisNotifyArrayPropertyPostAdd(ArrayAddr); } + P_NATIVE_END; + InnerProp->DestroyValue(StorageSpace); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Shuffle) @@ -154,9 +151,8 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Shuffle) P_FINISH; P_NATIVE_BEGIN; UKismetArrayLibrary::GenericArray_Shuffle(ArrayAddr, ArrayProperty); + NoesisNotifyArrayPropertyPostChanged(ArrayAddr); P_NATIVE_END; - - NoesisNotifyArrayPropertyChanged(ArrayAddr); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Append) @@ -184,12 +180,10 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Append) P_FINISH; P_NATIVE_BEGIN; + NoesisNotifyArrayPropertyPreAppend(TargetArrayAddr); UKismetArrayLibrary::GenericArray_Append(TargetArrayAddr, TargetArrayProperty, SourceArrayAddr, SourceArrayProperty); + NoesisNotifyArrayPropertyPostAppend(TargetArrayAddr); P_NATIVE_END; - - FScriptArrayHelper SourceArrayHelper(SourceArrayProperty, SourceArrayAddr); - int32 NumItems = SourceArrayHelper.Num(); - NoesisNotifyArrayPropertyAppend(TargetArrayAddr, NumItems); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Insert) @@ -218,10 +212,14 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Insert) P_FINISH; P_NATIVE_BEGIN; UKismetArrayLibrary::GenericArray_Insert(ArrayAddr, ArrayProperty, NewItemPtr, Index); + FScriptArrayHelper ArrayHelper = FScriptArrayHelper::CreateHelperFormInnerProperty(InnerProp, ArrayAddr); + int32 ArrayNum = ArrayHelper.Num(); + if (ArrayHelper.IsValidIndex(Index)) + { + NoesisNotifyArrayPropertyPostInsert(ArrayAddr, Index); + } P_NATIVE_END; InnerProp->DestroyValue(StorageSpace); - - NoesisNotifyArrayPropertyInsert(ArrayAddr, Index); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Remove) @@ -239,10 +237,10 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Remove) P_GET_PROPERTY(UIntProperty, Index); P_FINISH; P_NATIVE_BEGIN; + NoesisNotifyArrayPropertyPreRemove(ArrayAddr, Index); UKismetArrayLibrary::GenericArray_Remove(ArrayAddr, ArrayProperty, Index); + NoesisNotifyArrayPropertyPostRemove(ArrayAddr, Index); P_NATIVE_END; - - NoesisNotifyArrayPropertyRemove(ArrayAddr, Index); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_RemoveItem) @@ -267,7 +265,6 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_RemoveItem) void* ItemPtr = StorageSpace; P_FINISH; - // Bools need to be processed internally by the property so that C++ bool value is properly set. const UBoolProperty* BoolProperty = Cast(InnerProp); if (BoolProperty) @@ -277,23 +274,21 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_RemoveItem) } P_NATIVE_BEGIN; *(bool*)RESULT_PARAM = false; - if (ArrayAddr) { int32 IndexToRemove = UKismetArrayLibrary::GenericArray_Find(ArrayAddr, ArrayProperty, ItemPtr); while (IndexToRemove != INDEX_NONE) { + NoesisNotifyArrayPropertyPreRemove(ArrayAddr, IndexToRemove); UKismetArrayLibrary::GenericArray_Remove(ArrayAddr, ArrayProperty, IndexToRemove); *(bool*)RESULT_PARAM = true; //removed - NoesisNotifyArrayPropertyRemove(ArrayAddr, IndexToRemove); + NoesisNotifyArrayPropertyPostRemove(ArrayAddr, IndexToRemove); // See if there is another in the array IndexToRemove = UKismetArrayLibrary::GenericArray_Find(ArrayAddr, ArrayProperty, ItemPtr); } } - P_NATIVE_END; - InnerProp->DestroyValue(StorageSpace); } @@ -311,9 +306,8 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Clear) P_FINISH; P_NATIVE_BEGIN; UKismetArrayLibrary::GenericArray_Clear(ArrayAddr, ArrayProperty); + NoesisNotifyArrayPropertyPostClear(ArrayAddr); P_NATIVE_END; - - NoesisNotifyArrayPropertyClear(ArrayAddr); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Resize) @@ -327,13 +321,27 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Resize) Stack.bArrayContextFailed = true; return; } + P_GET_PROPERTY(UIntProperty, Size); + P_FINISH; P_NATIVE_BEGIN; - UKismetArrayLibrary::GenericArray_Resize(ArrayAddr, ArrayProperty, Size); + const UProperty* InnerProp = ArrayProperty->Inner; + FScriptArrayHelper ArrayHelper = FScriptArrayHelper::CreateHelperFormInnerProperty(InnerProp, ArrayAddr); + int32 ArrayNum = ArrayHelper.Num(); + for (int32 Index = ArrayNum; Index-- > Size;) + { + NoesisNotifyArrayPropertyPreRemove(ArrayAddr, Index); + UKismetArrayLibrary::GenericArray_Remove(ArrayAddr, ArrayProperty, Index); + NoesisNotifyArrayPropertyPostRemove(ArrayAddr, Index); + } + if (Size > ArrayNum) + { + NoesisNotifyArrayPropertyPreAppend(ArrayAddr); + UKismetArrayLibrary::GenericArray_Resize(ArrayAddr, ArrayProperty, Size); + NoesisNotifyArrayPropertyPostAppend(ArrayAddr); + } P_NATIVE_END; - - NoesisNotifyArrayPropertyResize(ArrayAddr); } DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Set) @@ -360,13 +368,23 @@ DEFINE_FUNCTION(UNoesisFunctionLibrary::execNoesisArray_Set) void* NewItemPtr = (Stack.MostRecentPropertyAddress != NULL && Stack.MostRecentProperty->GetClass() == InnerProp->GetClass()) ? Stack.MostRecentPropertyAddress : StorageSpace; P_GET_UBOOL(bSizeToFit); - P_FINISH; - P_NATIVE_BEGIN; - UKismetArrayLibrary::GenericArray_Set(ArrayAddr, ArrayProperty, Index, NewItemPtr, bSizeToFit); + FScriptArrayHelper ArrayHelper = FScriptArrayHelper::CreateHelperFormInnerProperty(InnerProp, ArrayAddr); + int32 ArrayNum = ArrayHelper.Num(); + if (bSizeToFit && Index >= ArrayNum) + { + NoesisNotifyArrayPropertyPreAppend(ArrayAddr); + UKismetArrayLibrary::GenericArray_Resize(ArrayAddr, ArrayProperty, Index + 1); + NoesisNotifyArrayPropertyPostAppend(ArrayAddr); + ArrayNum = Index + 1; + } + if (bSizeToFit || Index < ArrayNum) + { + NoesisNotifyArrayPropertyPreSet(ArrayAddr, Index); + UKismetArrayLibrary::GenericArray_Set(ArrayAddr, ArrayProperty, Index, NewItemPtr, bSizeToFit); + NoesisNotifyArrayPropertyPostSet(ArrayAddr, Index); + } P_NATIVE_END; InnerProp->DestroyValue(StorageSpace); - - NoesisNotifyArrayPropertySet(ArrayAddr, Index); } diff --git a/Source/NoesisRuntime/Private/NoesisInstance.cpp b/Source/NoesisRuntime/Private/NoesisInstance.cpp index 5f37960..2706945 100644 --- a/Source/NoesisRuntime/Private/NoesisInstance.cpp +++ b/Source/NoesisRuntime/Private/NoesisInstance.cpp @@ -164,13 +164,13 @@ class NoesisTextBoxTextInputMethodContext : public ITextInputMethodContext virtual bool GetTextBounds(const uint32 InBeginIndex, const uint32 InLength, FVector2D& OutPosition, FVector2D& OutSize) override { Noesis::Rect TextRangeBounds = TextBox->GetRangeBounds(InBeginIndex, InBeginIndex + InLength); - Noesis::Visual* ContentHost = TextBox->GetContentHost(); + Noesis::Visual* ContentHost = TextBox->GetTextView(); - if (Noesis::ScrollViewer* ScrollViewer = NsDynamicCast(ContentHost)) + if (Noesis::ScrollViewer* ScrollViewer = Noesis::DynamicCast(ContentHost)) { ContentHost = ScrollViewer; } - else if (Noesis::Decorator* Decorator = NsDynamicCast(ContentHost)) + else if (Noesis::Decorator* Decorator = Noesis::DynamicCast(ContentHost)) { ContentHost = Decorator; } @@ -262,7 +262,7 @@ void UNoesisInstance::InitInstance() Noesis::Ptr DataContext = Noesis::Ptr(NoesisCreateComponentForUObject(this)); - Xaml.Reset(NsDynamicCast(BaseXaml->LoadXaml().GetPtr())); + Xaml.Reset(Noesis::DynamicCast(BaseXaml->LoadXaml().GetPtr())); if (Xaml) { @@ -370,7 +370,20 @@ void UNoesisInstance::Update(float InLeft, float InTop, float InWidth, float InH { XamlView->SetSize(Width, Height); XamlView->SetIsPPAAEnabled(EnablePPAA); - XamlView->SetTessellationQuality((Noesis::TessellationQuality)TessellationQuality); + Noesis::TessellationMaxPixelError mpe = Noesis::TessellationMaxPixelError::MediumQuality(); + switch (TessellationQuality) + { + case ENoesisTessellationQuality::Low: + mpe = Noesis::TessellationMaxPixelError::LowQuality(); + break; + case ENoesisTessellationQuality::Medium: + mpe = Noesis::TessellationMaxPixelError::MediumQuality(); + break; + case ENoesisTessellationQuality::High: + mpe = Noesis::TessellationMaxPixelError::HighQuality(); + break; + } + XamlView->SetTessellationMaxPixelError(mpe); XamlView->SetFlags((uint32)RenderFlags); XamlView->Update(GetTimeSeconds() - StartTime); } @@ -388,7 +401,7 @@ FVector2D UNoesisInstance::GetSize() const void UNoesisInstance::OnPreviewGotKeyboardFocus(Noesis::BaseComponent* Component, const Noesis::KeyboardFocusChangedEventArgs& Args) { const Noesis::TypeClass* NewFocusClass = Args.newFocus->GetClassType(); - const Noesis::TypeClass* TextBoxClass = Noesis::TextBox::StaticGetClassType(); + const Noesis::TypeClass* TextBoxClass = Noesis::TextBox::StaticGetClassType(nullptr); if (!FPlatformApplicationMisc::RequiresVirtualKeyboard()) { if (NewFocusClass == TextBoxClass || NewFocusClass->IsDescendantOf(TextBoxClass)) @@ -426,7 +439,7 @@ void UNoesisInstance::OnPreviewGotKeyboardFocus(Noesis::BaseComponent* Component void UNoesisInstance::OnPreviewLostKeyboardFocus(Noesis::BaseComponent* Component, const Noesis::KeyboardFocusChangedEventArgs& Args) { const Noesis::TypeClass* OldFocusClass = Args.oldFocus->GetClassType(); - const Noesis::TypeClass* TextBoxClass = Noesis::TextBox::StaticGetClassType(); + const Noesis::TypeClass* TextBoxClass = Noesis::TextBox::StaticGetClassType(nullptr); if (!FPlatformApplicationMisc::RequiresVirtualKeyboard()) { if (OldFocusClass == TextBoxClass || OldFocusClass->IsDescendantOf(TextBoxClass)) @@ -457,7 +470,7 @@ struct NoesisHitTestVisibleTester { if (!Hit) { - Noesis::UIElement* Element = NsDynamicCast(Visual); + Noesis::UIElement* Element = Noesis::DynamicCast(Visual); if (Element && Element->GetIsEnabled()) { Hit = Element; diff --git a/Source/NoesisRuntime/Private/NoesisInteractivity.cpp b/Source/NoesisRuntime/Private/NoesisInteractivity.cpp new file mode 100644 index 0000000..f91128a --- /dev/null +++ b/Source/NoesisRuntime/Private/NoesisInteractivity.cpp @@ -0,0 +1,86 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NoesisGUI - http://www.noesisengine.com +// Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved. +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#define NS_APP_INTERACTIVITY_EXPORTS +#if PLATFORM_WINDOWS || PLATFORM_XBOXONE +#pragma warning(push) +#pragma warning(disable:4426) +#endif +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/App.Interactivity.cpp" +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/AttachableObject.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/Behavior.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/BehaviorCollection.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/ChangePropertyAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/ComparisonCondition.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/ComparisonLogic.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/ConditionalExpression.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/ConditionBehavior.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/ControlStoryboardAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/DataBindingHelper.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/DataTrigger.Interactivity.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/EventTrigger.Interactivity.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/EventTriggerBase.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/GoToStateAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/Interaction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/InvokeCommandAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/KeyTrigger.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/LaunchUriOrFileAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/MouseDragElementBehavior.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/PlaySoundAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/PropertyChangedTrigger.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/RemoveElementAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/SelectAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/SelectAllAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/SetFocusAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/StoryboardAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/StoryboardCompletedTrigger.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/StoryboardTrigger.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/StyleInteraction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TargetedTriggerAction.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TimerTrigger.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TranslateZoomRotateBehavior.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TriggerAction.Interactivity.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TriggerActionCollection.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TriggerBase.Interactivity.cpp" +NS_END_COLD_REGION +#include "NoesisSDK/Src/Packages/App/Interactivity/Src/TriggerCollection.cpp" +NS_END_COLD_REGION +#if PLATFORM_WINDOWS || PLATFORM_XBOXONE +#pragma warning(pop) +#endif diff --git a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp index bcfc0bc..f5739d1 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp +++ b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp @@ -22,6 +22,9 @@ #include "Widgets/Input/IVirtualKeyboardEntry.h" #include "Framework/Application/SlateApplication.h" +// Engine includes +#include "ActiveSound.h" + // Projects includes #include "Interfaces/IPluginManager.h" @@ -35,6 +38,8 @@ // Noesis includes #include "NoesisSDK.h" +extern "C" void NsRegisterReflectionAppInteractivity(Noesis::ComponentFactory*, bool); + static void NoesisErrorHandler(const char* Filename, uint32 Line, const char* Desc, bool Fatal) { if (Fatal) @@ -46,28 +51,32 @@ static void NoesisErrorHandler(const char* Filename, uint32 Line, const char* De } DECLARE_DWORD_COUNTER_STAT(TEXT("NoesisMemory"), STAT_NoesisMemory, STATGROUP_Noesis); -class NoesisMemoryAllocator : public Noesis::MemoryAllocator +void* NoesisAllocationCallbackUserData = nullptr; +void* NoesisAlloc(void* UserData, size_t Size) { -public: + void* Result = FMemory::Malloc(Size); + INC_DWORD_STAT_BY(STAT_NoesisMemory, FMemory::GetAllocSize(Result)); + return Result; +} - virtual void* Alloc(SIZE_T Size) override - { - void* Result = FMemory::Malloc(Size); - INC_DWORD_STAT_BY(STAT_NoesisMemory, FMemory::GetAllocSize(Result)); - return Result; - } +void* NoesisRealloc(void* UserData, void* Ptr, size_t Size) +{ + DEC_DWORD_STAT_BY(STAT_NoesisMemory, FMemory::GetAllocSize(Ptr)); + void* Result = FMemory::Realloc(Ptr, Size); + INC_DWORD_STAT_BY(STAT_NoesisMemory, FMemory::GetAllocSize(Result)); + return Result; +} - virtual void* Realloc(void* Ptr, SIZE_T Size) override - { - return FMemory::Realloc(Ptr, Size); - } +void NoesisDealloc(void* UserData, void* Ptr) +{ + DEC_DWORD_STAT_BY(STAT_NoesisMemory, FMemory::GetAllocSize(Ptr)); + FMemory::Free(Ptr); +} - virtual void Dealloc(void* Ptr) - { - DEC_DWORD_STAT_BY(STAT_NoesisMemory, FMemory::GetAllocSize(Ptr)); - FMemory::Free(Ptr); - } -}; +size_t NoesisAllocSize(void* UserData, void* Ptr) +{ + return FMemory::GetAllocSize(Ptr); +} static void NoesisLogHandler(const char* File, uint32_t Line, uint32_t Level, const char* Channel, const char* Message) { @@ -344,38 +353,80 @@ void ShowPasswordBoxVirtualKeyboard(Noesis::PasswordBox* PasswordBox) PasswordBoxVirtualKeyboardEntry = NewPasswordBoxVirtualKeyboardEntry; } -bool NoesisShowSoftwareKeyboard(void* UserData, Noesis::UIElement* FocusedElement) +void NoesisSoftwareKeyboardCallback(void* UserData, Noesis::UIElement* FocusedElement, bool Open) { - if (FocusedElement) + if (Open) { - const Noesis::TypeClass* NewFocusClass = FocusedElement->GetClassType(); - const Noesis::TypeClass* TextBoxClass = Noesis::TextBox::StaticGetClassType(); - const Noesis::TypeClass* PasswordBoxClass = Noesis::PasswordBox::StaticGetClassType(); - if (FPlatformApplicationMisc::RequiresVirtualKeyboard()) + if (FocusedElement) { - if (NewFocusClass == TextBoxClass || NewFocusClass->IsDescendantOf(TextBoxClass)) + const Noesis::TypeClass* NewFocusClass = FocusedElement->GetClassType(); + const Noesis::TypeClass* TextBoxClass = Noesis::TextBox::StaticGetClassType(nullptr); + const Noesis::TypeClass* PasswordBoxClass = Noesis::PasswordBox::StaticGetClassType(nullptr); + if (FPlatformApplicationMisc::RequiresVirtualKeyboard()) { - Noesis::TextBox* TextBox = (Noesis::TextBox*)FocusedElement; - - ShowTextBoxVirtualKeyboard(TextBox); + if (NewFocusClass == TextBoxClass || NewFocusClass->IsDescendantOf(TextBoxClass)) + { + Noesis::TextBox* TextBox = (Noesis::TextBox*)FocusedElement; + + ShowTextBoxVirtualKeyboard(TextBox); + } + else if (NewFocusClass == PasswordBoxClass || NewFocusClass->IsDescendantOf(PasswordBoxClass)) + { + Noesis::PasswordBox* PasswordBox = (Noesis::PasswordBox*)FocusedElement; + + ShowPasswordBoxVirtualKeyboard(PasswordBox); + } } - else if (NewFocusClass == PasswordBoxClass || NewFocusClass->IsDescendantOf(PasswordBoxClass)) - { - Noesis::PasswordBox* PasswordBox = (Noesis::PasswordBox*)FocusedElement; + } + } + else + { + if (FSlateApplication::IsInitialized() && FPlatformApplicationMisc::RequiresVirtualKeyboard()) + { + FSlateApplication::Get().ShowVirtualKeyboard(false, FSlateApplication::Get().GetUserIndexForKeyboard()); + } + } +} - ShowPasswordBoxVirtualKeyboard(PasswordBox); +void NoesisPlaySoundCallback(void* UserData, const char* Filename, float Volume) +{ +#if WITH_EDITOR + if (GIsEditor) + { + bool IsInGame = false; + for (const FWorldContext& Context : GEngine->GetWorldContexts()) + { + if (Context.WorldType == EWorldType::PIE || Context.WorldType == EWorldType::Game) + { + IsInGame = true; } } + + if (!IsInGame) + return; } +#endif - return false; -} + FString SoundName = Filename; + USoundWave* Sound = LoadObject(nullptr, SoundName[0] == TEXT('/') ? *SoundName : *(FString(TEXT("/")) + SoundName)); -void NoesisHideSoftwareKeyboard(void* UserData) -{ - if (FSlateApplication::IsInitialized() && FPlatformApplicationMisc::RequiresVirtualKeyboard()) + if (!Sound) + return; + + if (GEngine) { - FSlateApplication::Get().ShowVirtualKeyboard(false, FSlateApplication::Get().GetUserIndexForKeyboard()); + FAudioDevice* const AudioDevice = GEngine->GetActiveAudioDevice(); + if (AudioDevice) + { + FActiveSound NewActiveSound; + NewActiveSound.SetSound(Sound); + NewActiveSound.bIsUISound = true; + NewActiveSound.UserIndex = FSlateApplication::Get().GetUserIndexForKeyboard(); + NewActiveSound.Priority = Sound->Priority; + NewActiveSound.VolumeMultiplier = Volume; + + AudioDevice->AddNewActiveSound(NewActiveSound); + } } } @@ -385,7 +436,9 @@ class FNoesisRuntimeModule : public INoesisRuntimeModuleInterface // IModuleInterface interface virtual void StartupModule() override { - Noesis::GUI::Init(&NoesisErrorHandler, &NoesisLogHandler, &Allocator); + Noesis::MemoryCallbacks MemoryCallbacks{ NoesisAllocationCallbackUserData, &NoesisAlloc, &NoesisRealloc, &NoesisDealloc, &NoesisAllocSize }; + Noesis::GUI::Init(&NoesisErrorHandler, &NoesisLogHandler, &MemoryCallbacks); + NsRegisterReflectionAppInteractivity(nullptr, true); NoesisResourceProvider = new FNoesisResourceProvider(); Noesis::GUI::SetXamlProvider(NoesisResourceProvider); @@ -394,7 +447,9 @@ class FNoesisRuntimeModule : public INoesisRuntimeModuleInterface LastSelectedTextBox.Reset(); LastSelectedPasswordBox.Reset(); - Noesis::GUI::SetSoftwareKeyboardCallbacks(nullptr, &NoesisShowSoftwareKeyboard, &NoesisHideSoftwareKeyboard); + Noesis::GUI::SetSoftwareKeyboardCallback(nullptr, &NoesisSoftwareKeyboardCallback); + + Noesis::GUI::SetPlaySoundCallback(nullptr, &NoesisPlaySoundCallback); NoesisRuntimeModuleInterface = this; @@ -439,7 +494,6 @@ class FNoesisRuntimeModule : public INoesisRuntimeModuleInterface FNoesisResourceProvider* NoesisResourceProvider; FDelegateHandle PostGarbageCollectConditionalBeginDestroyDelegateHandle; FDelegateHandle PostEngineInitDelegateHandle; - NoesisMemoryAllocator Allocator; }; INoesisRuntimeModuleInterface* FNoesisRuntimeModule::NoesisRuntimeModuleInterface = 0; diff --git a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h index c3c45f3..6da1a5a 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h +++ b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h @@ -73,3 +73,4 @@ #include "NoesisRuntimeClasses.h" #include "NoesisRuntimeModule.h" + diff --git a/Source/NoesisRuntime/Private/NoesisSupport.cpp b/Source/NoesisRuntime/Private/NoesisSupport.cpp index cbf972f..2502f49 100644 --- a/Source/NoesisRuntime/Private/NoesisSupport.cpp +++ b/Source/NoesisRuntime/Private/NoesisSupport.cpp @@ -31,7 +31,7 @@ void CollectElements(Noesis::FrameworkElement* Element, TArray(Noesis::LogicalTreeHelper::GetChild(Element, ElementIndex)); + Noesis::FrameworkElement* ChildElement = Noesis::DynamicPtrCast(Noesis::LogicalTreeHelper::GetChild(Element, ElementIndex)); if (ChildElement) { CollectElements(ChildElement, Elements); diff --git a/Source/NoesisRuntime/Private/NoesisTypeClass.cpp b/Source/NoesisRuntime/Private/NoesisTypeClass.cpp index 038e471..1995feb 100644 --- a/Source/NoesisRuntime/Private/NoesisTypeClass.cpp +++ b/Source/NoesisRuntime/Private/NoesisTypeClass.cpp @@ -122,14 +122,14 @@ class NoesisEnumWrapper : public Noesis::BoxedValue return &Value; } - bool Equals(Noesis::BaseObject* BaseObject) const override + bool Equals(const Noesis::BaseObject* BaseObject) const override { if (this == BaseObject) { return true; } - NoesisEnumWrapper* EnumWrapper = NsDynamicCast(BaseObject); + const NoesisEnumWrapper* EnumWrapper = Noesis::DynamicCast(BaseObject); if (EnumWrapper) { return EnumWrapper->Value == Value; @@ -179,7 +179,7 @@ Noesis::Ptr GetProperty(void* BasePointer, UProperty* Pro template void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA >()); @@ -217,7 +217,7 @@ Noesis::Ptr GetProperty(void* BasePoin template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - NoesisEnumWrapper* BoxedValue = NsDynamicCast(Value); + NoesisEnumWrapper* BoxedValue = Noesis::DynamicCast(Value); if (BoxedValue) { if (UEnumProperty* EnumProperty = Cast(Property)) @@ -252,7 +252,7 @@ Noesis::Ptr GetProperty(void* BasePointer, template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -281,7 +281,7 @@ Noesis::Ptr GetProperty(void* BasePointer, template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -305,7 +305,7 @@ Noesis::Ptr GetProperty(void* BasePointer, template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -329,7 +329,7 @@ Noesis::Ptr GetProperty(void* BasePointer, template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -353,7 +353,7 @@ Noesis::Ptr GetProperty(void* BasePoin template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -377,7 +377,7 @@ Noesis::Ptr GetProperty(void* BaseP template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -401,7 +401,7 @@ Noesis::Ptr GetProperty(void* BasePoint template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -425,7 +425,7 @@ Noesis::Ptr GetProperty(void* BasePoint template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -449,7 +449,7 @@ Noesis::Ptr GetProperty(void* BasePointe template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoxedValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoxedValue = Noesis::DynamicCast*>(Value); if (BoxedValue) { check(Property->IsA()); @@ -472,7 +472,7 @@ Noesis::Ptr GetProperty(void* BasePointer, UPropert template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* BoolValue = NsDynamicCast*>(Value); + Noesis::Boxed* BoolValue = Noesis::DynamicCast*>(Value); if (BoolValue) { check(Property->IsA()); @@ -502,7 +502,7 @@ Noesis::Ptr GetProperty(void* BasePointer, UPro template<> void SetProperty(void* BasePointer, UProperty* Property, Noesis::BaseComponent* Value) { - Noesis::Boxed* StrValue = NsDynamicCast*>(Value); + Noesis::Boxed* StrValue = Noesis::DynamicCast*>(Value); if (StrValue) { if (Property->IsA()) @@ -627,63 +627,28 @@ class NoesisValueArrayWrapperBase : public Noesis::BaseComponent, public Noesis: public: // IList interface - virtual uint32 Count() const override + virtual int32 Count() const override { - return (uint32)ComponentArray.Num(); + return ComponentArray.Num(); } - virtual Noesis::BaseComponent* Get(uint32 Index) const override + virtual Noesis::Ptr GetComponent(uint32 Index) const override { - return ComponentArray[Index].GetPtr(); + return ComponentArray[Index]; } - virtual void Set(uint32 Index, Noesis::BaseComponent* Item) override + virtual void SetComponent(uint32 Index, Noesis::BaseComponent* Item) override { } - virtual void Set(uint32 Index, const char* Item) override - { - } - - virtual uint32 Add(Noesis::BaseComponent* Item) override - { - return ~0; - } - - virtual uint32 Add(const char* Item) override - { - check(false); - return 0; - } - - virtual void Clear() override - { - } - - virtual bool Contains(Noesis::BaseComponent* Item) const override - { - return IndexOf(Item) != -1; - } - - virtual int IndexOf(Noesis::BaseComponent* Item) const override + virtual int32 AddComponent(Noesis::BaseComponent* Item) override { return -1; } - virtual void Insert(uint32 Index, Noesis::BaseComponent* Item) override - { - } - - virtual void Insert(uint32 Index, const char* Item) override - { - } - - virtual void Remove(Noesis::BaseComponent* Item) override - { - } - - virtual void RemoveAt(uint32 Index) override + virtual int IndexOfComponent(Noesis::BaseComponent* Item) const override { + return ComponentArray.Find(Noesis::Ptr(Item)); } // End of IList interface @@ -721,7 +686,7 @@ class NoesisArrayWrapperBase : public Noesis::BaseComponent, public Noesis::ILis { public: NoesisArrayWrapperBase(void* BasePointer, UArrayProperty* ArrayProperty, UProperty* ArrayInnerProperty) - : InnerProperty(ArrayInnerProperty), ArrayPointer(ArrayProperty->ContainerPtrToValuePtr(BasePointer)), ArrayHelper(ArrayProperty, ArrayPointer) + : InnerProperty(ArrayInnerProperty), ArrayPointer(ArrayProperty->ContainerPtrToValuePtr(BasePointer)), ArrayHelper(ArrayProperty, ArrayPointer), PreviousCount(INDEX_NONE) { check(InnerProperty->GetOffset_ForDebug() == 0); ArrayMap.Add(ArrayPointer, this); @@ -755,99 +720,51 @@ class NoesisArrayWrapperBase : public Noesis::BaseComponent, public Noesis::ILis protected: virtual Noesis::Ptr NativeGet(uint32 Index) const = 0; virtual void NativeSet(uint32 Index, Noesis::BaseComponent* Item) = 0; - uint32 NativeSize() { return (uint32)ArrayHelper.Num(); } + int32 NativeSize() const { return ArrayHelper.Num(); } void NativeInsert(uint32 Index) { ArrayHelper.InsertValues(Index); } void NativeClear() { ArrayHelper.EmptyValues(); } void NativeRemoveAt(uint32 Index) { ArrayHelper.RemoveValues(Index); } public: // IList interface - virtual uint32 Count() const override + virtual int32 Count() const override { - return (uint32)ComponentArray.Num(); + return NativeSize(); } - virtual Noesis::BaseComponent* Get(uint32 Index) const override + virtual Noesis::Ptr GetComponent(uint32 Index) const override { - return ComponentArray[Index].GetPtr(); + return NativeGet(Index); } - virtual void Set(uint32 Index, Noesis::BaseComponent* Item) override + virtual void SetComponent(uint32 Index, Noesis::BaseComponent* Item) override { + NotifyPreSet(Index); NativeSet(Index, Item); - NotifySet(Index); + NotifyPostSet(Index); } - virtual void Set(uint32 Index, const char* Item) override - { - check(false); - } - - virtual uint32 Add(Noesis::BaseComponent* Item) override + virtual int32 AddComponent(Noesis::BaseComponent* Item) override { int32 Index = NativeSize(); NativeInsert(Index); NativeSet(Index, Item); - NotifyInsert(Index); - return (uint32)Index; + NotifyPostInsert(Index); + return Index; } - virtual uint32 Add(const char* Item) override - { - check(false); - return 0; - } - - virtual void Clear() override - { - NativeClear(); - NotifyClear(); - } - - virtual bool Contains(Noesis::BaseComponent* Item) const override - { - return IndexOf(Item) != -1; - } - - virtual int IndexOf(Noesis::BaseComponent* Item) const override + virtual int IndexOfComponent(Noesis::BaseComponent* Item) const override { for (uint32 Index = 0; Index != Count(); ++Index) { - if (ComponentArray[Index] == Item || (ComponentArray[Index] && ComponentArray[Index]->Equals(Item))) + Noesis::BaseComponent* ItemAtIndex = NativeGet(Index); + if (ItemAtIndex && ItemAtIndex->Equals(Item)) { return Index; } } return -1; } - - virtual void Insert(uint32 Index, Noesis::BaseComponent* Item) override - { - NativeInsert(Index); - Set(Index, Item); - NotifyInsert(Index); - } - - virtual void Insert(uint32 Index, const char* Item) override - { - ArrayHelper.InsertValues(Index); - Set(Index, Item); - } - - virtual void Remove(Noesis::BaseComponent* Item) override - { - uint32 IndexOfItem = IndexOf(Item); - if (IndexOfItem != -1) - { - RemoveAt(IndexOfItem); - } - } - - virtual void RemoveAt(uint32 Index) override - { - NativeRemoveAt(Index); - NotifyRemoveAt(Index); - } // End of IList interface virtual Noesis::NotifyCollectionChangedEventHandler& CollectionChanged() override @@ -855,92 +772,76 @@ class NoesisArrayWrapperBase : public Noesis::BaseComponent, public Noesis::ILis return CollectionChangedHandler; } - void NotifyAdd() + void NotifyPostAdd() { uint32 Index = NativeSize() - 1; - NotifyInsert(Index); + NotifyPostInsert(Index); } - void NotifyInsert(uint32 Index) + void NotifyPostInsert(uint32 Index) { - if (Index >= (uint32)ComponentArray.Num()) - { - ComponentArray.SetNum(Index + 1); - } Noesis::Ptr Item = NativeGet(Index); - ComponentArray[Index] = Item; Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Add, -1, Index, nullptr, Item.GetPtr()); CollectionChangedHandler(this, CollectionChangedArgs); } - void NotifySet(uint32 Index) + void NotifyPreSet(int32 Index) { - if (Index >= (uint32)ComponentArray.Num()) - { - ComponentArray.SetNum(Index + 1); - } - Noesis::Ptr OldItem = ComponentArray[Index]; + check(ItemToDelete == nullptr); + ItemToDelete = NativeGet(Index); + } + + void NotifyPostSet(int32 Index) + { + check(ItemToDelete != nullptr); Noesis::Ptr NewItem = NativeGet(Index); - ComponentArray[Index] = NewItem; - Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Replace, Index, Index, OldItem.GetPtr(), NewItem.GetPtr()); + Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Replace, Index, Index, ItemToDelete.GetPtr(), NewItem.GetPtr()); CollectionChangedHandler(this, CollectionChangedArgs); + ItemToDelete.Reset(); } - void NotifyClear() + void NotifyPostClear() { - ComponentArray.Empty(); - - Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Reset, -1, -1, nullptr, nullptr); - CollectionChangedHandler(this, CollectionChangedArgs); + NotifyPostChanged(); } - void NotifyRemoveAt(uint32 Index) + void NotifyPreRemoveAt(int32 Index) { - if (Index >= (uint32)ComponentArray.Num()) - { - ComponentArray.SetNum(Index + 1); - } - Noesis::Ptr Item = ComponentArray[Index]; - ComponentArray.RemoveAt(Index); + check(ItemToDelete == nullptr); + ItemToDelete = NativeGet(Index); + } - Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Remove, Index, -1, Item.GetPtr(), nullptr); + void NotifyPostRemoveAt(int32 Index) + { + check(ItemToDelete != nullptr); + Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Remove, Index, -1, ItemToDelete.GetPtr(), nullptr); CollectionChangedHandler(this, CollectionChangedArgs); + ItemToDelete.Reset(); } - void NotifyChanged() + void NotifyPostChanged() { - uint32 Count = FMath::Min(NativeSize(), (uint32)ComponentArray.Num()); - for (int32 Index = 0; Index != Count; ++Index) - { - NotifySet(Index); - } - - NotifyResize(); + Noesis::NotifyCollectionChangedEventArgs CollectionChangedArgs(Noesis::NotifyCollectionChangedAction_Reset, -1, -1, nullptr, nullptr); + CollectionChangedHandler(this, CollectionChangedArgs); } - void NotifyAppend(uint32 NumItems) + void NotifyPreAppend() { - uint32 Count = NativeSize(); - for (uint32 Index = Count - NumItems; Index != Count; ++Index) - { - NotifyInsert(Index); - } + check(PreviousCount == INDEX_NONE); + PreviousCount = NativeSize(); } - void NotifyResize() + void NotifyPostAppend() { + check(PreviousCount != INDEX_NONE); uint32 Count = NativeSize(); - while ((uint32)ComponentArray.Num() < Count) - { - NotifyInsert((uint32)ComponentArray.Num()); - } - - while ((uint32)ComponentArray.Num() > Count) + for (uint32 Index = PreviousCount; Index != Count; ++Index) { - NotifyRemoveAt((uint32)ComponentArray.Num() - 1); + NotifyPostInsert(Index); } + PreviousCount = INDEX_NONE; } NS_IMPLEMENT_INLINE_REFLECTION(NoesisArrayWrapperBase, Noesis::BaseComponent) @@ -956,7 +857,8 @@ class NoesisArrayWrapperBase : public Noesis::BaseComponent, public Noesis::ILis UProperty* InnerProperty; void* ArrayPointer; mutable FScriptArrayHelper ArrayHelper; - TArray > ComponentArray; + Noesis::Ptr ItemToDelete; + int32 PreviousCount; }; template @@ -967,14 +869,6 @@ class NoesisArrayWrapper : public NoesisArrayWrapperBase : NoesisArrayWrapperBase(BasePointer, ArrayProperty, ArrayInnerProperty) { check(InnerProperty->GetOffset_ForDebug() == 0); - - ComponentArray.Empty(); - - for (int32 Index = 0; Index != NativeSize(); ++Index) - { - Noesis::Ptr Item = NativeGet(Index); - ComponentArray.Add(Item); - } } virtual Noesis::Ptr NativeGet(uint32 Index) const override @@ -1040,6 +934,8 @@ class NoesisFunctionWrapper : public Noesis::BaseCommand } private: + NS_IMPLEMENT_INLINE_REFLECTION_(NoesisFunctionWrapper, Noesis::BaseCommand) + UObject* Object; UFunction* Function; UFunction* CanExecuteFunction; @@ -1099,9 +995,9 @@ class NoesisStructWrapper : public Noesis::BaseComponent return ""; } - bool Equals(Noesis::BaseObject* BaseObject) const override + bool Equals(const Noesis::BaseObject* BaseObject) const override { - NoesisStructWrapper* Wrapper = NsDynamicCast(BaseObject); + const NoesisStructWrapper* Wrapper = Noesis::DynamicCast(BaseObject); return Wrapper && Struct == Wrapper->Struct && Struct->CompareScriptStruct(BasePointer, Wrapper->BasePointer, PPF_None); } @@ -1110,7 +1006,7 @@ class NoesisStructWrapper : public Noesis::BaseComponent return 0; } - static const Noesis::TypeClass* StaticGetClassType(Noesis::T2T* = 0) + static const Noesis::TypeClass* StaticGetClassType(Noesis::TypeTag* = 0) { static const Noesis::TypeClass* Type; @@ -1192,9 +1088,9 @@ class NoesisObjectWrapper : public Noesis::BaseComponent, public Noesis::INotify return TCHARToNsString(*Object->GetPathName()); } - bool Equals(Noesis::BaseObject* BaseObject) const override + bool Equals(const Noesis::BaseObject* BaseObject) const override { - NoesisObjectWrapper* Wrapper = NsDynamicCast(BaseObject); + const NoesisObjectWrapper* Wrapper = Noesis::DynamicCast(BaseObject); return Wrapper && Object == Wrapper->Object; } @@ -1203,7 +1099,7 @@ class NoesisObjectWrapper : public Noesis::BaseComponent, public Noesis::INotify return Object->GetUniqueID(); } - static const Noesis::TypeClass* StaticGetClassType(Noesis::T2T* = 0) + static const Noesis::TypeClass* StaticGetClassType(Noesis::TypeTag* = 0) { static const Noesis::TypeClass* Type; @@ -1281,7 +1177,7 @@ class NoesisObjectWrapper : public Noesis::BaseComponent, public Noesis::INotify template bool SetArrayProperty(const TypePropertyData& Data, Noesis::BaseComponent* Value) { - NoesisArrayWrapperBase* ValueWrapper = NsDynamicCast(Value); + NoesisArrayWrapperBase* ValueWrapper = Noesis::DynamicCast(Value); if (ValueWrapper) { FScriptArrayHelper SourceArrayHelper = ValueWrapper->ArrayHelper; @@ -1300,7 +1196,7 @@ class NoesisObjectWrapper : public Noesis::BaseComponent, public Noesis::INotify } Noesis::Ptr Wrapper = GetArrayProperty(Data); - ((NoesisArrayWrapperBase*)Wrapper.GetPtr())->NotifyChanged(); + ((NoesisArrayWrapperBase*)Wrapper.GetPtr())->NotifyPostChanged(); return false; } @@ -1447,9 +1343,9 @@ void UStructTypeFiller(Noesis::Type* Type) check(RegisterNameMap.Find(NsStringToFString(ClassName))); UScriptStruct* Class = LoadObject(nullptr, **RegisterNameMap.Find(NsStringToFString(ClassName))); - const Noesis::TypeClass* ParentType = NoesisStructWrapper::StaticGetClassType(); + const Noesis::TypeClass* ParentType = NoesisStructWrapper::StaticGetClassType(nullptr); - NoesisTypeClass* TypeClass = NsDynamicCast(Type); + NoesisTypeClass* TypeClass = Noesis::DynamicCast(Type); TypeClass->Class = Class; check(TypeClass); @@ -1699,14 +1595,14 @@ void UClassTypeFiller(Noesis::Type* Type) check(RegisterNameMap.Find(NsStringToFString(ClassName))); UClass* Class = LoadObject(nullptr, **RegisterNameMap.Find(NsStringToFString(ClassName))); - const Noesis::TypeClass* ParentType = NoesisObjectWrapper::StaticGetClassType(); + const Noesis::TypeClass* ParentType = NoesisObjectWrapper::StaticGetClassType(nullptr); UClass* SuperClass = Class->GetSuperClass(); if (SuperClass) { ParentType = NoesisCreateTypeClassForUClass(SuperClass); } - NoesisTypeClass* TypeClass = NsDynamicCast(Type); + NoesisTypeClass* TypeClass = Noesis::DynamicCast(Type); TypeClass->Class = Class; check(TypeClass); @@ -2105,7 +2001,7 @@ Noesis::TypeClass* NoesisCreateTypeClassForUClass(UClass* Class) } if (!TypeClass) { - TypeClass = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentClassName), &UClassTypeCreator, &UClassTypeFiller)); + TypeClass = Noesis::DynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentClassName), &UClassTypeCreator, &UClassTypeFiller)); ClassMap.Add(Class, MakeTuple(TypeClass, PersistentClassName)); #if WITH_EDITOR @@ -2131,7 +2027,7 @@ void UEnumTypeFiller(Noesis::Type* Type) UEnum* Enum = LoadObject(nullptr, **RegisterNameMap.Find(NsStringToFString(EnumName))); - Noesis::TypeEnum* TypeEnum = NsDynamicCast(Type); + Noesis::TypeEnum* TypeEnum = Noesis::DynamicCast(Type); check(TypeEnum); Noesis::Ptr MetaData = *new Noesis::TypeId(EnumName); @@ -2170,7 +2066,7 @@ Noesis::TypeEnum* NoesisCreateTypeEnumForUEnum(UEnum* Enum) } if (!TypeEnum) { - TypeEnum = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentEnumName), &UEnumTypeCreator, &UEnumTypeFiller)); + TypeEnum = Noesis::DynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentEnumName), &UEnumTypeCreator, &UEnumTypeFiller)); NsSymbol EnumConverterId = Noesis::IdOf("Converter", TypeEnum); NsGetKernel()->GetComponentFactory()->RegisterComponent(EnumConverterId, NsSymbol::Null(), &CallbackCreateEnumConverter); @@ -2236,8 +2132,8 @@ void NoesisDestroyAllTypes() void AssignStruct(void* BasePointer, UStructProperty* StructProperty, Noesis::BaseComponent* Value) { - check(Value->GetClassType()->IsDescendantOf(NoesisStructWrapper::StaticGetClassType())); - check(NsDynamicCast(Value->GetClassType())); + check(Value->GetClassType()->IsDescendantOf(NoesisStructWrapper::StaticGetClassType(nullptr))); + check(Noesis::DynamicCast(Value->GetClassType())); check(((NoesisTypeClass*)Value->GetClassType())->Class == StructProperty->Struct); void* Dest = StructProperty->ContainerPtrToValuePtr(BasePointer); @@ -2259,7 +2155,7 @@ Noesis::TypeClass* NoesisCreateTypeClassForUStruct(UScriptStruct* Class) } if (!TypeClass) { - TypeClass = NsDynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentClassName), &UClassTypeCreator, &UStructTypeFiller)); + TypeClass = Noesis::DynamicCast(Noesis::TypeCreate::Create(Noesis::TypeInfo(PersistentClassName), &UClassTypeCreator, &UStructTypeFiller)); ClassMap.Add(Class, MakeTuple(TypeClass, PersistentClassName)); } @@ -2274,9 +2170,8 @@ Noesis::Ptr NoesisCreateComponentForUStruct(UScriptStruct } Noesis::TypeClass* TypeClass = NoesisCreateTypeClassForUStruct(Struct); - Noesis::MemoryManager* MemoryManager = NsGetKernel()->GetMemoryManager(); SIZE_T AllocSize = sizeof(NoesisStructWrapper) + Struct->GetStructureSize(); - void* Memory = MemoryManager->Alloc(AllocSize); + void* Memory = NoesisAlloc(NoesisAllocationCallbackUserData, AllocSize); FMemory::Memzero(Memory, AllocSize); void* Dest = ((NoesisStructWrapper*)Memory) + 1; Struct->CopyScriptStruct(Dest, Src, 1); @@ -2322,7 +2217,7 @@ NOESISRUNTIME_API Noesis::Ptr NoesisCreateComponentForUOb NOESISRUNTIME_API UObject* NoesisCreateUObjectForComponent(Noesis::BaseComponent* Component) { - NoesisObjectWrapper* Wrapper = NsDynamicCast(Component); + NoesisObjectWrapper* Wrapper = Noesis::DynamicCast(Component); if (Wrapper) { return Wrapper->Object; @@ -2335,8 +2230,8 @@ NOESISRUNTIME_API UObject* NoesisCreateUObjectForComponent(Noesis::BaseComponent NOESISRUNTIME_API void NoesisCopyUStructFromComponent(UScriptStruct* Struct, Noesis::BaseComponent* Component, void* Dest) { - check(Component->GetClassType()->IsDescendantOf(NoesisStructWrapper::StaticGetClassType())); - check(NsDynamicCast(Component->GetClassType())); + check(Component->GetClassType()->IsDescendantOf(NoesisStructWrapper::StaticGetClassType(nullptr))); + check(Noesis::DynamicCast(Component->GetClassType())); check(((NoesisTypeClass*)Component->GetClassType())->Class == Struct); void* Src = ((NoesisStructWrapper*)Component) + 1; @@ -2375,7 +2270,7 @@ void NoesisNotifyArrayPropertyChanged(UObject* Owner, FName ArrayPropertyName) NoesisArrayWrapperBase* Array = (NoesisArrayWrapperBase*)(ArrayTypeProperty->GetComponent(Wrapper).GetPtr()); if (Array) { - Array->NotifyChanged(); + Array->NotifyPostChanged(); } } #if DO_CHECK // Skip in shipping build @@ -2387,91 +2282,113 @@ void NoesisNotifyArrayPropertyChanged(UObject* Owner, FName ArrayPropertyName) } } -void NoesisNotifyArrayPropertyAdd(void* ArrayPointer) +void NoesisNotifyArrayPropertyPostAdd(void* ArrayPointer) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyAdd); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyAdd(); + Array->NotifyPostAdd(); } } -void NoesisNotifyArrayPropertyChanged(void* ArrayPointer) +void NoesisNotifyArrayPropertyPostChanged(void* ArrayPointer) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyChanged); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyChanged(); + Array->NotifyPostChanged(); + } +} + +void NoesisNotifyArrayPropertyPreAppend(void* ArrayPointer) +{ + SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyAppend); + NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); + if (ArrayWrapperPtr) + { + NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; + Array->NotifyPreAppend(); } } -void NoesisNotifyArrayPropertyAppend(void* ArrayPointer, int32 NumItems) +void NoesisNotifyArrayPropertyPostAppend(void* ArrayPointer) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyAppend); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyAppend(NumItems); + Array->NotifyPostAppend(); } } -void NoesisNotifyArrayPropertyInsert(void* ArrayPointer, int32 Index) +void NoesisNotifyArrayPropertyPostInsert(void* ArrayPointer, int32 Index) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyInsert); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyInsert(Index); + Array->NotifyPostInsert(Index); } } -void NoesisNotifyArrayPropertyRemove(void* ArrayPointer, int32 Index) +void NoesisNotifyArrayPropertyPreRemove(void* ArrayPointer, int32 Index) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyRemove); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyRemoveAt(Index); + Array->NotifyPreRemoveAt(Index); } } -void NoesisNotifyArrayPropertyClear(void* ArrayPointer) +void NoesisNotifyArrayPropertyPostRemove(void* ArrayPointer, int32 Index) +{ + SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyRemove); + NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); + if (ArrayWrapperPtr) + { + NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; + Array->NotifyPostRemoveAt(Index); + } +} + +void NoesisNotifyArrayPropertyPostClear(void* ArrayPointer) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyClear); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyClear(); + Array->NotifyPostClear(); } } -void NoesisNotifyArrayPropertyResize(void* ArrayPointer) +void NoesisNotifyArrayPropertyPreSet(void* ArrayPointer, int32 Index) { - SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertyResize); + SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertySet); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifyResize(); + Array->NotifyPreSet(Index); } } -void NoesisNotifyArrayPropertySet(void* ArrayPointer, int32 Index) +void NoesisNotifyArrayPropertyPostSet(void* ArrayPointer, int32 Index) { SCOPE_CYCLE_COUNTER(STAT_NoesisNotifyArrayPropertySet); NoesisArrayWrapperBase** ArrayWrapperPtr = ArrayMap.Find(ArrayPointer); if (ArrayWrapperPtr) { NoesisArrayWrapperBase* Array = *ArrayWrapperPtr; - Array->NotifySet(Index); + Array->NotifyPostSet(Index); } } diff --git a/Source/NoesisRuntime/Private/NoesisXaml.cpp b/Source/NoesisRuntime/Private/NoesisXaml.cpp index 3bd83ab..ac122c4 100644 --- a/Source/NoesisRuntime/Private/NoesisXaml.cpp +++ b/Source/NoesisRuntime/Private/NoesisXaml.cpp @@ -11,7 +11,7 @@ static void SetApplicationResources() if (ApplicationResources) { Noesis::Ptr Component = Noesis::GUI::LoadXaml(TCHARToNsString(*ApplicationResources->GetPathName()).c_str()); - Noesis::ResourceDictionary* Dictionary = NsDynamicCast(Component.GetPtr()); + Noesis::ResourceDictionary* Dictionary = Noesis::DynamicCast(Component.GetPtr()); if (Dictionary) { Noesis::GUI::SetApplicationResources(Dictionary); diff --git a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp index 1f125ba..4c293e3 100644 --- a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp +++ b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp @@ -33,13 +33,6 @@ class FNoesisTexture : public Noesis::Texture return (uint32)ShaderResourceTexture->GetSizeY(); } - virtual Noesis::TextureFormat::Enum GetFormat() const override - { - EPixelFormat PixelFormat = ShaderResourceTexture->GetFormat(); - check(PixelFormat == PF_B8G8R8A8 || PixelFormat == PF_B8G8R8A8 || PixelFormat == PF_G8 || PixelFormat == PF_DXT1 || PixelFormat == PF_DXT3 || PixelFormat == PF_DXT5); - return Format; - } - virtual bool HasMipMaps() const override { return (bool)(ShaderResourceTexture->GetNumMips() > 1); @@ -234,21 +227,12 @@ Noesis::Ptr FNoesisRenderDevice::CreateTexture(UTexture* InText } switch (Texture->ShaderResourceTexture->GetFormat()) { - case PF_B8G8R8A8: - Texture->Format = Noesis::TextureFormat::BGRA8; + case PF_R8G8B8A8: + Texture->Format = Noesis::TextureFormat::RGBA8; break; case PF_G8: Texture->Format = Noesis::TextureFormat::R8; break; - case PF_DXT1: - Texture->Format = Noesis::TextureFormat::BC1; - break; - case PF_DXT3: - Texture->Format = Noesis::TextureFormat::BC2; - break; - case PF_DXT5: - Texture->Format = Noesis::TextureFormat::BC3; - break; } return Noesis::Ptr(*Texture); @@ -256,7 +240,7 @@ Noesis::Ptr FNoesisRenderDevice::CreateTexture(UTexture* InText const Noesis::DeviceCaps& FNoesisRenderDevice::GetCaps() const { - static Noesis::DeviceCaps Caps = { 0.f, VertexBufferSize, IndexBufferSize, false, { true, true, true, true, true, true } }; + static Noesis::DeviceCaps Caps = { 0.f, VertexBufferSize, IndexBufferSize, false }; return Caps; } @@ -264,7 +248,7 @@ Noesis::Ptr FNoesisRenderDevice::CreateRenderTarget(const { uint32 SizeX = (uint32)Width; uint32 SizeY = (uint32)Height; - uint8 Format = (uint8)PF_B8G8R8A8; + uint8 Format = (uint8)PF_R8G8B8A8; uint32 NumMips = 1; uint32 Flags = 0; uint32 TargetableTextureFlags = (uint32)TexCreate_RenderTargetable; @@ -284,7 +268,7 @@ Noesis::Ptr FNoesisRenderDevice::CreateRenderTarget(const RenderTarget->Texture = *new FNoesisTexture(); RenderTarget->ColorTarget = ColorTarget; RenderTarget->Texture->ShaderResourceTexture = ShaderResourceTexture; - RenderTarget->Texture->Format = Noesis::TextureFormat::BGRA8; + RenderTarget->Texture->Format = Noesis::TextureFormat::RGBA8; RenderTarget->DepthStencilTarget = DepthStencilTarget; FName TextureName = FName(Label); @@ -305,13 +289,13 @@ Noesis::Ptr FNoesisRenderDevice::CloneRenderTarget(const c uint32 SizeX = SharedRenderTarget->Texture->ShaderResourceTexture->GetSizeX(); uint32 SizeY = SharedRenderTarget->Texture->ShaderResourceTexture->GetSizeY(); - uint8 Format = (uint8)PF_B8G8R8A8; + uint8 Format = (uint8)PF_R8G8B8A8; uint32 NumMips = 1; uint32 Flags = TexCreate_ResolveTargetable | TexCreate_ShaderResource; FRHIResourceCreateInfo CreateInfo; FTexture2DRHIRef ShaderResourceTexture = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, 1, Flags, CreateInfo); RenderTarget->Texture->ShaderResourceTexture = ShaderResourceTexture; - RenderTarget->Texture->Format = Noesis::TextureFormat::BGRA8; + RenderTarget->Texture->Format = Noesis::TextureFormat::RGBA8; return Noesis::Ptr(*RenderTarget); } @@ -320,7 +304,7 @@ Noesis::Ptr FNoesisRenderDevice::CreateTexture(const char* Labe { uint32 SizeX = (uint32)Width; uint32 SizeY = (uint32)Height; - EPixelFormat Formats[Noesis::TextureFormat::Count] = { PF_B8G8R8A8, PF_B8G8R8A8, PF_G8, PF_DXT1, PF_DXT3, PF_DXT5 }; + EPixelFormat Formats[Noesis::TextureFormat::Count] = { PF_R8G8B8A8, PF_G8 }; uint8 Format = (uint8)Formats[TextureFormat]; uint32 NumMips = (uint32)NumLevels; uint32 NumSamples = 1; @@ -350,7 +334,7 @@ void FNoesisRenderDevice::UpdateTexture(Noesis::Texture* InTexture, uint32 Level UpdateRegion.DestY = (uint32)Y; UpdateRegion.Width = (uint32)Width; UpdateRegion.Height = (uint32)Height; - uint32 SourcePitch = (uint32)Width * ((Texture->ShaderResourceTexture->GetFormat() == PF_B8G8R8A8) ? 4 : 1); + uint32 SourcePitch = (uint32)Width * ((Texture->ShaderResourceTexture->GetFormat() == PF_R8G8B8A8) ? 4 : 1); const uint8* SourceData = (const uint8*)Data; RHIUpdateTexture2D(Texture->ShaderResourceTexture, MipIndex, UpdateRegion, SourcePitch, SourceData); diff --git a/Source/NoesisRuntime/Public/NoesisRuntimeModule.h b/Source/NoesisRuntime/Public/NoesisRuntimeModule.h index 51b5fcd..b8098d7 100644 --- a/Source/NoesisRuntime/Public/NoesisRuntimeModule.h +++ b/Source/NoesisRuntime/Public/NoesisRuntimeModule.h @@ -17,6 +17,12 @@ DECLARE_STATS_GROUP(TEXT("Noesis"), STATGROUP_Noesis, STATCAT_Advanced); #define NOESISGUI_MODULE_NAME "NoesisRuntime" +NOESISRUNTIME_API extern void* NoesisAllocationCallbackUserData; +NOESISRUNTIME_API void* NoesisAlloc(void* UserData, size_t Size); +NOESISRUNTIME_API void* NoesisRealloc(void* UserData, void* Ptr, size_t Size); +NOESISRUNTIME_API void NoesisDealloc(void* UserData, void* Ptr); +NOESISRUNTIME_API size_t NoesisAllocSize(void* UserData, void* Ptr); + class NOESISRUNTIME_API INoesisRuntimeModuleInterface : public IModuleInterface { public: diff --git a/Source/NoesisRuntime/Public/NoesisTypeClass.h b/Source/NoesisRuntime/Public/NoesisTypeClass.h index a76c012..d67c802 100644 --- a/Source/NoesisRuntime/Public/NoesisTypeClass.h +++ b/Source/NoesisRuntime/Public/NoesisTypeClass.h @@ -38,14 +38,16 @@ StructType NoesisGetUStructFromComponent(Noesis::BaseComponent* Component) NOESISRUNTIME_API void NoesisNotifyPropertyChanged(class UObject*, FName); NOESISRUNTIME_API void NoesisNotifyArrayPropertyChanged(class UObject*, FName); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyAdd(void*); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyChanged(void*); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyAppend(void*, int32); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyInsert(void*, int32); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyRemove(void*, int32); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyClear(void*); -NOESISRUNTIME_API void NoesisNotifyArrayPropertyResize(void*); -NOESISRUNTIME_API void NoesisNotifyArrayPropertySet(void*, int32); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostAdd(void*); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostChanged(void*); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPreAppend(void*); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostAppend(void*); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostInsert(void*, int32); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPreRemove(void*, int32); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostRemove(void*, int32); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostClear(void*); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPreSet(void*, int32); +NOESISRUNTIME_API void NoesisNotifyArrayPropertyPostSet(void*, int32); NOESISRUNTIME_API void NoesisGarbageCollected(); void NoesisReflectionRegistryCallback(NsSymbol TypeId, Noesis::ReflectionRegistry* Registry); void NoesisRegisterTypes(); From 4a8eabc6401fb7c51f88f72ed5286242a31c2fa1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Feb 2019 00:11:43 +0100 Subject: [PATCH 19/20] Updated README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 52e281c..966f286 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ In order to use NoesisGUI in your UE4 project, you're going to need: * This Unreal Engine plugin. -* The NoesisGUI SDK version 2.1. You can download it from [our website](https://noesisengine.com). +* The NoesisGUI SDK version 2.2 beta. You can download it from [our website](https://noesisengine.com). * Python with some additional modules to run the installation script (tested with Python 2.7 and 3.6). @@ -63,7 +63,7 @@ With versions of Unreal Engine built from the source code in GitHub you can use 1. Copy the contents of this repository into `[UE4Root]/Engine/Plugins/NoesisGUI` if you want to use it as an Engine plugin, or `[ProjectRoot]/Plugins/NoesisGUI` if you choose to use it as a Project plugin. We'll refer to the directory where you install the plugin as `[NoesisGUIRoot]` from now on. `[UE4Root]` is the directory where you installed the engine from the Epic Games Launcher, or the directory where you cloned the GitHub repository. -2. Download the NoesisGUI SDK version 2.1 from [our developer portal](http://noesisengine.com/forums/) and extract it into `[NoesisGUIRoot]/Source/Noesis/NoesisSDK`. +2. Download the NoesisGUI SDK version 2.2 beta from [our developer portal](https://www.noesisengine.com/forums/viewtopic.php?f=14&t=1491) and extract it into `[NoesisGUIRoot]/Source/Noesis/NoesisSDK`. 3. If you haven't installed the required Python modules, or you want to verify they are correctly installed, you can execute `InstallPythonPrerequisites.bat` and `InstallPythonPrerequisites.command` from the Command Prompt on Windows or Terminal on Mac. Navigate to the plugin directory and execute them from there. These will test whether the required modules are installed or not, and will install them if they're not present. You only need to install them once, so you don't need to perform this step every time you update the plugin or Unreal Engine. From 2325ae73bae05d739e4f1cb7c58a3a11c0479c5a Mon Sep 17 00:00:00 2001 From: GeorgeR Date: Sat, 29 Jun 2019 19:04:43 +1000 Subject: [PATCH 20/20] a --- NoesisGUI.uplugin | 4 +- Source/Noesis/Noesis.Build.cs | 24 +- .../Noesis/NoesisSDK/COPY_NOESIS_SDK_HERE.txt | 20 -- .../NoesisEditor/Classes/NoesisXamlFactory.h | 2 +- .../Private/K2Node_NoesisAssignAndNotify.cpp | 4 +- .../Private/NoesisBlueprintCompiler.cpp | 18 +- .../Private/NoesisBlueprintCompiler.h | 8 + .../NoesisBlueprintCompilerContext.cpp | 7 + .../Private/NoesisBlueprintCompilerContext.h | 4 + .../Private/NoesisEditorModule.cpp | 19 ++ .../Private/NoesisXamlFactory.cpp | 311 +----------------- Source/NoesisRuntime/NoesisRuntime.Build.cs | 27 +- .../NoesisRuntime/Private/NoesisInstance.cpp | 105 +++--- .../Private/NoesisRuntimeModule.cpp | 2 +- .../Private/NoesisRuntimePrivatePCH.h | 4 +- .../Private/Render/NoesisRenderDevice.cpp | 15 +- 16 files changed, 180 insertions(+), 394 deletions(-) delete mode 100644 Source/Noesis/NoesisSDK/COPY_NOESIS_SDK_HERE.txt diff --git a/NoesisGUI.uplugin b/NoesisGUI.uplugin index 94a9a13..b72fc2e 100644 --- a/NoesisGUI.uplugin +++ b/NoesisGUI.uplugin @@ -10,7 +10,7 @@ "DocsURL": "http://www.noesisengine.com/docs", "MarketplaceURL": "", "SupportURL": "http://www.noesisengine.com/forums", - "EngineVersion": "4.21.0", + "EngineVersion": "", "CanContainContent": true, "Installed": true, "Modules": [ @@ -25,4 +25,4 @@ "LoadingPhase": "Default" } ] -} \ No newline at end of file +} diff --git a/Source/Noesis/Noesis.Build.cs b/Source/Noesis/Noesis.Build.cs index 21be35b..e63f6b7 100644 --- a/Source/Noesis/Noesis.Build.cs +++ b/Source/Noesis/Noesis.Build.cs @@ -68,8 +68,9 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) string NoesisLibPath = NoesisBasePath + "Lib/windows_x86_64/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); + PublicFrameworks.Add("CoreText"); - string BaseTargetPath = ""; + string BaseTargetPath = ""; if (Target.LinkType == TargetLinkType.Monolithic) { if (Target.ProjectFile != null) @@ -122,15 +123,18 @@ public Noesis(ReadOnlyTargetRules Target) : base(Target) string NoesisDylibPath = "/NoesisSDK/Bin/osx/Noesis.dylib"; RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath); } - else if (Target.Platform == UnrealTargetPlatform.IOS) - { - string NoesisLibPath = NoesisBasePath + "Lib/ios/"; - PublicLibraryPaths.Add(NoesisLibPath); - PublicAdditionalLibraries.Add("Noesis"); - - PublicAdditionalShadowFiles.Add(Path.Combine(NoesisLibPath, "libNoesis.a")); - } - else if (Target.Platform == UnrealTargetPlatform.Android) + else if (Target.Platform == UnrealTargetPlatform.IOS) + { + string NoesisLibPath = NoesisBasePath + "Lib/ios/"; + PublicLibraryPaths.Add(NoesisLibPath); + PublicAdditionalLibraries.Add("Noesis"); + + if (Target.Version.MinorVersion <= 21) + { + PublicAdditionalShadowFiles.Add(Path.Combine(NoesisLibPath, "libNoesis.a")); + } + } + else if (Target.Platform == UnrealTargetPlatform.Android) { string NoesisLibPath = NoesisBasePath + "Bin/android_arm/"; PublicLibraryPaths.Add(NoesisLibPath); diff --git a/Source/Noesis/NoesisSDK/COPY_NOESIS_SDK_HERE.txt b/Source/Noesis/NoesisSDK/COPY_NOESIS_SDK_HERE.txt deleted file mode 100644 index 1ddb0d6..0000000 --- a/Source/Noesis/NoesisSDK/COPY_NOESIS_SDK_HERE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Please, download the NoesisGUI SDK 2.1 from https://noesisengine.com and unpack its contents here. - -The directory structure after the SDK is unpacked should be as follows: - -[UE4Root] -+-- Engine - +-- Plugins - +-- NoesisGUI - +-- Binaries - +-- Content - +-- Resources - +-- Shaders - +-- Source - +-- Noesis - +-- NoesisSDK <- The directory containing this file - +-- Bin - +-- Include - +-- Lib - +-- NoesisEditor - +-- NoesisRuntime \ No newline at end of file diff --git a/Source/NoesisEditor/Classes/NoesisXamlFactory.h b/Source/NoesisEditor/Classes/NoesisXamlFactory.h index b9a99db..77dc0ef 100644 --- a/Source/NoesisEditor/Classes/NoesisXamlFactory.h +++ b/Source/NoesisEditor/Classes/NoesisXamlFactory.h @@ -39,7 +39,7 @@ class NOESISEDITOR_API UNoesisXamlFactory : public UFactory protected: void ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& XamlDescriptors); - void ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& FontDescriptors); + UFont* ImportFontFamily(FString Path, FString Family, FString BasePackageName, FString ProjectURIRoot); void ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& ImageDescriptors); UNoesisResourceResolver* GetResourceResolver(); diff --git a/Source/NoesisEditor/Private/K2Node_NoesisAssignAndNotify.cpp b/Source/NoesisEditor/Private/K2Node_NoesisAssignAndNotify.cpp index 7719575..e38a5b9 100644 --- a/Source/NoesisEditor/Private/K2Node_NoesisAssignAndNotify.cpp +++ b/Source/NoesisEditor/Private/K2Node_NoesisAssignAndNotify.cpp @@ -136,14 +136,14 @@ static UBlueprintFieldNodeSpawner* CreateSpawnerFromMemberOrParam(TSubclassOf()->bShowFriendlyNames; FText const VarName = bShowFriendlyNames ? FText::FromString(UEditorEngine::GetFriendlyName(VarProperty)) : FText::FromName(VarProperty->GetFName()); - // @TODO: NodeClass could be modified post Create() + // @#todo NodeClass could be modified post Create() MenuSignature.MenuName = FText::Format(LOCTEXT("UK2Node_NoesisAssignAndNotifyTitle", "Set {0} w/ NotifyChanged"), VarName); MenuSignature.Tooltip = GetPropertyTooltip(VarProperty); // add at least one character, so that PrimeDefaultUiSpec() doesn't // attempt to query the template node // - // @TODO: maybe UPROPERTY() fields should have keyword metadata like functions + // @#todo maybe UPROPERTY() fields should have keyword metadata like functions if (MenuSignature.Keywords.IsEmpty()) { // want to set it to something so we won't end up back in this condition diff --git a/Source/NoesisEditor/Private/NoesisBlueprintCompiler.cpp b/Source/NoesisEditor/Private/NoesisBlueprintCompiler.cpp index dbe64dc..2c9d5ec 100644 --- a/Source/NoesisEditor/Private/NoesisBlueprintCompiler.cpp +++ b/Source/NoesisEditor/Private/NoesisBlueprintCompiler.cpp @@ -13,9 +13,8 @@ bool FNoesisBlueprintCompiler::CanCompile(const UBlueprint* Blueprint) return Blueprint->IsA(UNoesisBlueprint::StaticClass()); } -void FNoesisBlueprintCompiler::PreCompile(UBlueprint* Blueprint) -{ -} +#if ENGINE_MINOR_VERSION <= 21 +void FNoesisBlueprintCompiler::PreCompile(UBlueprint* Blueprint) { } void FNoesisBlueprintCompiler::Compile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompilerOptions, FCompilerResultsLog& Results, TArray* ObjLoaded) { @@ -25,6 +24,17 @@ void FNoesisBlueprintCompiler::Compile(UBlueprint* Blueprint, const FKismetCompi check(Compiler.NewClass); } -void FNoesisBlueprintCompiler::PostCompile(UBlueprint* Blueprint) +void FNoesisBlueprintCompiler::PostCompile(UBlueprint* Blueprint) { } +#else +void FNoesisBlueprintCompiler::PreCompile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompilerOptions) { } + +void FNoesisBlueprintCompiler::Compile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompilerOptions, FCompilerResultsLog& Results) { + UNoesisBlueprint* NoesisBlueprint = CastChecked(Blueprint); + FNoesisBlueprintCompilerContext Compiler(NoesisBlueprint, Results, CompilerOptions); + Compiler.Compile(); + check(Compiler.NewClass); } + +void FNoesisBlueprintCompiler::PostCompile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompileOptions) { } +#endif diff --git a/Source/NoesisEditor/Private/NoesisBlueprintCompiler.h b/Source/NoesisEditor/Private/NoesisBlueprintCompiler.h index a8c6553..d4ce9e9 100644 --- a/Source/NoesisEditor/Private/NoesisBlueprintCompiler.h +++ b/Source/NoesisEditor/Private/NoesisBlueprintCompiler.h @@ -5,13 +5,21 @@ #pragma once +#include "KismetCompilerModule.h" + class FNoesisBlueprintCompiler : public IBlueprintCompiler { // IBlueprintCompiler interface virtual bool CanCompile(const UBlueprint* Blueprint) override; +#if ENGINE_MINOR_VERSION <= 21 virtual void PreCompile(UBlueprint* Blueprint) override; virtual void Compile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompilerOptions, FCompilerResultsLog& Results, TArray* ObjLoaded) override; virtual void PostCompile(UBlueprint* Blueprint) override; +#else + virtual void PreCompile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompileOptions) override; + virtual void Compile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompileOptions, FCompilerResultsLog& Results) override; + virtual void PostCompile(UBlueprint* Blueprint, const FKismetCompilerOptions& CompileOptions) override; +#endif // End of IBlueprintCompiler interface public: diff --git a/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp b/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp index 91c068b..fe07563 100644 --- a/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp +++ b/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.cpp @@ -8,10 +8,17 @@ // UnrealEd includes #include "Kismet2/KismetReinstanceUtilities.h" +#if ENGINE_MINOR_VERSION < 22 FNoesisBlueprintCompilerContext::FNoesisBlueprintCompilerContext(UNoesisBlueprint* NoesisBlueprint, FCompilerResultsLog& Results, const FKismetCompilerOptions& CompilerOptions, TArray* ObjLoaded) : Super(NoesisBlueprint, Results, CompilerOptions, ObjLoaded) { } +#else +FNoesisBlueprintCompilerContext::FNoesisBlueprintCompilerContext(UNoesisBlueprint* SourceSketch, FCompilerResultsLog& InMessageLog, const FKismetCompilerOptions& InCompilerOptions) + : Super(SourceSketch, InMessageLog, InCompilerOptions) +{ +} +#endif FNoesisBlueprintCompilerContext::~FNoesisBlueprintCompilerContext() { diff --git a/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.h b/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.h index da327f9..a1bf21f 100644 --- a/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.h +++ b/Source/NoesisEditor/Private/NoesisBlueprintCompilerContext.h @@ -12,7 +12,11 @@ class FNoesisBlueprintCompilerContext : public FKismetCompilerContext typedef FKismetCompilerContext Super; public: +#if ENGINE_MINOR_VERSION < 22 FNoesisBlueprintCompilerContext(UNoesisBlueprint* SourceSketch, FCompilerResultsLog& InMessageLog, const FKismetCompilerOptions& InCompilerOptions, TArray* InObjLoaded); +#else + FNoesisBlueprintCompilerContext(UNoesisBlueprint* SourceSketch, FCompilerResultsLog& InMessageLog, const FKismetCompilerOptions& InCompilerOptions); +#endif virtual ~FNoesisBlueprintCompilerContext(); // FKismetCompilerContext interface diff --git a/Source/NoesisEditor/Private/NoesisEditorModule.cpp b/Source/NoesisEditor/Private/NoesisEditorModule.cpp index 85a6770..de116c0 100644 --- a/Source/NoesisEditor/Private/NoesisEditorModule.cpp +++ b/Source/NoesisEditor/Private/NoesisEditorModule.cpp @@ -144,7 +144,11 @@ void OnObjectPropertyChanged(UObject* Object, struct FPropertyChangedEvent& Even TSharedPtr GetCompilerForNoesisBlueprint(UBlueprint* Blueprint, FCompilerResultsLog& Results, const FKismetCompilerOptions& CompilerOptions) { UNoesisBlueprint* NoesisBlueprint = CastChecked(Blueprint); +#if ENGINE_MINOR_VERSION < 22 return TSharedPtr(new FNoesisBlueprintCompilerContext(NoesisBlueprint, Results, CompilerOptions, nullptr)); +#else + return TSharedPtr(new FNoesisBlueprintCompilerContext(NoesisBlueprint, Results, CompilerOptions)); +#endif } class FNoesisEditorModule : public INoesisEditorModuleInterface @@ -152,6 +156,11 @@ class FNoesisEditorModule : public INoesisEditorModuleInterface public: // IModuleInterface interface virtual void StartupModule() override + { + FCoreDelegates::OnPostEngineInit.AddRaw(this, &FNoesisEditorModule::OnPostEngineInit); + } + + void OnPostEngineInit() { // Register slate style overrides FNoesisStyle::Initialize(); @@ -192,7 +201,12 @@ class FNoesisEditorModule : public INoesisEditorModuleInterface NoesisEditorModuleInterface = this; +#if ENGINE_MINOR_VERSION < 22 AssetImportHandle = FEditorDelegates::OnAssetPostImport.AddStatic(&OnObjectReimported); +#else + auto ImportSubsystem = GEditor->GetEditorSubsystem(); + AssetImportHandle = ImportSubsystem->OnAssetPostImport.AddStatic(&OnObjectReimported); +#endif ObjectPropertyChangedHandle = FCoreUObjectDelegates::OnObjectPropertyChanged.AddStatic(&OnObjectPropertyChanged); } @@ -233,7 +247,12 @@ class FNoesisEditorModule : public INoesisEditorModuleInterface if (AssetImportHandle.IsValid()) { +#if ENGINE_MINOR_VERSION < 22 FEditorDelegates::OnAssetPostImport.Remove(AssetImportHandle); +#else + //auto ImportSubsystem = GEditor->GetEditorSubsystem(); + //ImportSubsystem->OnAssetPostImport.Remove(AssetImportHandle); +#endif } if (ObjectPropertyChangedHandle.IsValid()) diff --git a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp index f50dc3a..9101b36 100644 --- a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp +++ b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp @@ -7,6 +7,7 @@ // UnrealEd includes #include "Settings/EditorLoadingSavingSettings.h" +#include "Paths.h" // NoesisEditor includes #include "NoesisEditorModule.h" @@ -27,27 +28,20 @@ void ExtractPaths(FString FileUri, FString BaseFilePath, FString BasePackage, FS { FilePath = FileUri; FString PackUri = TEXT("pack://application:,,,"); - int32 PackUriIndex = FilePath.Find(PackUri); + auto PackUriIndex = FilePath.Find(PackUri); if (PackUriIndex != INDEX_NONE) - { FilePath = FilePath.RightChop(PackUriIndex + PackUri.Len()); - } FString ComponentUri = TEXT(";component"); - int32 ComponentUriIndex = FilePath.Find(ComponentUri); + auto ComponentUriIndex = FilePath.Find(ComponentUri); if (ComponentUriIndex != INDEX_NONE) - { FilePath = FilePath.RightChop(ComponentUriIndex + ComponentUri.Len()); - } + FilePath = FilePath.RightChop(ComponentUriIndex + ComponentUri.Len()); if (FPaths::IsRelative(FilePath)) - { FilePath = BaseFilePath / FilePath; - } else - { FilePath = FilePath; - } FPaths::RemoveDuplicateSlashes(FilePath); FPaths::NormalizeFilename(FilePath); @@ -66,117 +60,6 @@ void ExtractPaths(FString FileUri, FString BaseFilePath, FString BasePackage, FS FPaths::CollapseRelativeDirectories(FilePath); } -TArray ScanKeyword(FString Text, FString Keyword) -{ - TArray Strings; - - int32 TextLen = Text.Len(); - int32 KeywordIndex = INDEX_NONE; - while ((KeywordIndex = Text.Find(Keyword, ESearchCase::IgnoreCase, ESearchDir::FromStart, KeywordIndex)) != INDEX_NONE) - { - int32 StartIndex = KeywordIndex; - while (StartIndex >= 0 && Text[StartIndex] != TEXT('\"') && Text[StartIndex] != TEXT('\'') && Text[StartIndex] != TEXT('>')) - { - --StartIndex; - } - - int32 EndIndex = KeywordIndex; - while (EndIndex < TextLen && Text[EndIndex] != TEXT('\"') && Text[EndIndex] != TEXT('\'') && Text[EndIndex] != TEXT('<')) - { - ++EndIndex; - } - - if (StartIndex >= 0 && EndIndex < TextLen) - { - Strings.Add(Text.Left(EndIndex).RightChop(StartIndex + 1)); - } - - KeywordIndex = EndIndex + 1; - } - - return Strings; -} - -TArray ParseForXamls(FString XamlText) -{ - TArray XamlDescriptors; - - TArray Strings = ScanKeyword(XamlText, TEXT(".xaml")); - for (auto String : Strings) - { - FXamlDescriptor& XamlDescriptor = *new(XamlDescriptors)FXamlDescriptor; - XamlDescriptor.Path = String; - } - - return XamlDescriptors; -} - -void UNoesisXamlFactory::ImportXamls(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& XamlDescriptors) -{ - auto XamlFact = NewObject(); - XamlFact->AddToRoot(); - - for (auto& XamlDescriptor : XamlDescriptors) - { - FString XamlPath; - FString FileName; - FString PackagePath; - FString XamlName; - ExtractPaths(XamlDescriptor.Path, Path, BasePackageName, ProjectURIRoot, XamlPath, FileName, PackagePath, XamlName); - - UPackage* XamlPackage = NULL; - - FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; - XamlObjectPath = GetResourceResolver()->ResolvePath(XamlObjectPath, ENoesisResourceType::NRT_Xaml); - UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); - - if (!ExistingXaml) - { - const FString Suffix(TEXT("")); - - XamlPackage = CreatePackage(NULL, *(PackagePath / XamlName)); - } - else - { - XamlPackage = ExistingXaml->GetOutermost(); - XamlPackage->FullyLoad(); - ExistingXaml->DestroyThumbnailRenderData(); - } - - FString FullFilename = XamlPath / FileName; - FPaths::MakeStandardFilename(FullFilename); - bool Cancelled = false; - UNoesisXaml* Xaml = (UNoesisXaml*)XamlFact->ImportObject(UNoesisXaml::StaticClass(), XamlPackage, *XamlName, RF_Standalone | RF_Public, FullFilename, nullptr, Cancelled); - - if (Xaml != NULL) - { - // Notify the asset registry - FAssetRegistryModule::AssetCreated(Xaml); - - // Set the dirty flag so this package will get saved later - XamlPackage->SetDirtyFlag(true); - } - - XamlDescriptor.Xaml = Xaml; - } - - XamlFact->RemoveFromRoot(); -} - -TArray ParseForFonts(FString XamlText) -{ - TArray FontDescriptors; - - TArray Strings = ScanKeyword(XamlText, TEXT("#")); - for (auto String : Strings) - { - FFontDescriptor& FontDescriptor = *new(FontDescriptors)FFontDescriptor; - FontDescriptor.Family = String; - } - - return FontDescriptors; -} - unsigned long StreamRead(FT_Stream Stream, unsigned long Offset, unsigned char* Buffer, unsigned long Count) { FMemory::Memcpy(Buffer, (uint8*)Stream->descriptor.pointer + Offset, Count); @@ -185,22 +68,10 @@ unsigned long StreamRead(FT_Stream Stream, unsigned long Offset, unsigned char* void StreamClose(FT_Stream) {} -void UNoesisXamlFactory::ImportFonts(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& FontDescriptors) +UFont* UNoesisXamlFactory::ImportFontFamily(FString Path, FString Family, FString BasePackageName, FString ProjectURIRoot) { FString BaseUri, FamilyName; Family.Split(TEXT("#"), &BaseUri, &FamilyName); - TSet UniqueFontFamilies; - for (auto FontDescriptor : FontDescriptors) - { - UniqueFontFamilies.Add(FontDescriptor.Family); - } - - FontDescriptors.Empty(); - - for (auto Family : UniqueFontFamilies) - { - FString BaseUri, FamilyName; - Family.Split(TEXT("#"), &BaseUri, &FamilyName); IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); @@ -213,8 +84,10 @@ void UNoesisXamlFactory::ImportFonts(FString BasePackageName, FString ProjectURI FT_Library FTLibrary; UNoesisResourceResolver* ResourceResolver; - ScanFolderForFonts(FString InFontPackagePath, FString InFamilyName, UNoesisResourceResolver* InResourceResolver) - : FontPackagePath(InFontPackagePath), FamilyName(InFamilyName), ResourceResolver(InResourceResolver) + ScanFolderForFonts(FString FontPackagePath, FString FamilyName, UNoesisResourceResolver* ResourceResolver) + : FontPackagePath(FontPackagePath), + FamilyName(FamilyName), + ResourceResolver(ResourceResolver) { int32 Error = FT_Init_FreeType(&FTLibrary); checkf(Error == 0, TEXT("Could not init Freetype")); @@ -328,14 +201,14 @@ void UNoesisXamlFactory::ImportFonts(FString BasePackageName, FString ProjectURI FString FontFileName; FString FontPackagePath; FString FontPackageName; - ExtractPaths(BaseUri, Path, BasePackageName, ProjectURIRoot, FontFilePath, FontFileName, FontPackagePath, FontPackageName); + ExtractPaths(BaseUri, Path, BasePackageName, Family, FontFilePath, FontFileName, FontPackagePath, FontPackageName); ScanFolderForFonts Visitor(FontPackagePath, FamilyName, GetResourceResolver()); PlatformFile.IterateDirectory(*FontFilePath, Visitor); if (Visitor.Fonts.Num()) { - UPackage* FontPackage = NULL; + UPackage* FontPackage = nullptr; FString FontName = GetResourceResolver()->ResolveName(FamilyName, ENoesisResourceType::NRT_Font); FString FontObjectPath = FontPackagePath / FontName + TEXT(".") + FontName; @@ -345,7 +218,6 @@ void UNoesisXamlFactory::ImportFonts(FString BasePackageName, FString ProjectURI if (!ExistingFont) { const FString Suffix(TEXT("")); - FontPackage = CreatePackage(NULL, *(FontPackagePath / FontName)); } else @@ -368,100 +240,7 @@ void UNoesisXamlFactory::ImportFonts(FString BasePackageName, FString ProjectURI Font->CompositeFont.DefaultTypeface.Fonts = Visitor.Fonts; return Font; - FFontDescriptor& FontDescriptor = *new(FontDescriptors)FFontDescriptor; - FontDescriptor.Family = Family; - FontDescriptor.Font = Font; - } - } - } -} - -TArray ParseForImages(FString XamlText) -{ - TArray ImageDescriptors; - - TArray Strings; - auto TextureFact = NewObject(); - for (auto Format : TextureFact->Formats) - { - int32 Index; - Format.FindChar(TEXT(';'), Index); - Strings += ScanKeyword(XamlText, FString(TEXT(".")) + Format.Left(Index)); - } - - for (auto String : Strings) - { - FImageDescriptor& ImageDescriptor = *new(ImageDescriptors)FImageDescriptor; - ImageDescriptor.Path = String; - } - - return ImageDescriptors; -} - -void UNoesisXamlFactory::ImportImages(FString BasePackageName, FString ProjectURIRoot, FString Path, TArray& ImageDescriptors) -{ - auto TextureFact = NewObject(); - TextureFact->AddToRoot(); - - TSet UniqueImagePaths; - for (auto ImageDescriptor : ImageDescriptors) - { - UniqueImagePaths.Add(ImageDescriptor.Path); - } - - ImageDescriptors.Empty(); - - for (auto ImagePath : UniqueImagePaths) - { - FString TexturePath; - FString FileName; - FString PackagePath; - FString TextureName; - ExtractPaths(ImagePath, Path, BasePackageName, ProjectURIRoot, TexturePath, FileName, PackagePath, TextureName); - - TextureName = "T_" + TextureName; - - UPackage* TexturePackage = NULL; - - FString TextureObjectPath = PackagePath / TextureName + TEXT(".") + TextureName; - TextureObjectPath = GetResourceResolver()->ResolvePath(TextureObjectPath, ENoesisResourceType::NRT_Texture); - UTexture2D* ExistingTexture = LoadObject(NULL, *TextureObjectPath); - - if (!ExistingTexture) - { - const FString Suffix(TEXT("")); - - TexturePackage = CreatePackage(NULL, *(PackagePath / TextureName)); - } - else - { - TexturePackage = ExistingTexture->GetOutermost(); - TexturePackage->FullyLoad(); } - - TextureFact->SuppressImportOverwriteDialog(); - - FString FullFilename = TexturePath / FileName; - bool Cancelled = false; - UTexture2D* Texture = (UTexture2D*)TextureFact->ImportObject(UTexture2D::StaticClass(), TexturePackage, *TextureName, RF_Standalone | RF_Public, FullFilename, nullptr, Cancelled); - - if (Texture != NULL) - { - Texture->LODGroup = TEXTUREGROUP_UI; - Texture->SRGB = false; - void FixPremultipliedPNGTexture(UTexture2D*); - FixPremultipliedPNGTexture(Texture); - - // Notify the asset registry - FAssetRegistryModule::AssetCreated(Texture); - - // Set the dirty flag so this package will get saved later - TexturePackage->SetDirtyFlag(true); - } - - FImageDescriptor& ImageDescriptor = *new(ImageDescriptors)FImageDescriptor; - ImageDescriptor.Path = ImagePath; - ImageDescriptor.Texture = Texture; } return nullptr; @@ -469,9 +248,9 @@ void UNoesisXamlFactory::ImportImages(FString BasePackageName, FString ProjectUR UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn) { - FString FullFilename = GetCurrentFilename(); - FString Filename = FullFilename; - FString Directory = FPaths::GetPath(Filename); + auto FullFilename = GetCurrentFilename(); + auto Filename = FullFilename; + auto Directory = FPaths::GetPath(Filename); Filename = FPaths::GetCleanFilename(Filename); FString ProjectURIRoot; FString BasePackageName; @@ -491,61 +270,18 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, } } } + if (ProjectURIRoot.IsEmpty()) { ProjectURIRoot = FPaths::ProjectContentDir(); BasePackageName = TEXT("/Game/"); } - FPaths::MakePathRelativeTo(Directory, *ProjectURIRoot); - FString XamlText = NsStringToFString((const char*)Buffer); - - TArray Comments; - FRegexPattern CommentPattern(TEXT("")); - FRegexMatcher CommentMatcher(CommentPattern, XamlText); - - while (CommentMatcher.FindNext()) - { - Comments.Add(XamlText.Left(CommentMatcher.GetMatchEnding()).RightChop(CommentMatcher.GetMatchBeginning())); - } - - for (auto Comment : Comments) - { - XamlText = XamlText.Replace(*Comment, TEXT("")); - } - - TArray XamlDescriptors = ParseForXamls(XamlText); - ImportXamls(BasePackageName, ProjectURIRoot, Directory, XamlDescriptors); - for (auto XamlDescriptor : XamlDescriptors) - { - if (!XamlDescriptor.Xaml) - { - UE_LOG(LogNoesisEditor, Log, TEXT("Error importing XAML file %s: Referenced XAML file %s not found."), *GetCurrentFilename(), *XamlDescriptor.Path); - } - } - - TArray FontDescriptors = ParseForFonts(XamlText); - ImportFonts(BasePackageName, ProjectURIRoot, Directory, FontDescriptors); - for (auto FontDescriptor : FontDescriptors) - { - if (!FontDescriptor.Font) - { - UE_LOG(LogNoesisEditor, Log, TEXT("Error importing XAML file %s: Referenced font family %s not found."), *GetCurrentFilename(), *FontDescriptor.Family); - } - } + FPaths::MakePathRelativeTo(Directory, *ProjectURIRoot); - TArray ImageDescriptors = ParseForImages(XamlText); - ImportImages(BasePackageName, ProjectURIRoot, Directory, ImageDescriptors); - for (auto ImageDescriptor : ImageDescriptors) - { - if (!ImageDescriptor.Texture) - { - UE_LOG(LogNoesisEditor, Log, TEXT("Error importing XAML file %s: Referenced image file %s not found."), *GetCurrentFilename(), *ImageDescriptor.Path); - } - } + auto XamlText = NsStringToFString((const char*)Buffer); UNoesisXaml* NoesisXaml = nullptr; - { FString XamlPath; FString FileName; @@ -553,7 +289,7 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, FString XamlName; ExtractPaths(Filename, Directory, BasePackageName, ProjectURIRoot, XamlPath, FileName, PackagePath, XamlName); - UPackage* XamlPackage = NULL; + UPackage* XamlPackage = nullptr; FString XamlObjectPath = PackagePath / XamlName + TEXT(".") + XamlName; XamlObjectPath = GetResourceResolver()->ResolvePath(XamlObjectPath, ENoesisResourceType::NRT_Xaml); @@ -630,17 +366,6 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, Texture->SRGB = false; void FixPremultipliedPNGTexture(UTexture2D*); FixPremultipliedPNGTexture(Texture); - for (auto FontDescriptor : FontDescriptors) - { - if (FontDescriptor.Font) - { - FString FontPath = FontDescriptor.Font->GetPathName(); - FString Uri, Family; - ensure(FontDescriptor.Family.Split(TEXT("#"), &Uri, &Family)); - XamlText = XamlText.Replace(*FontDescriptor.Family, *(FontPath / TEXT("#") + Family)); - NoesisXaml->Fonts.Add(FontDescriptor.Font); - } - } FString ImagePath = Texture->GetPathName(); XamlText = XamlText.Replace(*NsStringToFString(Dependency.c_str()), *ImagePath); diff --git a/Source/NoesisRuntime/NoesisRuntime.Build.cs b/Source/NoesisRuntime/NoesisRuntime.Build.cs index f080f7f..543e948 100644 --- a/Source/NoesisRuntime/NoesisRuntime.Build.cs +++ b/Source/NoesisRuntime/NoesisRuntime.Build.cs @@ -21,8 +21,7 @@ public NoesisRuntime(ReadOnlyTargetRules Target) : base(Target) PrivateIncludePaths.AddRange( new string[] { "NoesisRuntime/Private", - } - ); + }); PublicDependencyModuleNames.AddRange( new string[] @@ -33,22 +32,28 @@ public NoesisRuntime(ReadOnlyTargetRules Target) : base(Target) "RHI", "RenderCore", "UtilityShaders", - "ShaderCore", "SlateCore", "InputCore", "UMG", "ApplicationCore", "Slate", "Projects" - } - ); + }); + + if (Target.Version.MinorVersion <= 21) + { + PublicDependencyModuleNames.AddRange( + new string[] + { + "ShaderCore", + }); + } - PrivateDependencyModuleNames.AddRange( + PrivateDependencyModuleNames.AddRange( new string[] { "Noesis", - } - ); + }); if (Target.bBuildEditor == true) { @@ -56,15 +61,13 @@ public NoesisRuntime(ReadOnlyTargetRules Target) : base(Target) new string[] { "UnrealEd" - } - ); + }); } DynamicallyLoadedModuleNames.AddRange( new string[] { "AssetRegistry" - } - ); + }); } } diff --git a/Source/NoesisRuntime/Private/NoesisInstance.cpp b/Source/NoesisRuntime/Private/NoesisInstance.cpp index 2706945..805c1c6 100644 --- a/Source/NoesisRuntime/Private/NoesisInstance.cpp +++ b/Source/NoesisRuntime/Private/NoesisInstance.cpp @@ -76,7 +76,10 @@ void FNoesisSlateElement::DrawRenderThread(FRHICommandListImmediate& RHICmdList, if (Renderer) { FTexture2DRHIRef ColorTarget = *(FTexture2DRHIRef*)InWindowBackBuffer; - if (!DepthStencilTarget.IsValid() || DepthStencilTarget->GetSizeX() != ColorTarget->GetSizeX() || DepthStencilTarget->GetSizeY() != ColorTarget->GetSizeY() || DepthStencilTarget->GetNumSamples() != ColorTarget->GetNumSamples()) + if (!DepthStencilTarget.IsValid() + || DepthStencilTarget->GetSizeX() != ColorTarget->GetSizeX() + || DepthStencilTarget->GetSizeY() != ColorTarget->GetSizeY() + || DepthStencilTarget->GetNumSamples() != ColorTarget->GetNumSamples()) { DepthStencilTarget.SafeRelease(); uint32 SizeX = ColorTarget->GetSizeX(); @@ -89,18 +92,21 @@ void FNoesisSlateElement::DrawRenderThread(FRHICommandListImmediate& RHICmdList, CreateInfo.ClearValueBinding = FClearValueBinding(0.f, 0); DepthStencilTarget = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, NumSamples, TargetableTextureFlags, CreateInfo); } - FRHIRenderTargetView ColorView(ColorTarget, 0, -1, ERenderTargetLoadAction::ELoad, ERenderTargetStoreAction::EStore); - FRHIDepthRenderTargetView DepthStencilView(DepthStencilTarget, ERenderTargetLoadAction::ENoAction, ERenderTargetStoreAction::ENoAction, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::ENoAction, - FExclusiveDepthStencil::DepthNop_StencilWrite); - FRHISetRenderTargetsInfo Info(1, &ColorView, DepthStencilView); - // Clear the stencil buffer - RHICmdList.SetRenderTargetsAndClear(Info); + + FRHIRenderPassInfo RenderPassInfo(ColorTarget, ERenderTargetActions::Load_Store, DepthStencilTarget, MakeDepthStencilTargetActions(ERenderTargetActions::DontLoad_DontStore, ERenderTargetActions::Clear_DontStore), FExclusiveDepthStencil::DepthNop_StencilWrite); + + check(RHICmdList.IsOutsideRenderPass()); + + RHICmdList.BeginRenderPass(RenderPassInfo, TEXT("NoesisOnScreen")); RHICmdList.SetViewport(Left, Top, 0.0f, Right, Bottom, 1.0f); + SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_Draw); SCOPED_DRAW_EVENT(RHICmdList, NoesisDraw); FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); Renderer->Render(FlipYAxis); FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); + + RHICmdList.EndRenderPass(); } } @@ -274,8 +280,8 @@ void UNoesisInstance::InitInstance() { Noesis::Ptr Renderer(XamlView->GetRenderer()); - ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FNoesisInstance_InitRenderer, - Noesis::Ptr, Renderer, Renderer, + ENQUEUE_RENDER_COMMAND(FNoesisInstance_InitRenderer)( + [Renderer](FRHICommandListImmediate& RHICmdList) { FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); Renderer->Init(FNoesisRenderDevice::Get()); @@ -287,6 +293,8 @@ void UNoesisInstance::InitInstance() StartTime = GetTimeSeconds(); EventInitInstance(); + + Update(0.0f, 0.0f, 256.0f, 256.0f); } Xaml->PreviewGotKeyboardFocus() += Noesis::MakeDelegate(this, &UNoesisInstance::OnPreviewGotKeyboardFocus); @@ -498,11 +506,9 @@ void UNoesisInstance::TermInstance() Xaml.Reset(); // Pass the slate element to the render thread so that it's deleted after it's shown for the last time - ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER + ENQUEUE_RENDER_COMMAND(SafeDeleteNoesisSlateElement) ( - SafeDeleteNoesisSlateElement, - Noesis::Ptr, Renderer, Renderer, - FNoesisSlateElementPtr, NoesisSlateElement, NoesisSlateElement, + [Renderer, NoesisSlateElement = NoesisSlateElement](FRHICommandListImmediate& RHICmdList) mutable { Renderer->Shutdown(); NoesisSlateElement.Reset(); @@ -549,7 +555,14 @@ void UNoesisInstance::BeginDestroy() void UNoesisInstance::SetDesignerFlags(EWidgetDesignFlags::Type NewFlags) { // Enable native events in editor - Super::SetDesignerFlags((EWidgetDesignFlags::Type)(NewFlags & ~EWidgetDesignFlags::Designing)); + if (UWorld* LocalWorld = GetWorld()) + { + auto GameInstance = LocalWorld->GetGameInstance(); + if(GameInstance) + Super::SetDesignerFlags((EWidgetDesignFlags::Type)(NewFlags & ~EWidgetDesignFlags::Designing)); + } + + Super::SetDesignerFlags(NewFlags); } void UNoesisInstance::DrawThumbnail(FIntRect ViewportRect, const FTexture2DRHIRef& BackBuffer) @@ -558,32 +571,40 @@ void UNoesisInstance::DrawThumbnail(FIntRect ViewportRect, const FTexture2DRHIRe Noesis::Ptr Renderer(XamlView->GetRenderer()); - ENQUEUE_UNIQUE_RENDER_COMMAND_THREEPARAMETER( - FNoesisXamlThumbnailRendererDrawCommand, - Noesis::Ptr, Renderer, Renderer, - bool, FlipYAxis, FlipYAxis, - const FTexture2DRHIRef&, BackBuffer, BackBuffer, - { - FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); - Renderer->UpdateRenderTree(); - if (Renderer->NeedsOffscreen()) + if (BackBuffer != nullptr) + { + ENQUEUE_RENDER_COMMAND(FNoesisXamlThumbnailRendererDrawCommand) + ( + [Renderer, FlipYAxis = FlipYAxis, BackBuffer](FRHICommandListImmediate& RHICmdList) { - Renderer->RenderOffscreen(); - } + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(&RHICmdList); + Renderer->UpdateRenderTree(); + if (Renderer->NeedsOffscreen()) + Renderer->RenderOffscreen(); - uint32 SizeX = BackBuffer->GetSizeX(); - uint32 SizeY = BackBuffer->GetSizeY(); - uint8 Format = (uint8)PF_DepthStencil; - uint32 NumMips = BackBuffer->GetNumMips(); - uint32 NumSamples = BackBuffer->GetNumSamples(); - uint32 TargetableTextureFlags = (uint32)TexCreate_DepthStencilTargetable; - FRHIResourceCreateInfo CreateInfo; - CreateInfo.ClearValueBinding = FClearValueBinding(0.f, 0); - FTexture2DRHIRef DepthStencilTarget = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, NumSamples, TargetableTextureFlags, CreateInfo); - SetRenderTarget(RHICmdList, BackBuffer, DepthStencilTarget); - Renderer->Render(FlipYAxis); - FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); - }); + uint32 SizeX = BackBuffer->GetSizeX(); + uint32 SizeY = BackBuffer->GetSizeY(); + uint8 Format = (uint8)PF_DepthStencil; + uint32 NumMips = BackBuffer->GetNumMips(); + uint32 NumSamples = BackBuffer->GetNumSamples(); + uint32 TargetableTextureFlags = (uint32)TexCreate_DepthStencilTargetable; + FRHIResourceCreateInfo CreateInfo; + CreateInfo.ClearValueBinding = FClearValueBinding(0.f, 0); + FTexture2DRHIRef ColorTarget = BackBuffer; + FTexture2DRHIRef DepthStencilTarget = RHICreateTexture2D(SizeX, SizeY, Format, NumMips, NumSamples, TargetableTextureFlags, CreateInfo); + FRHIRenderPassInfo RPInfo(ColorTarget, ERenderTargetActions::Load_Store, DepthStencilTarget, + MakeDepthStencilTargetActions(ERenderTargetActions::DontLoad_DontStore, ERenderTargetActions::Clear_DontStore), FExclusiveDepthStencil::DepthNop_StencilWrite); + + check(RHICmdList.IsOutsideRenderPass()); + RHICmdList.BeginRenderPass(RPInfo, TEXT("NoesisThumbnail")); + + Renderer->Render(FlipYAxis); + FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); + + RHICmdList.EndRenderPass(); + } + ); + } } #endif // WITH_EDITOR @@ -606,8 +627,9 @@ int32 UNoesisInstance::NativePaint(const FPaintArgs& Args, const FGeometry& Allo { Noesis::Ptr Renderer(XamlView->GetRenderer()); - ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER(FNoesisInstance_DrawOffscreen, - Noesis::Ptr, Renderer, Renderer, + ENQUEUE_RENDER_COMMAND(FNoesisInstance_DrawOffscreen) + ( + [Renderer](FRHICommandListImmediate& RHICmdList) { SCOPE_CYCLE_COUNTER(STAT_NoesisInstance_DrawOffscreen); SCOPED_DRAW_EVENT(RHICmdList, NoesisDrawOffscreen); @@ -618,7 +640,8 @@ int32 UNoesisInstance::NativePaint(const FPaintArgs& Args, const FGeometry& Allo Renderer->RenderOffscreen(); } FNoesisRenderDevice::ThreadLocal_SetRHICmdList(nullptr); - }); + } + ); const FSlateRect& MyClippingRect = MyCullingRect; diff --git a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp index f5739d1..5f36b3b 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp +++ b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp @@ -12,7 +12,7 @@ #include "Stats/Stats.h" #include "Stats/Stats2.h" -// ShaderCore includes +// RenderCore includes #include "ShaderCore.h" // ApplicationCore includes diff --git a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h index 6da1a5a..65159a2 100644 --- a/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h +++ b/Source/NoesisRuntime/Private/NoesisRuntimePrivatePCH.h @@ -20,9 +20,6 @@ #include "Kismet/KismetArrayLibrary.h" #include "EditorFramework/AssetImportData.h" -// ShaderCore includes -#include "ShaderParameterUtils.h" - // CoreUObject includes #include "UObject/UObjectGlobals.h" @@ -44,6 +41,7 @@ // RenderCore includes #include "RenderingThread.h" +#include "ShaderParameterUtils.h" // SlateCore includes #include "Widgets/SLeafWidget.h" diff --git a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp index 4c293e3..21b069f 100644 --- a/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp +++ b/Source/NoesisRuntime/Private/Render/NoesisRenderDevice.cpp @@ -350,10 +350,11 @@ void FNoesisRenderDevice::SetRenderTarget(Noesis::RenderTarget* Surface) check(RHICmdList); check(Surface); FNoesisRenderTarget* RenderTarget = (FNoesisRenderTarget*)Surface; - FRHIRenderTargetView ColorTarget(RenderTarget->ColorTarget, ERenderTargetLoadAction::EClear); - FRHIDepthRenderTargetView DepthStencilTarget(RenderTarget->DepthStencilTarget, ERenderTargetLoadAction::ENoAction, ERenderTargetStoreAction::ENoAction, ERenderTargetLoadAction::EClear, ERenderTargetStoreAction::ENoAction); - FRHISetRenderTargetsInfo RenderTargetsInfo(1, &ColorTarget, DepthStencilTarget); - RHICmdList->SetRenderTargetsAndClear(RenderTargetsInfo); + + FRHIRenderPassInfo RenderPassInfo(RenderTarget->ColorTarget, ERenderTargetActions::Clear_DontStore, RenderTarget->DepthStencilTarget, MakeDepthStencilTargetActions(ERenderTargetActions::DontLoad_DontStore, ERenderTargetActions::Clear_DontStore), FExclusiveDepthStencil::DepthNop_StencilWrite); + check(RHICmdList->IsOutsideRenderPass()); + + RHICmdList->BeginRenderPass(RenderPassInfo, TEXT("NoesisOffScreen")); RHICmdList->SetViewport(0, 0, 0.0f, RenderTarget->ColorTarget->GetSizeX(), RenderTarget->ColorTarget->GetSizeY(), 1.0f); CurrentRenderTarget = RenderTarget; } @@ -402,6 +403,9 @@ void FNoesisRenderDevice::ResolveRenderTarget(Noesis::RenderTarget* Surface, con ResolveParams.DestRect.Y2 = ResolveMaxY; RHICmdList->CopyToResolveTarget(CurrentRenderTarget->ColorTarget, CurrentRenderTarget->Texture->ShaderResourceTexture, ResolveParams); } + + check(RHICmdList->IsInsideRenderPass()); + RHICmdList->EndRenderPass(); } void FNoesisRenderDevice::EndRender() @@ -619,5 +623,6 @@ void FNoesisRenderDevice::DrawBatch(const Noesis::Batch& Batch) RHICmdList->SetStencilRef(Batch.stencilRef); RHICmdList->SetStreamSource(0, DynamicVertexBuffer, Batch.vertexOffset); - RHICmdList->DrawIndexedPrimitive(DynamicIndexBuffer, PT_TriangleList, 0, 0, VertexBufferSize, Batch.startIndex, Batch.numIndices / 3, 1); + //RHICmdList->DrawIndexedPrimitive(DynamicIndexBuffer, PT_TriangleList, 0, 0, VertexBufferSize, Batch.startIndex, Batch.numIndices / 3, 1); + RHICmdList->DrawIndexedPrimitive(DynamicIndexBuffer, 0, 0, VertexBufferSize, Batch.startIndex, Batch.numIndices / 3, 1); }