Ziriax
Topic Author
Posts: 60
Joined: 10 Dec 2015, 17:59
Location: Belgium
Contact:

V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

12 Feb 2017, 15:53

We have two render systems in our application, Noesis and our own 2D CSG engine that uses Monogame. We use C#.

We render all our CSG elements to one big Monogame render-target "atlas".

All our UI elements are rendered using Noesis. Some of these Noesis UI elements display the CSG shapes from the atlas using an ImageBrush.

However, we only want to render those CSG elements for which the corresponding Noesis UI element is visible on the screen (when using a scrollviewer of lists of elements many elements can be off the screen).

To check if something is on screen, I need to get the Visual screen bounds.

To get the screen bounds (actually a parallelogram) in WPF, I can use a combination of TransformToAncestor and RenderSize (or 3 calls to PointToScreen), and I guess that would also work for Noesis. But it seems NoesisGUI does not have the LayoutUpdated event, so I don't know when to call this. I could call it every frame of course.

Also I would like to use an MVVM architecture, and the VM should not know about Noesis if possible.

Currently I have something like this:
    <my:NoesisRectConverter x:Key="NoesisRectConverter"/>
    <my:NoesisTextureConverter x:Key="NoesisTextureConverter"/>
    <DataTemplate DataType="{x:Type my:CsgViewModel}">
        <Rectangle Width="256" Height="256">
            <Rectangle.Fill>
                <ImageBrush ImageSource="{Binding CsgAtlas, Converter={StaticResource NoesisTextureConverter}}" ViewboxUnits="RelativeToBoundingBox">
                    <ImageBrush.Viewbox>
                        <Binding Path="TexCoord" Converter="{StaticResource NoesisRectConverter}" />
                    </ImageBrush.Viewbox>
                </ImageBrush>
            </Rectangle.Fill>
        </Rectangle>
    </DataTemplate>
The converters simply convert a to a Noesis texture and rectangle.

The CsgViewModel provides the CsgAtlas (a Monogame render-texture atlas of rendered CSG elements) , and texture coordinates within that atlas.

The CsgViewModel should also get Matrix and Size properties that must receive the Noesis element-to-screen matrix and local-space element-size.

I was hoping to achieve this by using a OneWayToSource binding, but again, I am missing a property that will be fired when the layout changes.

I could use attached properties, are these supported in C#? I can't get them working, my property-changed callback is never called.

On the other hand, all these bindings and converters feel like overhead; in WPF I would write a custom-control in C# for doing this, but I have no idea how to write such a custom control with C# bindings for Noesis.

Another solution would be to just use the Noesis virtualizing panel system somehow.

I'm a bit stuck here. For now, I'll just ignore this issue, but it will need to be fixed of course since otherwise I'm rendering way too many CSG shapes that are not visible.
Peter Verswyvelen,
Strongly Typed Solutions
 
Ziriax
Topic Author
Posts: 60
Joined: 10 Dec 2015, 17:59
Location: Belgium
Contact:

Re: V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

12 Feb 2017, 16:34

For now I ditched the pure MVVM approach for just the CSG 'views', I created a class CsgView that internally creates and updates a Noesis Rectangle and ImageBrush, checking the bounds each frame. Not ideal, but good enough for now, and avoids a lot of converters and boxing.

Nevertheless, I would still like to know:

* How to create Noesis attached properties in C#

* How to create a custom control in C++ and C# wrapper

* If a LayoutUpdated event is planned, or something better

* How to get access to the cached screen matrix, if that exists
Peter Verswyvelen,
Strongly Typed Solutions
 
User avatar
ai_enabled
Posts: 220
Joined: 18 Jul 2013, 05:28
Contact:

Re: V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

13 Feb 2017, 10:32

Attached properties are working good for us, using them in two projects with NoesisGUI for a few years (perhaps since v1.1).

