NETCF - Optimized Repaint (onPaint) - compact-framework

I want to ask for suggestions on how to optimize a repaint in Compact Framework? GetHashCode() didn't help because it always return a different hash code.
Anyway, I have a program which you can drag and resize an object in run time. This object is a transparent object and it has a PNG image which also dynamically resize relative to object client size.
Though I noticed, (e.g. I have 4 transparent object and I'm dragging or resizing one) all 4 of them triggers OnPaintBackground even if the 3 are not moving. Another one when am just tapping on the one object .. it sill triggers onPaintBacground(). Anyway, I don't have a problem when this events get triggered.
What I like to do is optimization and that means I only have to repaint the object when it's necessary.
Can you guys please give a suggestions?
here's my pseudo C# code
Bitmap _backBuff;
onResize() {
if(_backBuff != null) _backBuff.Dispose();
_backBuff = new Bitmap(ClientSize.Width, ClientSize.Height);
Invalidate();
}
onPaintBackground(e) /*have to use onPaintBackground because MSDN said it's faster*/ {
using(Graphics g = Graphics.FromImage(_backBuff)) {
g.Clear(Color.Black);
// draw background
....some interface calling here
....and paint the background
// draw alpha PNG
.. get hDc
.. paint PNG
.. release hDc
}
e.Graphics.DrawImage(_backBuff,0,0);
}
Thanks in advance.

Got an idea
I have to check for new location or new size differences between the old ones. If one of them are new, then do a repaint .. else .. paint the _backBuff (which acts as a cache image).
I implemented it and it looks good so far about repainting or painting the cache.

Related

GameMaker Studio 2 - Object changes to different sprite without programming (GML)

While programming my game, I came up on a significant issue. I am trying to create a tactical game, and I created grid cell objects for it. In the object's step event, it has the following code to change the sprite index when the mouse hovers over it.
if (position_meeting(mouse_x,mouse_y,OBJ_GridCell))
{
sprite_index = 1;
}
else
{
sprite_index = 0;
}
This is what the intended sprite looks like (set in object properties):
But then when I run the game, it changes to another sprite I have, and the code functions like it should. It just is the wrong sprite.
I have tried searching, but I can't find anything that matches my issue. Help?
Looks like you want to pick a different frame inside a sprite, so you should use image_index instead of sprite_index.
image_index decided which frame in the sprite will be picked, where sprite_index let you choose a different sprite.

wxPanel flickering/failure when window is inactive

Basically, I have a wxWidget application that implements OpenGL - the latter is displayed on a panel that can be updated through user input (clicking, dragging, etc), wxTimer, or events generated by external processes. The problem arises when focus is shifted to another window (whether an internal dialog box, or another application entirely) - the wxPanel ceases to update anywhere from immediately to after a few seconds, particularly if the other window is on top of it (sometimes, a small part of the panel that was obscured will still continue to update). Reactivating the application or resizing the window "unfreezes" the panel, and normal operation continues.
This is an issue I've always had in wxWidgets, be it with an OpenGL panel such as in this case, or otherwise. Generally, I've been able to get around it by making numerous SwapBuffer() calls in between a Freeze() and a Thaw() upon window refocusing, window resizing, or something similarly kludgy, but these all have the potential to produce flicker or other non-negligible visual artifacts, and additionally can affect performance if done every frame (such as when an animation needs to continue playing in an inactive window).
An indeterminate period of trial and error could probably produce something nice and kludgy for this also, but I'd really like to know, what is the "right" way to handle this problem? Many thanks in advance.
Here's a skeleton of the code for reference:
void MyGLCanvas::Draw(bool focus, int parentID) //This is what's called by the rest of the application
{
if (focus) { SetFocus(); }
SetCurrent();
wxClientDC dc(this);
Paint(dc);
}
void MyGLCanvas::Paint(wxDC &dc)
{
//All OpenGL drawing code here
glFlush();
SwapBuffers();
}
void MyGLCanvas::OnPaint(wxPaintEvent& event)
{
wxPaintDC dc(this);
Paint(dc);
event.Skip();
}
You're doing several strange or downright wrong things here:
Do not skip the event in your OnPaint(). This is a fatal error in wxWidgets 2.8 under Windows and even though we clean up after your code if it does this in 3.0, it's still a bad idea.
Don't use wxClientDC, just call Refresh() and let Windows repaint the window by invoking your existing OnPaint() handler.
Don't call SetFocus() from Draw(), this really shouldn't be necessary.
Do call SetCurrent() before drawing. Always, not just in Draw().
I don't know which of those results in the problems you're seeing but you really should change all of them. See samples\opengl\cube\cube.cpp for an example of how to do it correctly.

Only on new iPad 3: wait_fences: failed to receive reply: 10004003

So I know there's a lot of questions regarding this, but so far as I can tell this is a unique situation so I figured I would post it. Hopefully, this will add some info that may finally give us an answer as to why this is happening to us. I'm getting the error: wait_fences: failed to receive reply: 10004003, when my device rotates. The animation of my views are initiated from:
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
I'm only getting the error on the new iPad 3. I've used the exact same program on an original iPad and iPhones as low as a 3GS. They all don't get the wait_fences error and they all rotate faster than the iPad 3 does.
I use Core Graphics almost exclusively to draw the views. I also ensure they're redrawn on a resize so I don't get pixilated views. If I disable the redraw on resize, I don't get this error (but I get stretched views). If I disable core graphics drawing altogether I don't get the error (but, of course, I get black views).
I used the Time Profiler and found out that the hangup was primarily in drawing gradients:
I have altered the code to fill rather than draw gradients and that does alleviate the problem. I would say that the gradients are the problem except I do these animations in other situations (other than in response to rotation) and it works just fine.
I would also like to note that I've paid special attention to making sure I only animate views that are actually on the screen. I know that animating views off screen can sometimes cause this error to occur.
I have not included the animation code
Any ideas as to why this is happening? Especially since it's only happening on the iPad 3?
For those who will ask, this is the code that performs the animation. It will normally be wrapped in a UIView Animation Block.
- (void) setFramesForFocusView:(CustomControl *)focusView atX:(CGFloat)x showInput:(BOOL)showInput{
CGSize bSize = self.bounds.size;
CGRect fRect = focusView.frame;
fRect.size.width = bSize.width;
CGRect iRect;
if (focusView.inputViewIsSystemKeyboard){
if (_keyboardRect.origin.y < 0 || _keyboardRect.origin.y >= CGRectGetMaxY(self.bounds) || CGRectIsEmpty(_keyboardRect) || CGRectGetMaxY(_keyboardRect) > CGRectGetMaxY(self.bounds)) return;
iRect = _keyboardRect;
} else {
iRect = (focusView.inputUIView && showInput) ? CGRectMake(0, bSize.height / 2, bSize.width, bSize.height / 2) : CGRectZero;
}
CGRect iaRect = focusView.inputAccessoryUIView.frame;
CGFloat availableFieldHeight = iRect.origin.y - iaRect.size.height;
iRect.size.width = bSize.width;
iaRect.size.width = bSize.width;
if (!showInput){
iRect.origin.y = bSize.height;
}
iaRect.origin.y = iRect.origin.y - iaRect.size.height;
iRect.origin.x = x;
iaRect.origin.x = x;
focusView.inputUIView.frame = iRect;
focusView.inputAccessoryUIView.frame = iaRect;
if (focusView.expandInput){
fRect.origin.y = 0;
fRect.size.height = availableFieldHeight;
} else {
if (focusView.labelPlacement != LabelPlacementTop && focusView.labelPlacement != LabelPlacementBottom){
fRect.size.height = _currentView.storedFrame.size.height + [focusView.label.text sizeWithFont:focusView.label.font].height;
}
fRect.origin.y = availableFieldHeight - fRect.size.height;
}
if (fRect.size.height > availableFieldHeight){
fRect.origin.y = 0;
fRect.size.height = availableFieldHeight;
}
fRect.origin.x = x;
[focusView setLabelPlacement:LabelPlacementTop toFrame:fRect];
}
Well that was quick. #RobNapier was correct in that it was a timing issue. I commented out my animations and wow there were a lot of other views animating behind there! Even though I was explicitly animating only on-screen views, there was another ViewController receiving the rotation events behind my views without my... uh... knowledge? I mean, I should know right? I wrote the code. I didn't realize at first because my set of views was covering the entire screen. Unfortunately this will require a lot of rewriting. I use Custom Container Controllers and now I see I need to reconsider my implementation. A lot of stuff is getting needlessly rotated/animated. But wow...that answered a lot of performance questions....
Update
So I had thought that the problem I was facing had to do with the extra views being animated by other view controllers. However, while this is technically true, it's not as true as I thought or in the way I thought. I made absolutely sure that no other views were animated by removing the entire root view hierarchy from the window and replacing it with only the view controller I'm wanting to have rotated. This definitely helped, but not completely. Really, it just 'lowered the bar' so that it was less likely for me to get the 'wait_fences' error. I still discovered I was getting the error though in certain situations.
I believe the problem I'm having is my use of a UIScrollView. My implementation has a variable number of of subviews that it manages. The specific view is my own custom implementation of a UIPickerView, so as you can imagine, the number of views it manages can become quite large. I've discovered that if those subviews become too numerous, I start getting the 'wait_fences' error.
So it appears that: If UIScollView is animated, it will animate all of it's subviews, even if those subviews aren't on screen. This is important. I rather suspect that a lot of people who are struggling with this error may not realize this. Each one of those off-screen subviews are pushing you ever closer to hitting the 'wait_fences' error. The solution in my case is "simple": I'm going to convert my UIScrollView to a UITableView. That'll mean rewriting a lot of code, but at least I know that off-screen subviews will be removed from the screen and thus not animated.
I also noted something else: Core-Graphic Gradients hit you hard. I can animate a lot more off-screen views if they don't use gradients. Of course, I love gradients and I'm not willing to give them up (which is why I'm rewriting my PickerView) but it is interesting and important to note.
Update 2
Finished rewriting my UIScrollView as a tableView and that seems to have done the trick. I'm getting no lag and no wait_fences error when I rotate the screen.
Update 2
So yeah, it's a lot easier to hit the wait_fences error on the iPad 3 than any other iPad/iPhone. I've gone through all my code making sure I never animate anything that's not on screen, so that issue's resolved. I still get the wait_fences error on the iPad 3 when I use 'heavy' drawing routines. Stuff I've found that makes me hit it:
Gradients: gradients really make the CPU work on the retina screen.
Transparency: if your view isn't opaque, the CPU works hard to figure out the transparent areas of the view.
Transparent Colors: not the same as view transparency. This is layering transparent colors/gradients over the top of each other to gain an 'effect', like gloss, highlights whatever.
Textures: I find using textures makes it a little more likely to hit the wait_fences error, but nothing near like what gradients/transparency does.

draw with opengl less than every frame

Is their any way, in cocos2d, to have a cclayer draw via opengl less frequently than every frame? I have tried:
-(void) draw
{
glEnable(GL_LINE_SMOOTH);
if (iShouldUpdate) {
ccDrawLine(ccp(50,50), ccp(200,200));
iShouldUpdate = false;
}
}
-(void) updateTheMap
{
iShouldUpdate = true;
}
and then call: updateTheMap whenever needed, but it just displays for 1 frame.
Thanks.
Yes and no.
Normally the frame contents are cleared before a new frame renders. Every frame begins at a clean state. Now if you were to disable clearing of the screen, you could draw something once and it would stay on screen. But then you wouldn't be able to move what you've drawn without clearing exactly just the parts that you've drawn.
Since this gets overly complex and error prone really quickly, the standard way for games has been ever since there are game engines to clear the frame contents before beginning to draw a new frame. One notable exception being DooM, where it was assumed by the engine developer that every pixel on screen would be updated every frame - unless there were missing textures in which case you could see the famous Halls of Mirrors (HOM) effect that occurs when you're not clearing the framebuffer every frame:
So the standard is to draw the entire screen contents again every frame. Because of that, you can't draw something just every couple of frames because if you do that, then whatever you've drawn will be visible on screen for one frame and then it'll be gone.
In summation: you have to draw everything that should be visible on screen repeatedly every frame. That's the way almost all game engines work.

Animating a marker pin on Bing Maps for Metro apps

I have a Bing Map control and I want to animate the location of a pin drawn on the map.
Ideally I'd want to write code like this:
// Image myPin = some Image on the map layer;
var sb = new Storyboard();
var duration = DurationHelper.FromTimeSpan(System.TimeSpan.FromMilliseconds(1000));
sb.Duration = duration;
LocationAnimation ani = new LocationAnimation();
ani.To = new Location(33.3, 11.1); // destination lat, lng
ani.Duration = duration;
sb.Children.Add(ani);
Storyboard.SetTarget(ani, myPin);
Storyboard.SetTargetProperty(ani, "MapLayer.Position");
Resources.Add("moveMyPin", sb);
sb.Begin();
Of course there is no LocationAnimation class in the framework. There are a couple similar: PointAnimation works with the Point type, while DoubleAnimation works with individual double values.
I assumed I have to implement my Timeline-derived class but the documentation I found so far is not helpful in this regard and I don't know where to start.
How to animate a property for which there is no *Animation class ready? Am I missing something?
Update: I think I can do something like
// let aniX and aniY be two DoubleAnimation objects
StoryBoard.SetTargetProperty(aniX, "(MapLayer.Position).Latitude")
StoryBoard.SetTargetProperty(aniY, "(MapLayer.Position).Longitude")
but now I have another problem as I don't see how to animate the attached property and always get an exception like "Cannot resolve TargetProperty (MapLayer.Position).Latitude on specified object."
So I guess the question now becomes: how to specify a property path for an attached property?
Further update: I may be on a wrong lead with the "SetTargetProperty" thing as that would make a dependent animation (see link in comments). Could there be a better way to animate a marker pin to a coordinate destination?
Update 3: as Jared pointed out I could try to animate RenderTransform, or use a transition to achieve my result. I had already gone this way and it doesn't seem to be my solution. This is what I found out:
Using RepositionThemeAnimation, it seems I have to give the new pixel position of the pin. This is problematic for a couple reasons: first, I know the lat/lng destination of the pin, but would have to work out the projection (as far as I can tell there is no public interface to work with projection). Secondly the projection itself can change as the map zooms/pans. The pixel destination at the time of the end of the animation could not be the same as the initial pixel destination. In my scenario it's a major problem as it's very likely the map is moving while the animation is occurring.
Using RepositionThemeTransition all the weird pixel/projection problems went away. It's the only way so far I was able to see the animation I expected. I just set the transition and set the new lat/lng position of the tag (via MapLayer.SetPosition). It has two major problems though. I can't set the duration (nor the easing functions) for the animation. And most importantly I can see no way to execute code when the pin gets to its final position.
Attached properties can be animated, but you must enclose their names in parenthesis. See an example here:
http://www.charlespetzold.com/blog/2007/09/080231.html
However, I believe this only works for setting the whole value (Location) and potentially not sub properties (Latitude and Longitude).
I'm wondering if you can provide more information about what you're trying to do. Is this a temporary animation? i.e. are you wanting the pin to animate in on entrance or departure? If so you can just do an animation on the RenderTransform X and Y instead. You won't actually be changing the location of the pin but you can use the RenderTransform to temporarily change where it's being drawn.
Even better, you might be able to get away with the free animations now built into the framework. You don't even need a storyboard to use them, you just set them right on the element like this:
<Button Content="Transitioning Button">
<Button.Transitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Button.Transitions>
</Button>
For more examples of the animation library and even video previews for many of the animations, see:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh452703.aspx
Okay, man, your problem isn't related to Bing Maps. It's related to dependency properties that can't be animated UNLESS you specify that they can. Here's how: http://blog.jerrynixon.com/2012/06/windows-8-animated-pie-slice.html
That link in the other answer with Charles' site is not up to date.