API to mimic previous group behaviors

From investigations so far, the main thing that throws out nested groups is the way group anchor points need to be explicitly defined, rather than being defined by the average of the children’s coordinates. It used to be you would add object1, 2 and 3 into Group1 then define where the anchor point (reference point) was out of TopLeft, TopCenter etc… But you didn’t need to define where the group was in x and y - it knew where it was as defined by the contents placement.

Now in G2, in order to move (to a definite point rather than self.x=self.x + z), scale, rotate or add transitions, you have to state that anchorChildren = true. As soon as you do, the contents of a group are moved so that their anchor point go to the groups default position 0,0. Now it becomes necessary to define the actual placement of the group which is the average placement of its contents, something which G1.0 already did.

Another useful thing with reference points is you could change them on the fly without upsetting the position of the group’s contents. Now with G2.0 if you need to do that, you’d also have to formulate a way to move the contents back to where they were doing something like group.x = group.x + (newAnchor - oldAnchor) * group.width or something like that…

So with G2.0 there has been introduced many more lines of code to achieve the same thing as G1.0. How is that an improvement? It is one thing to have new api design introduce migration headaches, it is another to create more work when nested groups are required.

As an animator, nested groups has been one of the great productivity time savers and has enabled all kinds of uses. Now I’ve read here that Tom from Corona Staff doesn’t even think anchor points should be used with groups, especially not nested groups. Well it’s worked absolutely perfectly in G1.0, why kill something so useful?

http://forums.coronalabs.com/topic/42781-questions-about-anchorchildren/?hl=groups

If G.0 suddenly can’t handle nested groups, what is the point? Or more usefully, what is the alternative?

Are you using the graphicsCompatibility = 1 flag in your config.lua?  If you do, you can continue to use setReferencePoint() and everything should position as it did.

If you are not and want to do things in the Graphics 2.0 way, you use anchor points instead of reference points:

local background = display.newRect(0, 0, 320, 50) --background:setReferencePoint(display.TopLeftReferencePoint) background.anchorX = 0 background.anchorY = 0 background.x = 0; background.y = 0; tabbarGroup:insert(background)

Hi Rob, we’re aware of the graphicsCompatibility and are currently using it, but if I’m not mistaken it will be deprecated in the future, so would be stupid to continue building on to old code which just adds on to and postpones the inevitable.

And if you misunderstood, we aren’t talking about converting :setReferencePoint to anchorX/Y, that transition is fine. But the fact that you can not position nested groups like before, that’s our problem and the way groups behave now in terms of positioning is not the same as before. Rewriting THIS will be a massive effort as we’d have to rethink our apps, not just change a few lines to something else.

Edit: If you want an illustration of the issue, copypaste the code I wrote in my first post and give it a try with graphicsCompatibility 1, it will place a rect with “buttons” at the bottom of your screen. Now convert the setRefs to anchors and try it with graphics 2.0. You will suddenly have to rewrite it in order to achieve the same thing. It is this rewrite we are referring to which will consume a LOT of time.

Have started a new thread to focus getting a function together to make nested groups work again:http://forums.coronalabs.com/topic/46954-solution-to-fix-nested-groups-in-g20/

@skatan
 
I tried adding anchorChildren=true on the groups in your sample code, and it seems to work as expected.

