I have two different grids, one stacked up on another. Now I am trying to reduce the size of the first grid(using visual layer animations), such that the other grid now takes up all the space.
ScalarKeyFrameAnimation animation1 = compositor.CreateScalarKeyFrameAnimation();
animation1.InsertKeyFrame(1.0f, 0);
animation1.Duration = TimeSpan.FromMilliseconds(300);
visual.StartAnimation(nameof(visual.Scale) + "." + nameof(visual.Scale.Y), animation1);
I have tried manipulating both offsets and scale property but none are able to change the actual height of the grid. As a result, the second grid doesn't move from its place.
Above is the live visual tree values, the actual height is not being affected with either scale or offset animation. And no "second grid" taking up entire space animation is happening.
ActualHeight & ActualWidth are values set by the layout engine.
VisualLayer animations and RenderTransform animations in XAML apply after the Layout passes and won't update affect ANY layout properties. They are, for lack of a better word, "Render time" properties. Any changes to them will not affect any layout other object.
If you'd really like this to work, you'd need to use either a LayoutTransform or animate the Width & Height of the object if they have one set using Storyboards. Noting however, this will cause animations to run on the UI thread because they require the Layout engine to re-run passes every frame, which will reduce performance.
Related
here is my problem:
I want to have a bunch of Text-GameObjects to be evenly distributed across the screen horizontally.
So I took a Layout-Group and added it onto a Panel, which is streched across the screen, with the following settings:
Panel Settings
(The Layout Element on the Panel is not important here, I think, but the Panel itself is controlled by another Object to stretch across the Screen)
Now, I add the Text-GameObjects via Script. That looks like that:
days[i].transform.SetParent(GameObject.Find("Day Panel").transform);
days[i].AddComponent<Text>();
days[i].transform.GetComponent<Text>().font = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");
days[i].transform.GetComponent<Text>().fontSize = 25;
days[i].transform.GetComponent<Text>().color = Color.black;
days[i].transform.GetComponent<Text>().alignment = TextAnchor.UpperCenter;
days[i].transform.GetComponent<Text>().text = shownDates[i].Day.ToString();
days[i].transform.localScale = new Vector3(1, 1, 1);
days[i].transform.localPosition = new Vector3(0, 0, 0);
Now I have the problem, that the width of the text-GameObjects is influenced by the length of the string I show with them. So if a text-GameObject has a 3-char-long string in it, it is wider than a text-GameObject next to it with a one-char-long string. But I need to distribute the width "fairly" between the Text-Objects, independently from what's inside.
I hope, that you can help me, Thanks :D
Making my comment an answer as it answers your question. You have two options to solve your issue.
The first I provided is not as robust and not modular that will work if you know the number of child objects at compile time. You can utilize the field minWidth of a LayoutElement. By setting this value as the width each element needs to be to evenly fill the space, the text object will be no smaller than the value you give it. However, if you ever add any new objects to your layout group at runtime or at any other time, you would need to recalculate these values so it is not a great solution.
The second solution which would allow for almost no work by you is to add an empty parent RectTransform to fill the space above the text object. With the layout group forcing the width and height to expand to the container, each RectTransform will fill the space evenly, while the childed text can be whatever size it needs to be. Here is the hierarchy setup of this solution:
And here is the solution working:
In the example, the parent objects are panels with Image components. I only did this to show that there is a divide between each object like you want. You can remove this component and still have the object retain its structure.
I want to create a plot that dynamically displays active elements as rectangles. I have achieved a first version that is actually ok using OxyPlot.Annotations.RectangleAnnotation which I add to myPlotModel.Annotations, you can see it in the image hereafter:
Example of wanted display
The thing is that after a while, the amount of drawn rectangles make the update not smooth as I update the shown timewindow (which is set to 15 seconds). I have already set a maximum of drawn elements that suffice to cover the displayed window (i.e. the rectangles get removed as they are too far in the past), but the rendering is still jerky. I draw the rectangles by allocating them to an equal fraction of the Y-axis, that is the third one from the top gets:
rowNumber= 3.0
minimumY = maximalY - maximalY / totalElements * rowNumber
maximumY = maximalY - maximalY / totalElements * (rowNumber + 1.0)
And the Y-axis is hidden.
My question:
Is there a smarter way of creating such a display that would be less computationally heavy, and therefore allow a smoother update? I do not have to stick to OxyPlot, it is simply the easiest way that I found to obtain what I wanted.
Thanks for your answers!
Technically, the answer to your question is "Yes".
There are a number of ways to do this.
You could have a vertical itemscontrol that had an itemscontrol in it's template. That could have a canvas as it's itemspresenter and you could bind canvas.top and canvas.left to properties in it's content. Template each into a rectangle and bind height and width.
And of course do something about the scale on the bottom and the column of activity labels or whatever you want to call them there.
Unless you're using an absolutely ancient machine, that'd just fly.
It's quite a lot of work but it would probably be quicker to write that than to search through a load of alternative packages and decide which was optimal.
I've put a TextBlock in a 3D panel (Planerator) and I used a Storyboard to animate it. (as crawl text)
When the field of view is 1 everything works fine, But if I set the field of view to more than 50 the frame rate will drop sharply and rendering will be choppy.
I used theCompositionTarget.rendering.
Please see the following images:
I need to 2D animations in 3d view with good performance.
Please tell me how can I solve this problem? Should I leave WPF and go to the DirectX?
UPDATE 1 :
I just want to move ONE 2Dtext in 3D space , but the performance is poor.(rendering isn't smooth it is choppy)
This is a sample project.
UPDATE 2:
This is the sample project updated version based on cokeman19's answer. (the performance have been improved ~10 frames, But I need to perfect rendering)
UPDATE 3 :
Finally, I got an acceptable performance with the help of the cokeman19's answer and the contents of this page.
I'm not sure if it's just a byproduct of the sample app, but under Planerator.CreateVisualChild(), it doesn't seem to be necessary to set the GeometryModel3D.BackMaterial. For reference:
VisualBrush vb = new VisualBrush(_logicalChild);
SetCachingForObject(vb); // big perf wins by caching!!
Material backMaterial = new DiffuseMaterial(vb);
...
GeometryModel3D backModel = new GeometryModel3D() { ..., BackMaterial = backMaterial };
The BackMaterial is a VisualBrush wrapper around the logical child, which doesn't belong to the visual tree, so rendering doesn't seem to make sense here. Moreover, the logical child (the LayoutInvalidationCatcher class), is in turn a wrapper around the visual child, which is already rendered (using _logicalChild) in setting frontModel.Visual.
Removing the code for the creation and setting of BackMaterial brings the FPS up to ~55.
In addition, if it's an option, setting the following brings the FPS back up to 60, with no noticeable degradation in quality.
RenderOptions.SetEdgeMode(_viewport3d, EdgeMode.Aliased);
Update:
The only other gain I was able to make was to set the CacheMode to BitmapCache, which may not be appliable for your needs.
frontModel.CacheMode = new BitmapCache(20) { EnableClearType = false };
Even on my slowest machine, this allowed for maximum FPS, but there are some drawbacks. Because the zoom level is so high on the text element, and this technique creates a picture to use in the animation (instead of animating the UIElement itself), I had to set the scale level to 20 before it became almost visually imperceptible. This of course has memory implications, as well.
I have an application with some small windows on the screen. I would like to align them to each other, so when I move one close enough, it will automatically be align with the other. Helping me positioning and size them all.
How can I know the position of other windows when there isn't a parent window? Is it possible to know it even if they are different process (applications)?
I am not fully sure what you mean but the following trick is what I use for dynamic layout and it gives me full control over anything, you just need to play around with it and you can easily get the distance between two windows.
This code is copied from a windows phone app but it is easily understood.
width = Convert.ToInt32(Window.Current.Bounds.Width);//gets window width
height = Convert.ToInt32(Window.Current.Bounds.Height);// gets window height
double dist Math.Abs(Btn1.GetValue(Canvas.LeftProperty) - Btn2.GetValue(Canvas.LeftProperty) + Btn2.Width);
note first two lines are only in order to have the proportions right in every single movement and resize you do, you can keep it all proportional to the window size.
I'm resizing a canvas with touch events as follows:
e.Handled = true;
var transformation = MyCanvas.RenderTransform as MatrixTransform;
var matrix = transformation == null ? Matrix.Identity :transformation.Matrix;
matrix.ScaleAt(e.DeltaManipulation.Scale.X,
e.DeltaManipulation.Scale.Y,
e.ManipulationOrigin.X,
e.ManipulationOrigin.Y);
MyCanvas.RenderTransform = new MatrixTransform(matrix);
The canvas has several child canvasses. I don't want to resize them and in fact need them to go smaller. So looked at RenderTransform.Inverse but am not having any joy.
You can create a custom canvas by inheriting from Panel with
A new dependency property: NonInheritableScale
A binding between bind the transform's scale to the NonInhertiableScale property
overrides of the MeasureOverride() and ArrangeOverride() methods,
so that the take 1.0/NonInhertiableScale.X and 1.0/NonInhertiableScale.Y into account during the layout.
Here is an article on creating custom WPF panels that might help you (a search result, haven't read it).
EDIT after reading the comment below
In that case of a chart you might want to redraw the chart with different axis ranges. A RenderTransform might be not accurate enough and indeed you will have to scale back everything else (axis, labels, gridlines,...)
previous answer, still valid
You will have to iterate through the child canvases and scale them individually. As far as I know there is no build in support for what you want.
You will have to apply both the inverse scale transformation to negate the parent's resize and a scale transformation that will make them smaller.
Post the code you are using to get more detailed help and or feedback.