How to remove surfaces from a layout? - famo.us

I'm creating a lot of little surfaces that get added to a layout ( int this case a header footer layout), animated, then need to go away. However, I'm not sure how to remove the surfaces once added?

Kraig is right about using a RenderController when possible, but I would not suggest it for your case. RenderController works well with large layouts and not so much for small particles and such. RenderController only shows one view at a time.
I have asked about this on the IRC channel and it turns out the way I do it, feels really hacky, but is still the recommended most straight forward approach. The idea is to just redefine the render function to return null.
// surface to remove
surface.render = function(){ return null; }
That's it!
Just make sure you remove all references in your code as well!
I often do it from an object..
delete littleSurfaces['little-surface-key']
FWIW The more advanced approach is to actually define a view that controls specifically the surfaces that get rendered. You do this by defining the render function on a custom view that returns what is known as a renderSpec. A renderSpec is a list of hashes that define the surfaces that will be rendered. The example everyone points to is the Flipper class. Take a look at Flippers render function..
https://github.com/Famous/views/blob/master/Flipper.js
Good Luck!

You can add/remove surfaces using a RenderController object. You can also apply an optional transition when things are shown and hidden.
The DOM may lie to you sometimes, as Famo.us repurposes and recycles DOM Elements for efficiency.
https://famo.us/docs/api/latest/views/RenderController

Related

What is a good way to know when all surfaces had been initially rendered in famo.us?

I would like to be able to know when all views have been rendered in a layout. The reason I want to do this is because I need to be able to reference positions of rendered views in the layout, so that I may animate views relative to other views that had already been rendered.
I have read this:
Surface render events in famo.us
One way I can think of is to count views that have been rendered and after all had been rendered (based on a known count), I can then assume all have been rendered. Obviously this would not work if there's an unknown number of views to render.
So another way to achieve this would be to have the layout fire a custom event when all of its managed surfaces have completed rendering. It seems like a good place to do this would be in a function shim in the given layout. For example, in SequentialLayout it would be SequentialLayout.prototype.commit. But, I am not 100% certain on whether that's the right approach, because it looks like the Engine or Entity manages the rendering. So, what that smells like to me is that this approach wouldn't actually fire the event I want fired at the right time.
Are there any best practices for this?
The best way in your use case may be to listen for the deploy on each surface (renderable) in each view
surface.on('deploy', function() {...});
and once all of the surfaces have been deployed emit a custom event to the view
thisView._eventOutput.emit('completed-deploy', {data: someData});
You can then listen to each view to know when the renderables are deployed
view.on('completed-deploy', function(data) {....});
Although this does take care of the fact that the renderable is deployed to the DOM, it will not let you know if it is done with any transition of a modifier. In the case you would also need to have a function for flagging when transition is complete in your views, if that is what you need.

RaphaelJS Multiple animate same element

I currently have the following working fiddle
var moveAnim = Raphael.animation({ progress: 1 }, 5000, 'bounce').repeat(Infinity);
I animate a circle along a line.
I also want to make the circle flash at the same time but I can't seem to work out a way to do this?
I thought about adding the circle to a set and applying the additional animation to this but I can't see to get this either!
Any ideas?
This is a hack and I make no attempt to hide it, but it could be made a bit nicer.
There's a couple of problems depending on 'how' you want to animate the flash. The main problem is having 2 simultaneous animation on the same object, as Raphael doesn't do this (to my knowledge). Its easier if you want to animate an alternate attribute than the same one. If you want to animate a scale to indicate a flash, you will need to append the scale transform to the end of the path transform string ('t,s').
Example here, just uses opacity attribute.
Probably the nicest method would be to include something that figures out time running and amends an attribute manually within the animation function (paper.customAttributes.progress). However, that will probably take a bit longer.
Another alternative could be to animate another object off screen, that does all the calculations for you. It feels a bit ugly, but should work.
So earlier we create a dummy object off screen...
var dummy = paper.circle(-100,-100,10).attr({ opacity: 0 });
Within the progress func, you can then set the real circles opacity to be the same as the offscreen one.
this.attr('opacity', dummy.attr('opacity'));
And we get the dummy animation triggering later
dummy.animate(flashingAnim);
jsfiddle
As mentioned, I think there are cleaner ways, but may involve you writing a small linear animation func separately, but this may help if performance isn't an issue and you don't mind extra elements in the dom.
An alternative solution that I came up with is a looping callback. The very sound of a looping callback sounds ugly but I guess thats what an animation is?
It does appear that you can attach multiple animations to an element! Here's a an example
function animateIn() {
flashingCircle.animate({ fill: '#f00' }, 1000, animateOut);
}
function animateOut() {
flashingCircle.animate({ fill: '#fff' }, 1000, animateIn);
}
animateIn();