local tabbarGroup = display.newGroup() -- Tab bar background local background = display.newRect(0, 0, 320, 50) --background:setReferencePoint(display.TopLeftReferencePoint) background.anchorX, background.anchorY = 0,0; background.x = 0; background.y = 0; background:setFillColor(100/255, 100/255, 100/255) tabbarGroup:insert(background) -- Buttons group local buttonsGroup = display.newGroup() tabbarGroup:insert(buttonsGroup) -- Create buttons local buttons = {} for i=1, 3 do buttons[i] = display.newRect(0, 0, 40, 40) --buttons[i]:setReferencePoint(display.TopLeftReferencePoint) --buttons[i].anchorX, buttons[i].anchorY = 0, 0; buttons[i].x = (i-1)\*50; buttons[i].y = 0; buttonsGroup:insert(buttons[i]) end -- Position tabbar buttons --buttonsGroup:setReferencePoint(display.CenterLeftReferencePoint) buttonsGroup.anchorX, buttonsGroup.anchorY = 0, 0.5; buttonsGroup.anchorChildren = true; buttonsGroup.x = 0; buttonsGroup.y = background.height\*.5; -- Finally position the outermost group --tabbarGroup:setReferencePoint(display.BottomCenterReferencePoint) tabbarGroup.anchorX, tabbarGroup.anchorY = 0.5, 1; tabbarGroup.anchorChildren = true tabbarGroup.x = display.contentCenterX; tabbarGroup.y = display.contentHeight; 

The inner buttons in your sample don’t need any specific anchor points (I commented them out) since they all would have the same anchors and they’re all positioned relative to each-other anyway.
 
NOTE:
I still have to say that the term anchorChildren is a bit confusing for me. It might be just me, but my brain doesn’t process the term since it doesn’t modify the behavior of the children per se.

Regardless of if anchorChildren is true or false, adding objects to a group will still use the children’s common anchor point to position them relative to each other.

The only time anchorChildren comes into play is when you want to position the group on the stage.
When anchorChildren=true, the group will get its own anchor point which you can set like on any other object. This makes it easier to position if you have groups where the children’s common anchor point is at an arbitrary position.
When anchorChildren=false, the group’s positioning will be using the children’s common anchor point which may prove to be tricky to position the way you want.

To me the term  anchorGroup =true makes more sense than  anchorChildren =true as the ultimate effect of setting this property affects the group’s positioning, not the children within the group.

I’ll add on to this as I know group positions are a constant source of confusion. @ingemar setting anchorChildren = true will cahnge the position of the children in the group as well. If groups AnchorX = 0 then children objects bounding box left edge will be positioned at group origin x = 0. If groups anchorX = 1 then childrens objects bounding box right edge will be positioned at group origin x = 0. Same goes for Y and top, bottom.

This is nicely demostrated in the groups guide at the end when discussing anchorChildren = true.

https://docs.coronalabs.com/guide/graphics/group.html

For the OP let me test this when I get home as i forgot how groups behaved before with all this confusion that I finally figured out in G2.0. I may be able to find a way that would make the least impact on your code.

@ingemar setting anchorChildren = true will cahnge the position of the children in the group as well. If groups AnchorX = 0 then children objects bounding box left edge will be positioned at group origin x = 0. If groups anchorX = 1 then childrens objects bounding box right edge will be positioned at group origin x = 0. Same goes for Y and top, bottom.

What you say is 100% correct.

I was trying to say that anchorChildren=true only affects the *group’s* positioning on the stage, not the positioning of the child when you *insert* the child-object into the group.

Ahhh I see!! You can set anchorChildren to displayObjects as well! Thought it only worked for groups! This should be more clear somewhere. So in general, just setting anchorChildren to true for every single displayObject on the stage pretty much will imitate the old positioning style? Can just use it as a rule of thumb then to get the behavior I want :slight_smile:

Thanks a lot for the help.

Ooops. A typo!

anchorChildren only applies to groups!

I’ve updated my code above by removing the anchorChildren on background.

But it doesn’t affect the result! The sample still works.

What I did was:

• Replace setReferencePoint with the appropriate anchorX, anchorY equivalent

• Set anchorChildren=true on all groups

 

I believe by setting anchorChildren on all necessary groups will have the effect you want.

I’m not sure if there are any penalties for nesting multiple groups with anchorChildren=true though.

The only problem you might have when you set anchorChildren = true on a group is that before if you had left reference point (now anchorX = 0) on all groups and objects for example and you positioned the left most object in the group at x = 10 and you set the group.x = 0. The object would still be at position x = 10 in regards to both groups. With anchorChildren = true if there is no object in the group left of x = 10 it will reposition the contents of the group by 10 to the left so the left most object will start at 0.

