Animating a canvas

[quote=87520:@Thom McGrath]How an object is created has no bearing at all on how its code is executed. All events are just methods. Timer actions get called as part of the main event loop, and no other way. If the timer had a Poll method, you could force the timer to run in a thread, but it doesn’t, so you can’t.

As for why you’re seeing different results, I have no idea. I can’t figure how a thread would ever help animation speed. Either your calculations take less time than it takes for a frame to expire, or it doesn’t. A thread won’t have any impact on that.[/quote]

Ok :slight_smile: I have no doubts that what you say is correct about Xojo, but I know the period difference occurs because Windows is not a real-time operating system (Except Windows CE…yet Linux and Mac are :-/), which is why the variability in period occurs…and I understand that WM_Timer messages are all sent to the same window message queue via the dispatch created in the entrypoint…as all messages are. I don’t remember the exact specifics given by the engineering professor why it works (was almost 7 years ago)…but I will ask him via email and get back as to why a timer created by a thread reacts differently (on windows) than created from the main itself. Either way, it’s great Xojo performs exactly as expected, if I had sat down in-front of a notepad and C++…that is finesse on the Xojo developer’s part :slight_smile:

I learn something new everyday about Xojo :slight_smile:

So Xojo pretty much does what my S++ compiler does to handle timers under-the-hood…


dword Timer1; 
Timer1 =  1000; //just random identifier
dword Timer1_Period;
dword Timer1_Mode;

frame Window1.Events.Handler(dword hwnd,dword message,dword wparam,dword lparam);
	if (message = WM_TIMER){
	
	if (wparam = Timer1){if (Timer1.Mode = 1){Timer1_Action();KillTimer(Window1.hwnd,Timer1);}if (Timer1.Mode = 2){Timer1_Action();}}
	}
	DefWindowProc(hwnd,message,wparam,lparam);
end;

property set Timer1.Mode(dword ModeValue);
	dword Timer1_Mode;
	Timer1_Mode = ModeValue;
	if (ModeValue = 0){KillTimer(Window1.hwnd,Timer1);}
	if (ModeValue = 1){SetTimer(Window1.hwnd,Timer1,Timer1.Period,NULL);}
	if (ModeValue = 2){SetTimer(Window1.hwnd,Timer1,Timer1.Period,NULL);}
end;

property get Timer1.Mode() as dword;
	return(Timer1_Mode);
end;

property set Timer1.Period(dword IntervalValue);
	Timer1_Period = IntervalValue;
	if (IntervalValue = 0){Timer1.Mode = 0;
	}else{
	SetTimer(Window1.hwnd,Timer1,Timer1_Period,NULL);
	}
end;

property get Timer1.Period() as dword;
	return(Timer1_Period);
end;

frame Timer1_Action();
//Code to perform during the interval
end;

If anyone is interested, I had an idea to do a perspective flip in pure Xojo, using drawpicture to render each line stretched/compressed. Keep in mind that there is no error checking and it could optimized better.

Image rotation

There’s also the http://www.einhugur.com Picture effects plugin which uses vector to ‘distort’ a picture, like Photoshop.

Jim,
that is the kind of control which would be nice if it was a part of Xojo.

Would be excellent if you could simply drag the control onto your canvas, set the rotation duration, and off it goes.
Hopefully Xojo may include a few eye candy controls in future versions (or at least allow us to add our own controls to the library).

[quote=87987:@Richard Summers]Jim,
that is the kind of control which would be nice if it was a part of Xojo.

[/quote]
I would be thrilled to see some basic graphics effects added, like blur, perspective, etc… would make it sooo much easier to add eye candy to apps!

I am always searching for little things like that, but I think the user base is too small at the moment to realistically expect user contributed eye candy :frowning:

ImagePlay on sourceforge…

Thanks Matthew.
If you find any more stuff - please let me know :slight_smile:

[quote=88079:@Richard Summers]Thanks Matthew.
If you find any more stuff - please let me know :)[/quote]

I have a ginormous library of over 2.6 GB of code, functions, and custom controls to share… Only the most common to get a user “going” are included in the Xojo Developer’s Library (package to download in righthand column of xojodevspot.com)…it contains more than is available in the “downloads” section, and has 400+ useful items, reusable functions, and custom webedition control templates…plus regex tools… color pickers…and the VB to Xojo Converter all in one program…I have yet to post the latest update. .where users will be able to search the remote library of over 2GB code and save items to the local library. :slight_smile:

www.mediafire.com is a free hosting site

In the signage demo, how do I change the size of the image that is flipping and how do I change it from a Horizontal Flip to a Vertical Flip? I am working on a TCG Card game and need to have the card flip both Vertically and Horizontally and this demo is perfect for my needs.