Example created right from one of our projects:
public static class ToolTipServiceExtend
{

public static readonly DependencyProperty ToolTipProperty = DependencyProperty.RegisterAttached(
			"ToolTip",
			typeof(BaseComponent),
			typeof(ToolTipServiceExtend),
			new FrameworkPropertyMetadata(null, PropertyToolTipAttachedHandler));

public static BaseComponent GetToolTip(FrameworkElement element)
{
	return (BaseComponent)element.GetValue(ToolTipProperty);
}

public static void SetToolTip(FrameworkElement frameworkElement, object value)
{
	frameworkElement.SetValue(ToolTipProperty, value);
}

private static void PropertyToolTipAttachedHandler(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
	throw new Exception("Callback works! " + d);	
}

}
I'm not sure but it seems there was a requirement (perhaps only for Unity version) that they must be defined in a class deferred from DependencyObject. I just checked and it works without this requirement fine for us.
Last edited by ai_enabled on 13 Feb 2017, 10:40, edited 1 time in total.
AtomicTorch Studio Pte. Ltd. http://atomictorch.com
 
User avatar
ai_enabled
Posts: 220
Joined: 18 Jul 2013, 05:28
Contact:

Re: V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

13 Feb 2017, 10:36

And regarding your issue... I would use virtualization for that case. It will automatically display only required controls - so it will not request more than needed textures in your case. Please note there are two modes for virtualization - one with full-item-scrolling (by default) and another one with the exact pixel scrolling which is usually preferred. You can enable it in the ItemsControl/ListBox style:
<Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True" />
<Setter Property="VirtualizingPanel.VirtualizationMode" Value="Recycling" />
<Setter Property="VirtualizingPanel.ScrollUnit" Value="Pixel" />
AFAIK creating C# custom controls is still not possible... I've saw a manual for that in C++ in Docs.

Regards!
AtomicTorch Studio Pte. Ltd. http://atomictorch.com
 
Ziriax
Topic Author
Posts: 60
Joined: 10 Dec 2015, 17:59
Location: Belgium
Contact:

Re: V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

13 Feb 2017, 18:07

@ai_enabled, thanks for the info!

I'm not sure what I'm doing wrong with my attached properties, I'll try it in a standalone test case.

Regarding the virtualization, I would still need a way to figure out if my view-model has a view or not.

In WPF I could use <
ItemContainerGenerator.ContainerFromItem
, or maybe the ItemsChanged events.

I'll try it out.

PS: Also thanks for your Monogame wrapper github project, it really helped me a lot!
Peter Verswyvelen,
Strongly Typed Solutions
 
User avatar
sfernandez
Site Admin
Posts: 1785
Joined: 22 Dec 2011, 19:20

Re: V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

15 Feb 2017, 20:21

For now I ditched the pure MVVM approach for just the CSG 'views', I created a class CsgView that internally creates and updates a Noesis Rectangle and ImageBrush, checking the bounds each frame. Not ideal, but good enough for now, and avoids a lot of converters and boxing.

Nevertheless, I would still like to know:

* How to create Noesis attached properties in C#
As aienabled indicated attached properties should work, and they are defined just like in WPF. Could you please post an example of your attached property definition?
* How to create a custom control in C++ and C# wrapper
We need time to study if with our current architecture this is even possible to accomplish outside our source code.
It would be great to support that kind of extensibility.
* If a LayoutUpdated event is planned, or something better
We should add this event as it is very useful. Could you please create a ticket in our bugtracker?
* How to get access to the cached screen matrix, if that exists
There is no cached screen matrix available for the user, that value is internally calculated by the render tree.
You have to use TransformToAncestor or PointToScreen to calculate that matrix.
In WPF I could use ItemContainerGenerator.ContainerFromItem
In Noesis you can also use that:
ItemsControl itemsControl = ...;
itemsControl.ItemContainerGenerator.ContainerFromItem(item);
 
Ziriax
Topic Author
Posts: 60
Joined: 10 Dec 2015, 17:59
Location: Belgium
Contact:

Re: V1.3, C#: screen bounds of Visual, LayoutUpdated event ?

15 Feb 2017, 21:32

It also seems that when using virtualization, the DataContext of the FrameworkElement is being reset. So I could even use that :-)

The problem is that currently my view-models are hierarchical (a visual reactive fluent-style programming language, internally stored as a LISP-like tree), so a typical virtualizing stackpanel won't work.

Unless Noesis also supports hierarchical virtualization?

Otherwise I guess I'm going to create a derived view-model that flattens my hierarchy into something suitable for the view.
Peter Verswyvelen,
Strongly Typed Solutions

Who is online

Users browsing this forum: Bing [Bot] and 9 guests