I have a timer control and a grid with a List of coordinates for the grid. I was wondering how I could use the timer control or any other control in order to execute code in the interval, coordinate.Time as it varies for each coordinate. Also, thread.sleep(time) is not an option for me.
foreach (Coordinate coordinate in this.Macro)
{
coordinate.Time;
coordinate.Initial;
coordinate.Final;
... executecode # coordinate.Time.
}
Just create a new Thread per each coordinate with a Timer set to the specified interval.
Related
I am attempting to animate a slider using DoubleAnimationUsingKeyFrames and DiscreteDoubleKeyFrame to animate a slider for each key frame. However, it seems to be skipping frames when the storyboard is played, that is, the ValueChanged event is not firing for every key frame. The storyboard and animation are set up in the code-behind as follows:
DoubleAnimationUsingKeyFrames _timelineAnimation = new DoubleAnimationUsingKeyFrames();
Storyboard _timelineStoryboard = new Storyboard();
void SetupTimeline()
{
// set up timeline storyboard animation
_timelineAnimation.SpeedRatio = 1.0;
Storyboard.SetTarget(_timelineAnimation, timelineSlider);
Storyboard.SetTargetProperty(_timelineAnimation, new PropertyPath(Slider.ValueProperty));
_timelineStoryboard.Children.Add(_timelineAnimation);
timelineSlider.ValueChanged += TimelineSlider_ValueChanged;
}
void StartTimeline(List<double> times)
{
foreach (double time in times)
{
double value = time - timelineSlider.Value;
var keyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(value));
_timelineAnimation.KeyFrames.Add(new DiscreteDoubleKeyFrame(time, keyTime));
}
_timelineStoryboard.Begin(timelineSlider, true);
}
// this does not fire for every key frame
void TimelineSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Debug.Print($"TimelineSlider_ValueChanged {e.NewValue}");
}
Example input data (in seconds):
136.224
136.238
136.244
136.2441
136.246
136.2461
136.264
136.274
136.294
136.2941
136.296
136.2961
I imagine that the problem may be that the data items are too close together. Is there any way to speed up the resolution of the animation timer? Or any other suggestions as to a solution?
In fact, when the interval between two frames is set below 30 milliseconds or so, some frames might be skipped.
This is much like a WPF DispatcherTimer. A WPF DispatcherTimer, no matter how small its Interval is, only ticks once in every (about) 30 milliseconds.
To produce animation effect, WPF uses a time manager to signal an update periodically. When it ticks, the animated properties (in this case, the Value property of the Slider) are re-evaluated and the UI is updated. And it apparently picks the “most recent” frame in the timeline and discard those are already outdated.
The time manager "ticks" many times per second; the actual number of ticks that occur each second varies depending on available system resources.
Even if you manage to speed up the resolution timer - I guess it is not possible for a UI timer, say, make it tick every 1 millisecond, human eyes can't perceive such a high frequency in the animation, and, monitors display at only 50-60 Hz.
I am using D3DImage to display a sequence of frames that are rendered unto the same Direct3D Surface one after the other. My current logic is thus:
Display last rendered frame (i.e.D3DImage.Lock()/AddDirtyRect()/Unlock())
Start rendering next frame
Wait for next frame to be ready and that it's time to display it
Display last rendered frame
...
The problem with this approach is that when we are done calling Unlock() on D3DImage, the image isn't actually copied, it's only scheduled to be copied on the next WPF render. It's therefore possible that we render a new frame on the Direct3D surface before WPF has had the chance to display it. The net result is that we see missed frames on the display.
Right now I'm experimenting with using a separate Direct3D texture for rendering and performing a copy to a "display texture" just before display, which is giving better results but incurs substantial overhead. It would be preferrable to just be able to know when D3DImage is done refreshing and start rendering the next frame immediately after. Is this possible, if so how? Or do you have a better idea altogether?
Thanks.
The CompositionTarget.Rendering event is called when WPF is going to render, so that's when you should do your Lock() and Unlock(). After the Unlock(), you can kick off the next render.
You should also check the RenderingTime because the event may fire multiple times per frame. Try something like this:
private void HandleWpfCompositionTargetRendering(object sender, EventArgs e)
{
RenderingEventArgs rea = e as RenderingEventArgs;
// It's possible for Rendering to call back twice in the same frame
// so only render when we haven't already rendered in this frame.
if (this.lastRenderTime == rea.RenderingTime)
return;
if (this.renderIsFinished)
{
// Lock();
// SetBackBuffer(...);
// AddDirtyRect(...);
// Unlock();
this.renderIsFinished = false;
// Fire event to start new render
// the event needs to set this.renderIsFinished = true when the render is done
// Remember last render time
this.lastRenderTime = rea.RenderingTime;
}
}
Update to address comments
Are you sure that there's a race condition? This page says that the back buffer gets copied when you call Unlock().
And if there really is a race condition, how about putting Lock/Unlock around the render code? This page says that Lock() will block until the copy is finished.
It looks like the clean way of doing this, in order to render in parallel with the UI, is to render into a separate D3D surface, and copy it to the display surface (i.e. the one passed to SetBackBuffer) between the calls to Lock() and Unlock(). So the algorithm becomes:
Copy and display the last rendered frame, i.e.
Lock()
Copy from render to display surface
SetBackBuffer(displaySurface)
AddDirtyRect()
Unlock()
Schedule a new render to the render surface
Wait for it to complete and that the timing is ok to display it
Goto 1
The documentation for D3DImage explicitely states:
Do not update the Direct3D surface while the D3DImage is unlocked.
The sore point here is the copy, which is potentially costly (i.e. >2ms if the hardware is busy). In order to use the display surface while the D3DImage is unlocked (avoiding a potentially costly operation at render time), one would have to resort to disassembly and reflection to hook into D3DImage's own rendering...
I am trying to implement a custom control which consists of a grid with some canvas elements as children , When a swipe action is made on the grid , I am intended to preform some operation with the canvas elements .
I am unable to handle the swipe for the grid , i have posted the same in the
msdn - win8 Dev forum
I was in the same boat as you guys, since there was no samples out there on how this was done, but after perusing and scrutinizing the MSDN documentation on how a swipe gesture is implemented on a Windows 8 Store app using C#, this is what i came up with (and it works for my app which requires swiping up / down / left / right):
First of all, instead of the GestureRecognizer, the Manipulation events need to be used, so on the grid that you want to handle the swiping (lets' say you make it so that it takes the whole screen so it interprets the gestures) do the following:
I called my grid swipingSurface and i'm handling manipulation modes for both the Y-axis and X-axis:
swipingSurface.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
Then wire up the manipulation events that you want to be notified, in my case i just want to know then the manipulation started and when it ended:
swipingSurface.ManipulationStarted += OnManipulationStarted;
swipingSurface.ManipulationCompleted += OnManipulationCompleted;
Do whatever you want on your manipulation started, such as getting the initial point if you want. But the actual trick is on the ManipulationCompleted event, in which you need to get the Velocities resulting from your gesture, as follows:
public void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e) {
var velocities = e.Velocities;
}
The ManipulationCompletedEventArgs Velocities property will bring back a struct of type ManipulationVelocities, which contains other properties inside:
-Angular: The rotational velocity in degrees per millisecond.
-Expansion: The expansion, or scaling, velocity in DIPs per millisecond.
-Linear: The straight line velocity in DIPs per millisecond.
I'm actually looking at the Linear velocity, which is a Point that contains X and Y values indicating the direction in which the gesture was performed; for example, if the swipe was upward, you will notice that the Y value is positive, and if its down the Y value is negative; the same goes for the X value, if the swipe is left, the X values are negative and if the swipe is right, the X values are positive, so you can play around with those values and check your swiping direction, final points, etc.
Hope this helps.
You could try setting ManipulationMode on your swipe-able control and handling the Manipulation~ events. Note that some controls might stop bubbling of UI events, so if you say put your control inside of a Button or a ScrollViewer - the events might not work.
You could check out SwipeHintThemeAnimation that uses GestureRecognizer to hook up to a Rectangle control or modify it to use your Grid control, see the documentation.
I want to implement a smooth/animated scrolling for a custom control in C#. I want something similar to the following javascript example:
http://www.kryogenix.org/code/browser/smoothscroll/#p0
My first idea is moving the scrollbars to the target point but stopping in intermediate points. For example, this is a very simplified idea:
public void SetSrollValue(int x)
{
// assume right scrolling
float step = x / 10;
while (scroll.Value < x)
{
scroll.Value += step;
}
}
My questions are:
Should I implement this in a thread?
Will this be painted smoothly (I suppose that yes if I have double buffer activated in my control)
So, if you know any good example, article, guide or similar, please could you provider a link here?
Thanks in advance.
To make the content of the control scroll, you pass the value of the AutoScrollPosition to e.Graphics.TranslateTransform(). That's your angle, alter the value you pass.
Write a little helper class that observes the value of the control's AutoScrollPosition with a method that you call in your OnPaint method, passing e.Graphics so you can call its TranslateTransform method. When you see it change, record Environment.TickCount, set an internal 'scrollBusy' flag and start a 15 msec timer. On each timer tick, call the control's Invalidate() method so that you'll calculate a new value for TranslateTransform when your method is called again. Calculate the increment from the original to the target scroll position so it takes, say, 250 msec.
I need to animate a MapPolyLine such that on a given event, the start pin zips up to the end pin. The approach I am considerg is to animate frames such that I divide the MapPolyLine into n number of segments and decrease the TimeSpan ts between each frame along the logic of my chosing (to keep things simple, let's just say ts = ts / 2 after each cycle).
I know that one cannot animate the MapPolyLine, but one can change the appearance of the line by updating the latitude and longitude of the end position. My question concerns timing. My experience with multithreading is minimal, so I did not want to take the risk of a user running into a threading based error that may be difficult to diagnose. Should I:
use a simple DispatcherTimer and tick method
use a BackgroundWorker that reports progress every-time the TimeSpan has elapsed
use a dummy animation and attach an event handler to the rendering event
solution other than the above mentioned options?
Thank you in advance for your help!
Decided to use the DispatcherTimer considering the amount of time the animation is going to take - by creating a separate animation object that holds state and its own dispatch timer, it ended up being more efficient than using separate threads because the callback would mean interrupting the main UI thread and based on the requirements it was highly unlikely that there will be more than 2-3 of these animations occuring simultaneously with 95% or greater being only 1 animation at a time.