Surface html content with sub-surfaces

What is so recommend way to do the following?
I have a surface with some html content which is layouted by the browser.
Within the html a want to have an extra Scrollview with surfaces.
Where to get the x,y, and width, height for the Scrollview from?
Do i have to wait for the html to be rendered an THEN convert the inner-html part into a surface?
You can not use Surfaces as containers for other surfaces. You need to collect all your surfaces in a View, RenderNode, or ContainerSurface object.
https://github.com/Famous/core/blob/master/View.js
https://github.com/Famous/core/blob/master/RenderNode.js
https://github.com/Famous/surfaces/blob/master/ContainerSurface.js
Remember that the way that Famo.us lays out content is in the style of a render tree. With a tree analogy, the Surface would be a leaf, where the aforementioned Objects would act more like branches.
Here is everything you need to know about the Famo.us RenderTree:
https://github.com/Famous/guides/blob/master/dev/2014-04-09-render-tree.md
Also, take a look at the examples for each of the Objects mentioned as well. You can find the one that fits your use case best..
https://github.com/Famous/examples/blob/master/src/examples/core/View/example.js
https://github.com/Famous/examples/blob/master/src/examples/surfaces/ContainerSurface/example.js
Hope this helps!

Best Practice in Cocos2d

I am at the start of my cocos2d adventure, and have some ideological questions to ask. I am making a small space-shooter game, am I right to use the following class structure?
Scene
Background Layer
Infinite parallax background
Game Layer
Space ships
Bullets
Control Layer
Joystick
Buttons
and a followup question — what is the best practice in accessing objects from other layers? For example, when the joystick is updated, it must rotate the space ship and move the background. Both of these are in other layers. Is there some recommended way to go about this or should I simply get the desired objects by Tag and operate on them?
Cocos is a big singleton-based system, which may not appeal to some developers but is often used in Cocos apps and is the fundamental architecture of the framework. If you have one main scene and many subsequent layers added to that scene, and you want controls from one layer to affect sprites or logic on other layers, there really is nothing wrong with making your main scene a singleton and sending the information from the joystick layer back to the scene to handle for manipulating other layers or sprites. I do this all the the time and this technique is used in countless Cocos tutorials in books and online, so you can feel that you aren't breaking too many rules if you do it this way (and it's also quite easy to do).
If you instead choose to use pointers in one layer to send data to other layers, this can get you into a lot of trouble since one node should never own another node that it doesn't have a specific parent-child relationship with. Doing so can cause crashes and problems with the native Cocos cleanup methods when you remove scenes later, and potentially leak memory. You could use a weak reference in such a case instead, but that is still dependent on one layer expecting another layer to always be around, which may not be the case.
Sending data back to the main game scene to then dispatch and use accordingly is really efficient.
This seems like a perfectly reasonable way to arrange your objects, this is a method I use.
For accessing objects, I would keep an explicit reference to the object as a member variable and use it directly. (Using tags isn't a bad option, I just find it can get a little messy).
#interface Class1 : NSObject
{
CCLayer *backgroundLayer;
CCLayer *contentLayer;
CCLayer *hudLayer;
CCSprite *objectIMayNeedToUseOnBackgroundLayer;
CCNode *objectIMayNeedToUseOnContentLayer;
}
Regarding tags, one method I use to make sure the tag numbers I'm assigning are unique is define an enum as follows:
typedef enum
{
kTag_BackgroundLayer = 100,
kTag_BackgroundImage,
kTag_GameLayer = 200,
kTag_BadGuy,
kTag_GoodGuy,
kTag_Obstacle,
kTag_ControlLayer = 300
kTag_Joystick,
kTag_Buttons
};
Most times I'll also just set zOrder and tag properties of CCNodes (i.e. CCSprites, CCLabelTTFs, etc.) the same, so you can actually use the enum to define your zOrder, too.

What makes a Qt widget and its layout behave properly (in regard to its size)?

I'm having all sorts of size problems with Qt. I am creating my own widgets and using different layouts (generally, I need my own to make them work properly without spending hours on the "powerful" default layouts... which don't lay things out as intended.)
Once I'm done with a widget and its layout though, it doesn't work right. The size is never getting set properly unless I call widget->resize(1, 1); which finally forces a "resize" and makes the widget look correct (i.e. recompute the geometry.) Even the updateGeometry() call has no effect.
This is a dreadful problem when the resize() needs to be called on the parent widget (yuck!) and from what I'm reading should not be necessary were the layouts properly programmed.
Is there a sample that works and is not several thousand of lines long, or does Qt require several thousand lines to make anything work perfectly, even the simplest widget?
What are the minimal functions to be called to make a widget & its layout work at once?
Thank you.
Alexis
P.S. I tried to implement the sizeHint(), minimumSize(), maximumSize(), others that I'm missing? I was hoping that would be enough. Obviously, I also implement the setGeometry() on the layout to resize the children appropriately.
--- addition 1
There is a sample image with a layout that clearly isn't available as is in Qt. The positioning, functions, and colors of the different keys is XML driven and works for any keyboard in the world.
(note, this sample doesn't show the Enter key displayed on two rows and wider below than at the top; more or less, not doable at all with the regular layouts; of course, it works with my version.)
--- clarification
I'm not too sure how to describe the problem better. I was thinking to write a test widget next to see how I can reproduce the problem and then post that and eventually fix it. 8-)
The default layout function that the internal Qt layouts make use of require a lot of coding. I would like to avoid having to copy/paste all of that because for maintenance, it makes it close to impossible.
--- today's findings
As I needed to tweak one of the widgets, I decided to add a VBoxLayout and make it work.
I actually found the problem... One of the widgets in my tree is a QScrollArea and that sizeHint() returns (-1, -1). Not exactly what I'd expect but... whatever you put inside that widget has better know how to compute its width and height or else... it fails.
Looking at the code closely, I could actually compute the width by using the widest width found. Once I used that, the widget would appear (and it actually resizes itself as things change in the list, kinda cool.)
This being said, my earlier comment about having a tree of widgets that auto-resize themselves stands. From the root up to the parents of the leaves in your tree, all of those widgets will need a valid layout. Once I added one in the top widget it resized itself and its children properly (well... in my case up to the QScrollArea, the rest required a bottom to top resizing. Funny how that works!)
--- ah! ha! moment (or: what you find reading the implementation code!)
Today I bumped in another problem which just needed the correct call... I just couldn't find anything worth it in the documentation.
All the objects have a layout now, but a certain parent would not resize properly. Plain simple.
I had a call to the parent as following:
// changes to the children are changing the geometry
parentWidget()->updateGeometry();
Yeah. The docs says that's what you have to do. Nothing happens at all with that call. No idea what it's supposed to do, I did not look at that function. It never did anything for me anyway.
So... I looked at the layout to try to understand how it would send the info up/down. I did not see much except for one interesting comment:
// will trigger resize
This is said of the SetFixedSize mode. To reach that function you need to make the layout for update. Ah! Yes... the layout, not the parent widget... let's try that instead:
parentWidget()->layout()->update();
And voila! It resizes correctly in all cases I have. Quite incredible that the widget updateGeometry() doesn't trigger the same effect...
Although it's possible to do what you want it sounds like the problems you are having are because you're using Qt in a way that it's not meant to be used. Why do you need separate widgets for each key represented on the keyboard?
I see two options, both of which are better in some way:
Use QGraphicsScene and QGraphicsView.
A single custom widget that uses custom drawing to display the keyboard (and likely uses hover for hints).
The first option is probably better. Your keys could then be represented by QGraphicsSimpleTextItem's or even a QGraphicsSvgItem. It also provides a number of standard layouts or you could choose to write your own layout. By default you can use the keyPressEvent or mouseReleaseEvent to respond to user interactions.
I'd highly recommend you take a look at the QGraphicsView examples to get an idea what you can do.
If you go the second route you'll need to record the different key locations so you can respond accordingly as the user moves the mouse around, clicks, etc.
This won't help you with your immediate issue but I wanted to show you a keyboard I made using standard layouts and buttons. It's not perfect and it still won't help you with an enter key that spans two rows but it's not bad. It's resizable too by resizing the window, although I'm not sure if that will be apparent from the images below as SO may be scaling them. (you can view the actual images by opening them in their own tab)
Anyway, this was done using only Qt Designer with no manual coding. It consists of a top level vertical layout with 5 horizontal layouts in it. The buttons are then inserted into one of the 5 horizontal layouts. The size of the keys can be controlled by setting the horizontal and vertical size policies to "ignored" for most of the buttons and then horizontal "minimum" for buttons that you want to be wider. Things can be tweaked by setting min and max size restrictions to buttons. When resized, the buttons will not maintain their relative proportions though, that would probably take some custom programming.
The styling in your example could be approximated pretty well using css style sheets and background images. Still not a minor effort but you should be able to get most of the way there without custom layouts and buttons.