How you might use this for your app depends a lot on the layout of your game. Is it currently 2D in a canvas? resizable? and if so how is it fit within bounds?

For your specific questions the signage demo is relying on default values which puts the camera at z = 5, looking at the origin, with a 55 degree field of view horizontally(*). This is looking flat on into the XY plane and at Z=0 the visible X ranges about -2.5 to 2.5.

All of that is just setup to point out the sign is drawn centered on the origin in the XY plane with a width of 4 and height of 2.

g.draw.shapes.rectSolidTex(-2, -1, 4, 2) //( x, y, w, h)

Note the orientation is Y up, so <-2, -1> specifies the bottom left corner, then it spans 4 right and 2 up. It could also be done as (-2, 1, 4, -2) or even (2, 1, -4, -2), with a consequent flipping of texture.

From that placement the sign is rotated about the X axis with

g.xform.rotate( (1-(0.5*(cos(a/2*3.14159)+1)))*180, 1, 0, 0)

The first parameter, all that math, is the angle, then <1,0,0> is the vector to rotate about. Could’ve also been written as g.xform.rotateX(angle). So to rotate left to right use…

g.xform.rotateY(angle) //or g.xform.rotate(angle, 0, 1, 0)

The tricky part is I’m guessing your drawing coordinates are already setup for a Canvas which makes orthogonal projection a more natural fit over perspective projection. But without perspective, rotating a card will just look like it’s shrinking then stretching not tilting out of the plane. Two ideas come to mind: use orthogonal and when something rotates then manually alter the vertices to fake perspective, or use perspective and work out the math so the camera produces the same coordinate bounds as a canvas.

(*) field of view isn’t correct in the signage project but it’s since been fixed.

The graphics will be 2D in a non-resizing canvas. The Canvas will contain about 30 or so elements. Cards will either be face-up or face-down, horizontally or vertically depending on what’s going on. The cards on the field will have a fixed size of 60x88 or 88x60 depending on card position.

In your signage project, there is so much code, I have no idea what is going on. I don’t even know where the first line of code is being executed from or where the height and lengths of the images are being grabbed from.

The signage demo seems to be perfect fro what I need if I could figure out what is going on.

For small images like 60x88 and only one rotating at a time only on the X or Y axis it might be easier/fast-enough to fake perspective by drawing it in strips, I think this is how the original castle wolfenstein did it.

Looking back over this thread I see that’s exactly what Jim Mckay’s Image Rotation project does. That’ll be much easier to incorporate into your game and plenty fast.

Really just the 15 lines in Window1 is what I’d count. Everything in ‘ezgl set’ is meant to be like an API but I don’t have much in the way of documentation yet. It’ll appear here when it happens and there’s some simple examples in the download that may shed light.

Also, if you’re looking for 3D engines check out the already documented X3Core by Alwyn Bester. 小小影视 - 2024最新免费高清电影、电视剧、韩剧、美剧、日剧在线观看 and https://github.com/alwyn1024/x3-core

[quote=87515:@Matthew Combatti]Thom,

I believe you since you’d know the under-the-hood specs of the framework… but help me understand as it defies logic…

Aside from the main topic this has me curious then, as, if any class within a thread accesses the UI, it thows a ThreadAccessingUI error message correct? (True)

So creating a timer (class) in a thread (if its truly part of the main thread) should throw a “ThreadAccessingUI” error as the new thread would conflict with the main thread and UI (but it doesn’t).

In Windows using C++, the proper method to prevent lockup of the main thread, which I implemented in Xojo (and seems to work as it should with better performance than a timer alone…if the timers all exist within the same space it should render the same result if implemented in both ways??? But doesn’t…), would be to create a thread using api and within the thread create a timer using i.e. SetTimer(1000, pointer) api… which allocates the timer in the thread. I assumed Xojo did the same as it would be “best practices” and works with comparable noticable results between xojo and c++ using both methods. So you’re saying whenever a timer is created in Xojo, its actually an underlying “array of thread handles” created in the main thread with all WM_Timer messages being handled in the main app message receiver?
[/quote]

Depending on what API you used to create the thread you may in fact end up causing yourself reentrancy problems.
The Xojo framework is NOT reentrant and using a preemptive thread to call back into is may work most times but will really be masking fundamental issues that cannot be worked around in pure Xojo code.

As far as I know Timers are NOT fired using WM_Timer messages - hence why timers CAN actually only be approximately accurate.
If there is long running code that blocks the main thread from being serviced then timers could miss a call.

Declares & core animation :stuck_out_tongue:

