- Rocko Bonaparte
- Posts: 39
- Joined:
Proper way to load compiled XAML at run time in Unity
I feel stupid asking this because it must be pretty simple. I've implemented InitializeComponent with the LoadComponent calls that I think I need to properly pair to XAML in Noesis with Unity. This works fine while in the editor. However, the built game can't find the XAML files, and I'm not surprised. I figure I have to use the compiled asset instead, but I'm not sure how to point to that since everything implies being given a XAML. I figured I'd ask while poking around because the turnaround on trying stuff is kind of long thanks to the builds. Do I just use the .asset files in my Resources path instead?
What am I supposed to do in the final build instead of this?
What am I supposed to do in the final build instead of this?
Code: Select all
private void InitializeComponent()
{
Noesis.GUI.LoadComponent(this, "Assets/Project/UI/wpf/mainmenu/Save/SaveUserControl.xaml");
}
- Rocko Bonaparte
- Posts: 39
- Joined:
Re: Proper way to load compiled XAML at run time in Unity
I guess the samples directly associate the XAML with the scene so Unity would know to include them. It implies I need to put the xaml in Resources if I want to find them.
I kind of figured the .xaml was getting compiled when made into an asset but I guess it's not true.
I kind of figured the .xaml was getting compiled when made into an asset but I guess it's not true.
- Rocko Bonaparte
- Posts: 39
- Joined:
Re: Proper way to load compiled XAML at run time in Unity
The saga continues.
Of course trying to reference paths in the Resources path wouldn't work because Unity turns that into single-file blob. I tried using StreamingResources instead. However, Noesis.GUI.LoadComponent never seems to find the path if I use what I thought was the typical thing:
The error I see reported matches up to the xaml in both the editor and the game, but the runtime errors that it can't locate it when I do this. Just to lay this out, the exact logged error text:
I could get it to work in the editor is I didn't use Application.streamingAssetsPath but just referenced it relative to my project root: Assets/StreamingAssets/UI/wpf/mainmenu/Top/MainMenuUserControl.xaml. This doesn't work in the game build and I'm not sure what would when I can't reference the installation streaming asset path.
So I'm getting a lot of vibes here that even streaming paths are a no-go. I have to stub up some object that drags in the assets to get them into the build.
Of course trying to reference paths in the Resources path wouldn't work because Unity turns that into single-file blob. I tried using StreamingResources instead. However, Noesis.GUI.LoadComponent never seems to find the path if I use what I thought was the typical thing:
Code: Select all
Noesis.GUI.LoadComponent(this, System.IO.Path.Combine(Application.streamingAssetsPath, "UI/wpf/mainmenu/Top/MainMenuUserControl.xaml"));
Side note: It seems to turn my slashes into forward slashes no matter what I do. I got the same exact error when I changed them around, had the code built, and reimported all the XAMLs for giggles:[noesis] Xaml not found 'C:/coding/learning_unity/game/unity/Assets/StreamingAssets\UI\wpf\mainmenu\Top\MainMenuUserControl.xaml'
UnityEngine.Debug:LogError(Object)
NoesisUnity:UnityLog(Int32, String) (at Assets/NoesisGUI/Plugins/NoesisUnity.cs:141)
Noesis.GUI:Noesis_LoadComponent(HandleRef, String)
Noesis.GUI:LoadComponent(Object, String) (at Assets/NoesisGUI/Plugins/API/Core/NoesisGUI.cs:292)
GameWpf.MainMenuUserControl:InitializeComponent() (at Assets/Project/UI/wpf/mainmenu/Top/MainMenuUserControl.xaml.cs:184)
GameWpf.MainMenuUserControl:.ctor() (at Assets/Project/UI/wpf/mainmenu/Top/MainMenuUserControl.xaml.cs:175)
System.Object:lambda_method(Closure)
Noesis.Extend:CreateInstance(IntPtr, IntPtr) (at Assets/NoesisGUI/Plugins/API/Core/Extend.cs:4659)
System.Object:wrapper_native_00007FFDF370E400(HandleRef, Size&, Size&)
Noesis.FrameworkElement:MeasureOverride(Size) (at Assets/NoesisGUI/Plugins/API/Proxies/FrameworkElementExtend.cs:45)
Noesis.FrameworkElement:CallMeasureOverride(Size, MeasureBaseCallback) (at Assets/NoesisGUI/Plugins/API/Proxies/FrameworkElementExtend.cs:89)
Noesis.Extend:FrameworkElementMeasure(IntPtr, Size&, Size&, MeasureBaseCallback) (at Assets/NoesisGUI/Plugins/API/Core/Extend.cs:1949)
Noesis.View:Noesis_View_SetSize(HandleRef, Int32, Int32)
Noesis.View:SetSize(Int32, Int32) (at Assets/NoesisGUI/Plugins/API/Core/View.cs:57)
NoesisXamlEditor:RenderPreview(View, Int32, Int32) (at Assets/NoesisGUI/Plugins/Editor/NoesisXamlEditor.cs:267)
NoesisXamlEditor:RenderStaticPreview(String, Object[], Int32, Int32) (at Assets/NoesisGUI/Plugins/Editor/NoesisXamlEditor.cs:241)
UnityEditor.AssetDatabase:SaveAssets()
NoesisPostprocessor:ImportXaml(String, Boolean, Boolean, Boolean&) (at Assets/NoesisGUI/Plugins/Editor/NoesisPostprocessor.cs:342)
NoesisPostprocessor:ImportXaml(String, Boolean, Boolean) (at Assets/NoesisGUI/Plugins/Editor/NoesisPostprocessor.cs:299)
NoesisPostprocessor:ImportAssets(String[], Boolean, UpdateProgress) (at Assets/NoesisGUI/Plugins/Editor/NoesisPostprocessor.cs:78)
NoesisPostprocessor:ImportAllAssets(UpdateProgress) (at Assets/NoesisGUI/Plugins/Editor/NoesisPostprocessor.cs:28)
NoesisPostprocessor:ImportAllAssets() (at Assets/NoesisGUI/Plugins/Editor/NoesisPostprocessor.cs:15)
NoesisSettingsEditor:OnInspectorGUI(SerializedObject) (at Assets/NoesisGUI/Plugins/Editor/NoesisSettingsEditor.cs:96)
NoesisSettingsEditor:OnInspectorGUI() (at Assets/NoesisGUI/Plugins/Editor/NoesisSettingsEditor.cs:11)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr)
Code: Select all
Noesis.GUI.LoadComponent(this, System.IO.Path.Combine(Application.streamingAssetsPath, @"UI\wpf\mainmenu\Top\MainMenuUserControl.xaml"));
So I'm getting a lot of vibes here that even streaming paths are a no-go. I have to stub up some object that drags in the assets to get them into the build.
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: Proper way to load compiled XAML at run time in Unity
Hi Rocko,
Yes, xaml assets must be referenced by the scene so Unity would know to include them.
As explained in our Unity tutorial the import process will automatically inject dependencies to used resources like ResourceDictionaries, UserControls, Textures, AudioClips and Fonts. For UserControls the .xaml file should be named as the control type to be automatically found (class NumericUpDown -> NumericUpDown.xaml).
In case you need to add extra dependencies to your XAML, for example resources used by code we provided an extension property, Xaml.Dependencies, for that purpose.
Another option is to have in your scene a gameobject that exposes a list of xamls assets that will be used in your application, this way they are also referenced and available to be loaded later in code using the path inside assets:
Yes, xaml assets must be referenced by the scene so Unity would know to include them.
As explained in our Unity tutorial the import process will automatically inject dependencies to used resources like ResourceDictionaries, UserControls, Textures, AudioClips and Fonts. For UserControls the .xaml file should be named as the control type to be automatically found (class NumericUpDown -> NumericUpDown.xaml).
In case you need to add extra dependencies to your XAML, for example resources used by code we provided an extension property, Xaml.Dependencies, for that purpose.
Code: Select all
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:noesis="clr-namespace:NoesisGUIExtensions"
x:Class="Localization.MainWindow"
FontFamily="./#Oxygen, ./#FontopoNIHONGO"
Foreground="#FF488EB5">
<noesis:Xaml.Dependencies>
<noesis:Dependency Source="Language-en.xaml"/>
<noesis:Dependency Source="Language-fr.xaml"/>
<noesis:Dependency Source="Language-jp.xaml"/>
</noesis:Xaml.Dependencies>
</UserControl>
Code: Select all
Noesis.GUI.LoadXaml("Assets/Path/To/Some.xaml");
Noesis.GUI.LoadComponent(this, "Assets/Path/To/SomeControl.xaml");
- Rocko Bonaparte
- Posts: 39
- Joined:
Re: Proper way to load compiled XAML at run time in Unity
I figured out this method from skimming around a lot of posts. Instead of using the static LoadComponent, I can load the NoesisXaml as a result and then call LoadComponent on it instead:
I tried reference the NoesisXAML objects in my project but the Noesis.GUI.LoadComponent call still didn't find them for some reason. The tutorials seem fine using the asset path but they're also directly shoving them right into the Noesis View. I tried to get cute and make a stub in an included scene to just get the references in place. That just didn't seem to be enough for the path to be recognized from my title screen scene. I didn't poke it any further once I found that other method of loading them.
Taking it from resources does have its own down side. I have to make sure the output in the Resources folder is up-to-date. Before I had my project in the Unity directory tree, I had a batch file doing that. I'm not sure how I want to do it now with the Blend project in the same tree.
Code: Select all
private void InitializeComponent()
{
// Previously: Noesis.GUI.LoadComponent(this, "Assets/Project/UI/wpf/mainmenu/Top/MainMenuUserControl.xaml");
var xaml = UnityEngine.Resources.Load<NoesisXaml>("UI/wpf/mainmenu/Top/MainMenuUserControl");
xaml.LoadComponent(this);
}
Taking it from resources does have its own down side. I have to make sure the output in the Resources folder is up-to-date. Before I had my project in the Unity directory tree, I had a batch file doing that. I'm not sure how I want to do it now with the Blend project in the same tree.
Re: Proper way to load compiled XAML at run time in Unity
We don't recommend using Resources folder. Just have your user controls located wherever you want, make sure .xaml and .cs have the same name and reference the .xaml from code like this.
Whenever this user control is used in another XAML, our post processor will inject a dependency to the xaml and everything should work, all our examples are built like that.
If something is not working, please report a ticket with a minimal repro (for example, just the usercontrol and the xaml using it).
Code: Select all
private void InitializeComponent()
{
Noesis.GUI.LoadComponent(this, "Assets/NoesisGUI/Samples/TicTacToe/MainWindow.xaml");
}
If something is not working, please report a ticket with a minimal repro (for example, just the usercontrol and the xaml using it).
Who is online
Users browsing this forum: Ahrefs [Bot], Google [Bot] and 53 guests