Hm that is strange. I gave this a try as I wrote this post and it didn’t work, now it suddenly does. Not sure what I did differently. We’ll try migrate the code again soon and see if we get better results this time or if there perhaps was something else spooking about which caused the problems.

Thanks again

@primoz.cerar

Yeah, that’s true. 

anchorChildren returns the minimum bounding box of the objects within the group, which can be a potential problem. 

This can be what the problem was exactly. When we migrated the code we stumbled upon issue after issue with the groups and eventually realized that it was either A, that we’d need an API that completely mimics the old groups features as this could not be achieved with the current groups supplied with the new engine, or B. rethink the entire code.

Edit: Removed, checking the issue against our code

This behavior occurs by default too right, since objects xy values now get adjusted to the xy of their parent automatically, so if you use anchorChildren and you position an object at x=10, it will automatically move back to x0,y0 with a centerReferencePoint due to the groups position. Is there any way you can solve this by disabling the automatic xy feature? As I think this is the problem we hit when trying to migrate the code and used anchorChildren, which made anchorChildren not work for us and we eventually threw in the towel. If there was a property fixing this so the automatic positioning would not occur by default, along with anchorChildren I think you’d be able to completely mimic the old groups completely.

Due to this I went with anchorChildren = false where the contents have to be offset and only used anchorChildren = true where I want the group to be bound to the contents. As I said I would have to test how to get as close as possible to the previous behavior. I’m not at my corona computer at the moment so I’ll only be able to test this in the evening. I’ll post back if I find a good solution.

I just tried some code in compatibility mode and it seems to me that he groups behave exactly like they do in G2.0 with anchorChildren = true. If you add + 10 to your buttons x they are still on the left edge as they would be in G2 anchorChildren = true. You can offset the button group because you have the background rect in the main group that starts at 0 thus moving the buttonGroup works to offset it.

If this is how it worked in G1 (I really don’t  remember) then anchorChildren is the way to go and just convert reference points to anchor values.

Note if you have masked groups and you want to convert them to containers it’s a bit different. Containers have anchorChildren = true by default and while it is true all positions inside the container are based on its center. Meaning center of the container has position 0, 0 no matter the anchor values.

Is there an outcome to the problem stated by Skatan at the beginning of this thread? We are similarly being knee capped by the way these new anchors throw out nested groups. Not sure why G2.0 works this way as it means having to add more code rather than less in every group set up to work like it does in G1.0 So in addition to setting the anchor, you have to state anchor.children = true then work out where the group is on the stage (by calculating the average positions of the children) and then setting these positions to the group. That’s more time when creating new projects but a nightmare when it comes to migrating G1.0 projects. Why have Corona mucked around with the way nested groups work like this and introduce more work? Shouldn’t new versions be improvements which speed up productivity? It’s been a while since you posted Skatan, have you resolved your issue?

Hi Skatan, a question for you on this issue. Were or are you using Director to manage scenes? Just wondering if it is adding another layer of complication to group management.

In fact, are there any other known issues with Director and graphics 2.0? Or do they work fine together?

Hey Kilo, thank you for formulating the issue much better than I could. We did give it another try last time we posted in this thread but were again unsuccessful. Not sure what exactly is different between G2.0 and G1.0, but something obviously is, and we have thus been stuck since.

We are using Director too but don’t think that by itself should be making things more complicated as Director’s just managing and animating groups. Don’t think there should be something exclusive to G1.0 in there.

But yeps we’ve been unsuccessful in properly migrating our code and apps as they are just too many and the code is just too much, rethinking everything to keep up with small Corona API changes just doesn’t make sense and instead of spending a few months migrating the code to make all apps completely bug free, that time can go into tons of other stuff.

Glad to see we’re not the only ones though.