Animated texture for buttons
Is it possible to animated the skin of the buttons?? If not possible, can you please tell whether there is any widget which supports animated skins?? If buttons support animated skins, can you please give a hint how it can be done??
Thanks in advance.
To my knowledge the answer is 'no'. If you look at the way the widgets are skinned, each one is just a static PNG file.
I could be wrong, of course, but I don't think you can animate widgets like that. The only way I can see is to have a series of different definitions for each widget and to iterate through them with every frame... and I know I wouldn't want to be the one coding that.
Yah, animated Widget skins aren't supported at this time. A while back I was thinking of working on this, but it would take quite a bit of work. One thing you could do is use the Image widget, which supports RTT, or any texture in general. You can supply it with an Ogre Texture, and change this Texture periodically to get an animation. Theres no easy paths for animation at this time.
Thank you for your reply Master. I'll try that method.
I don't know why but for some reason this has stuck in my head. So I've been digging through the QuickGUI code and source.
Rendering operations are performed by the QuickGUIBrush class, as far as I can tell, which stores a pointer to a Material and a Texture, and this renders everything to the screen. It's a singleton class, so the same brush is used by all the objects in the GUI, and the only thing that changes is image for the Texture.
Which means, in theory
- and I mean, in theory, because firstly I don't want to tread on KFM's toes and secondly I'm not sure if this is even feasible - you could modify the code to allow a Material pointer to be passed to the Brush. Bear in mind that because of how QuickGUI needs to be rendered there would be certain parameters which would have to be set, so you'd have to allow for that. Then, each time the frame was rendered you'd need to pass that Material to the Brush, and you'd get your animated texture since the Material would be updated as past of Ogre's automatic render process.
The problem with doing this is that you end up with a lot of Brushes... or, one Brush and a lot of AnimatedBrushes. And you'd need to add at least one extra pointer and some functions to the base Widget class, and, if you were doing it properly, rework the way in which skins are applied...
So, in theory, yes, it's feasible. To do a quick programmatic hack job, probably a couple of hours. To do it properly... a few more.
The Brush class is very low level, it allows you to:
- specify a render target
- set clipping region
- draw a texture in a rectangular region
When a window is executing the draw process, it first sets itself as the render target, and adjusts the clipping region. Then it uses the brush to draw its skin, including the borders and background. It then iterates through each child, which uses the brush to draw its skin, and then iterates through its children, etc.
I don't remember how materials are rendered at low level, so that would be the first step in evaluating if you can 'draw materials' instead of drawing textures. Another thing that would have to be changed is that the Window would have to become invalidated every frame, so it is redrawn with the new appearance. This has some performance implications as well, since the entire window will be redrawn every frame. In current state, the window is only redrawn when it, or a child widget, marks the window as dirty (needs to be redrawn). On every frame the window is redrawn, if it is visible and dirty.
I am able to get the animation effect by using Image widget. I'm changing the texture according to the length of the animation. But i'm facing a new problem with the image widget now. When the screen is made full screen, the position of the Image is not changing and major misalignments are happening. Is there any way to create a Image with Normalized screen space coordiantes ( -1, 1, 1, -1 ) instead of pixel positions?? or is there any other way to keep the image in the position which is relative to the screen space??
Thanks in advance.
The Sheet does not stretch to fit the viewport, so if your viewport changes dimensions, and you want to have the sheet take up the new dimensions, you can set the Sheet size.
The layout and resizing of Widgets is related to its Anchoring. The Anchoring concept comes from WinForms, basically you can specify a Widget to be positioned relative to it's parent's client area.
I wrote a wiki tutorial that better outlines/explains Anchoring: http://www.ogre3d.org/wiki/index.php/QuickGUI_Beginner_Tutorial_3
If it still doesn't make sense let me know and I'll see if I can help.
Thank you for your reply. I tried that anchoring method. But the result after using anchoring is same. There is no change. When the screen size is more than the given sheet size, the sheet is not stretching.
1. I'm creating Ogre Window with 1280 X 800 size in Full screen mode
2. Creating QuickGUI::Sheet with the same size of the window.
3. I found that the sheet size is not changing when the game is run in full screen and the monitor size exceeds the given size ( I tested it on 1366 X 768 size Monitor )
4. Button positons are changing when the game is run in monitors with different sizes.
I dont know how i can create sheet and QuickGUI widgets with normalised values and how to get the width and height of the screen from Ogre. I am really struck up with this issue. Please help me to get out this problem.
Are you manually changing the size of the Sheet when you go into full screen mode? The Sheet does not resize automatically, you have to write code to do that.
1. Change to Full Screen Mode
2. Call mSheet->setSize(Size(newWidth,newHeight));
Are you saying you're calling the setSize API and its not working?
I'm not changing the window into full screen in the middle of the game. But i'm creating a full screen window at the time of its creation. I'm just passing the Window width and window height params while creating the Sheet. I'm trying to used Ogre::Rectangle2D and RTT method to get the animation effect. But its not a straight method though.
The idea is to create a Sheet with set dimensions, and then stretch the Sheet to match the size of the window.
For example say you create a Sheet with 800 x 600 size. You create a window that its 800 x 600, you create the UI within the Sheet exactly how you want it. Now you want to stretch the Sheet so it fits a 1280 x 1024 window.
1. Create the Sheet in 800 x 600.
2. Make sure all your widgets have a Vertical anchor of TOP_AND_BOTTOM, and a Horizontal anchor of LEFT_AND_RIGHT.
3. After all widgets are created, etc., re-size the Sheet to be 1280 x 1024.
After step 3, the Sheet resizes itself, and iterates through all children to apply the effects of their anchors. LEFT_AND_RIGHT basically mean the widget maintains the same distance between the left and right sides of its Parent's client area. TOP_AND_BOTTOM mean the widget maintains the same distance between the top and bottom sides of its Parent's client area. So by changing the Sheet's size, all child widgets will grow or shrink proportionally to match these distances from the Sheet's client area sides.