[quote=130111:@Will Shank]For small images like 60x88 and only one rotating at a time only on the X or Y axis it might be easier/fast-enough to fake perspective by drawing it in strips, I think this is how the original castle wolfenstein did it.

Looking back over this thread I see that’s exactly what Jim Mckay’s Image Rotation project does. That’ll be much easier to incorporate into your game and plenty fast.

Really just the 15 lines in Window1 is what I’d count. Everything in ‘ezgl set’ is meant to be like an API but I don’t have much in the way of documentation yet. It’ll appear here when it happens and there’s some simple examples in the download that may shed light.

Also, if you’re looking for 3D engines check out the already documented X3Core by Alwyn Bester. http://www.xojo3d.com/index.php and https://github.com/alwyn1024/x3-core[/quote]

2D is all I need. In your code, I was having a difficult time figuring out where the height and length are being set since any picture I try to use the code thinks it’s the same dimensions as your pics and not mine. That is my main issue with your code. The code is seeing the dimensions of my pics but is still using something else so I guess they are hard coded somewhere and I can’t find where.

Core Image is the way to do pixel manipulations on OS X, MBS has the classes. Core Animation is superb for animation, I recently switched over some animation in an application from (what I thought) was a highly optimized code to Core Animation and everything was so buttery smooth I was gob smacked!

Both Core Image and Core Animation have a learning curve, one of the most awkward things is that they use bottom up vertical locations, where as Xojo uses top down vertical locations.

Actually thinking about it, I think that MBS has code for Core Animation also.

…and if CoreAnimation is a bit too much to learn for a simple animation, how about using an extended ImageWell for a GIF animation? This is a project currently in Alpha, but I will try if I can convert this piece to 2014r2 once I find some time.

https://dl.dropboxusercontent.com/u/21200221/Xojo/MacOSImageWell.mov

Oh, that was easy. It‘s far from completed, and quite some features are not working, but it extends the ImageWell class by some NSImage and NSImageView features. You just need an animated GIF to try the animation – or load some vector graphics instead for real crisp images.

https://dl.dropboxusercontent.com/u/21200221/Xojo/MacOSImageWell.zip

Ah yes, the dimensions used are that of the rect drawn

g.draw.shapes.rectSolidTex(-2, -1, 4, 2)

Whatever texture is currently bound is stretched to fill that rect. Textures do retain their width and height accessible as texA.width and texA.height.

There’s convenience methods on textures to draw them in their current aspect ratio. With the perspective setup only a small region is viewed in the Z=0 plane so it would need to be scaled down into that region from full size.

[code]//draws texture fullsize centered on <0, 0> in the Z=0 plane
texA.drawCentered(0, 0)

//draw with optional scaling so it’s only 2 units wide
texA.drawCentered(0, 0, 2 / texA.width)[/code]

If this still sounds confusing that’s because it’s 3D. To put it in 2D mode add the Open event with this code

[code]me.setCamera(nil)
me.autoDepthIsOn = false

//or if you’re using the current ezgl version
me.init2D[/code]

Now in the Paint event coordinates match that of a Canvas where top-left is <0,0> and bottom-right is <surface.width, surface.height>. You can draw the texture without scaling and it’ll appear Picture sized. To see that try this Paint code

[code] //load Picture into texture
static myTex As new EZTexture2D(myPic, false, false)

//must turn texturing on for it to be used
g.texture.enable

//draw fullsize with top-left corner at <50, 50>
myTex.drawTopLeft(50, 50)

//draw a box around the image
g.texture.disable
g.draw.shapes.rectWire(50, 50, myTex.width, myTex.height)[/code]

A couple notes. myTex is a static variable here just for quick coding purposes but that can cause problems later on. The proper way is to create them in Open and store in a property, then in close set the properties nil.

Also, 2D coordinates match a Canvas but not as pixels. In a Canvas <0, 0> is an integer coordinate and just designates the top-left most pixel. In ezgl’s 2D mode <0,0> is the top-left corner of the top-left-most pixel. That is, coodinates are subpixel values aligned so that the left of the left-most pixels are 0 and the right side of right-most pixels are surface.width, likewise for top and bottom. What this means is you might want to add 0.5 to your coordinates so they effect pixel values and an easy way to do that is by modifying the transform so it’s automatically done to all coordinates. Add this to the top of Paint…

g.xform.translate(0.5, 0.5)

Whether this makes a difference or is noticeable depends on what you’re doing. And this doesn’t address psuedo 3d perspective rotating under orthographic projection which will require manually calculating the vertices (or carefully setting a transform matrix).

There’s more OpenGL machinations I haven’t covered that may trip you up :slight_smile: