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/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. diff --git a/Source/Noesis/Noesis.Build.cs b/Source/Noesis/Noesis.Build.cs index 9eca2db..e63f6b7 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); @@ -66,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) @@ -120,18 +123,23 @@ 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); + string NoesisLib64Path = NoesisBasePath + "Bin/android_arm64/"; + PublicLibraryPaths.Add(NoesisLib64Path); PublicAdditionalLibraries.Add("Noesis"); string NoesisAplPath = "/Noesis_APL.xml"; @@ -148,5 +156,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/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/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/Classes/NoesisXamlFactory.h b/Source/NoesisEditor/Classes/NoesisXamlFactory.h index 397e0a5..77dc0ef 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); + 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/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..9101b36 100644 --- a/Source/NoesisEditor/Private/NoesisXamlFactory.cpp +++ b/Source/NoesisEditor/Private/NoesisXamlFactory.cpp @@ -7,10 +7,13 @@ // UnrealEd includes #include "Settings/EditorLoadingSavingSettings.h" +#include "Paths.h" // NoesisEditor includes #include "NoesisEditorModule.h" #include "NoesisEditorUserSettings.h" +#include "NoesisSettings.h" +#include "NoesisResourceResolver.h" UNoesisXamlFactory::UNoesisXamlFactory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) @@ -25,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()); - } if (FPaths::IsRelative(FilePath)) - { FilePath = BaseFilePath / FilePath; - } else - { FilePath = FilePath; - } FPaths::RemoveDuplicateSlashes(FilePath); FPaths::NormalizeFilename(FilePath); @@ -64,129 +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; -} - -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,288 +68,189 @@ 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* UNoesisXamlFactory::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(); - - class ScanFolderForFonts : public IPlatformFile::FDirectoryVisitor + public: + FString FontPackagePath; + FString FamilyName; + TArray Fonts; + FT_Library FTLibrary; + UNoesisResourceResolver* ResourceResolver; + + ScanFolderForFonts(FString FontPackagePath, FString FamilyName, UNoesisResourceResolver* ResourceResolver) + : FontPackagePath(FontPackagePath), + FamilyName(FamilyName), + ResourceResolver(ResourceResolver) { - 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); + ResourceResolver = nullptr; + } - 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))); + FString FontFaceName = ObjectTools::SanitizeObjectName(FPaths::GetBaseFilename(FPaths::GetBaseFilename(FilenameOrDirectory))); + FontFaceName = "FF_" + FontFaceName; - UPackage* FontFacePackage = NULL; + UPackage* FontFacePackage = NULL; - FString FontFaceObjectPath = FontPackagePath / FontFaceName + TEXT(".") + FontFaceName; - UFontFace* ExistingFontFace = LoadObject(NULL, *FontFaceObjectPath); + FString FontFaceObjectPath = FontPackagePath / FontFaceName + TEXT(".") + FontFaceName; + FontFaceObjectPath = ResourceResolver->ResolvePath(FontFaceObjectPath, ENoesisResourceType::NRT_FontFace); + UFontFace* ExistingFontFace = LoadObject(NULL, *FontFaceObjectPath); - if (!ExistingFontFace) - { - const FString Suffix(TEXT("")); - - 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, Family, 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, GetResourceResolver()); + PlatformFile.IterateDirectory(*FontFilePath, Visitor); - for (auto String : Strings) + if (Visitor.Fonts.Num()) { - FImageDescriptor& ImageDescriptor = *new(ImageDescriptors)FImageDescriptor; - ImageDescriptor.Path = String; - } + UPackage* FontPackage = nullptr; - return ImageDescriptors; -} + 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); -void 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); - - 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(); + UFontFactory* FontFactory = NewObject(); + FontFactory->bEditAfterNew = false; - 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) + 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) { - 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; @@ -496,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; @@ -558,9 +289,10 @@ 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); UNoesisXaml* ExistingXaml = LoadObject(NULL, *XamlObjectPath); if (!ExistingXaml) @@ -583,35 +315,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) + { + 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) { - if (FontDescriptor.Font) + 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); + } + } } } @@ -625,3 +397,8 @@ UObject* UNoesisXamlFactory::FactoryCreateBinary(UClass* Class, UObject* Parent, return NoesisXaml; } + +UNoesisResourceResolver* UNoesisXamlFactory::GetResourceResolver() +{ + return GetMutableDefault()->GetResourceResolver(); +} diff --git a/Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h b/Source/NoesisRuntime/Classes/NoesisFunctionLibrary.h index 48a318c..842a83d 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/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/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/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/NoesisFunctionLibrary.cpp b/Source/NoesisRuntime/Private/NoesisFunctionLibrary.cpp index 021cef2..6364100 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); @@ -38,7 +47,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 +105,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 +132,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 +160,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 +189,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 +221,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 +246,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 +274,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 +283,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 +315,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 +330,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 +377,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..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(); } } @@ -164,13 +170,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 +268,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) { @@ -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); @@ -370,7 +378,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 +409,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 +447,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 +478,7 @@ struct NoesisHitTestVisibleTester { if (!Hit) { - Noesis::UIElement* Element = NsDynamicCast(Visual); + Noesis::UIElement* Element = Noesis::DynamicCast(Visual); if (Element && Element->GetIsEnabled()) { Hit = Element; @@ -485,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(); @@ -536,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) @@ -545,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 @@ -593,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); @@ -605,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/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/NoesisResourceProvider.cpp b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp index 81443aa..add0a28 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp +++ b/Source/NoesisRuntime/Private/NoesisResourceProvider.cpp @@ -17,10 +17,14 @@ // NoesisRuntime includes #include "NoesisXaml.h" #include "NoesisSupport.h" +#include "NoesisResourceResolver.h" +#include "NoesisSettings.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 +40,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 +64,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 +80,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 +123,8 @@ Noesis::Ptr FNoesisResourceProvider::OpenFont(const char* InFold } return Noesis::Ptr(); } + +UNoesisResourceResolver* FNoesisResourceProvider::GetResourceResolver() const +{ + return GetMutableDefault()->GetResourceResolver(); +} 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/NoesisRuntimeModule.cpp b/Source/NoesisRuntime/Private/NoesisRuntimeModule.cpp index bcfc0bc..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 @@ -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..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" @@ -73,3 +71,4 @@ #include "NoesisRuntimeClasses.h" #include "NoesisRuntimeModule.h" + 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; } 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..21b069f 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); @@ -366,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; } @@ -418,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() @@ -635,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); } diff --git a/Source/NoesisRuntime/Private/NoesisResourceProvider.h b/Source/NoesisRuntime/Public/NoesisResourceProvider.h similarity index 92% rename from Source/NoesisRuntime/Private/NoesisResourceProvider.h rename to Source/NoesisRuntime/Public/NoesisResourceProvider.h index cae5e7e..06df357 100644 --- a/Source/NoesisRuntime/Private/NoesisResourceProvider.h +++ b/Source/NoesisRuntime/Public/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/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();