Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

API to mimic previous group behaviors
Started by Skatan Mar 15 2014 10:42 AM

21 replies to this topic
[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

Hi,

 

I have been meaning to write this for a long time so please Corona staff hear us out. We are in the middle of the process of migrating all of our apps from the G1.0 engine to G2.0, but we've hit a MAJOR obstacle with the G2.0 engine that will force us to have to rewrite the design and layout of ALL of our apps, entirely from scratch. Our apps aren't small either, have been developing them and building on to them constantly every day since the early spring of 2012. So our apps are by now extremely large and contain tons of different pages, functionalities and designs - having to rewrite all of it, almost 2 years worth of code, just to be able to migrate from one graphics code to the other without any real benefit except being up to date with some changes made under the hood is something we really wish to skip. Do not get us wrong we really appreciate the work and effort you guys have put into making the transition as simple and smooth as possible, but with this obstacle all of that goes down the drain as we'd still have to rewrite almost everything, just to adapt and make the code work with the new functionalities and behaviors of the new groups.

 

So, what is the problem we've encountered? Previously when you inserted objects into a group, the objects inserted could be placed anywhere on the x/y axis to form a perfect alignment between them, and the group they were inserted to was not affected at all by these x/y values. It had its own x/y that were completely independent. So you could align multiple objects on the screen, then insert them into a group, then place that group anywhere on the screen - just like how Photoshop groups can position multiple layers together. We could then insert this group to yet another group and again, position this new group anywhere on the screen regardless of the x/y values of the previous nested groups. I will try illustrate it below with code for creating a quick tabbar.

 

 

local tabbarGroup = display.newGroup()


-- Tab bar background
local background = display.newRect(0, 0, 320, 50)
background:setReferencePoint(display.TopLeftReferencePoint)
background.x = 0; background.y = 0;
background:setFillColor(100, 100, 100)
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].x = (i-1)*50; buttons[i].y = 0;
    buttonsGroup:insert(buttons[i])
end
-- Position tabbar buttons
buttonsGroup:setReferencePoint(display.CenterLeftReferencePoint)
buttonsGroup.x = 0; buttonsGroup.y = background.height*.5;

-- Finally position the outermost group
tabbarGroup:setReferencePoint(display.BottomCenterReferencePoint)
tabbarGroup.x = display.contentCenterX; tabbarGroup.y = display.contentHeight;
 

 

 

Now this way, you could quickly and logically position your objects anywhere on the grid, then insert them into a group and collectively position that group anywhere on the grid, and insert that group into another group and position THAT group anywhere on the grid as well regardless of the x/y values of the group children. This made for a VERY effective way to build layouts and create perfect alignments and good design.

 

Now with the G2.0 however this method completely breaks. We were advised to use the group.anchorChildren property but even with this our old code does not work and needs to be rewritten. We don't know what anchorChildren specifically does but it sure does not make groups work like before. Now we need to take into account all the group children's original x/y values when we position objects, which is a little problematic when you have tenfold of objects inside each group nested into several other groups which are all positioned independently. Going through each group individually and calculating their children's x/y etc on multiple pages in multiple modules is way too much for our code as it is now and it would take us months to fully migrate all our apps to the new engine.

 

So please can we have an API that imitates the old group's positioning behavior so we don't have to rewrite all of our code? As we'd love to stay up to date with your latest innovations and have always done so ever since the beginning, but this migration will require immense effort on our side and in the end we'll see absolutely no benefit from the migration whatsoever, except just adapting to new group behaviors which will provide no benefit to anyone, not the end users and not to us.

 

 

Sorry for the wall of text and thanks for reading! If you know of a solution that we perhaps missed please don't hesitate to reply :)



[TOPIC: post.html]
#2

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,328 posts
  • Corona Staff

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)


[TOPIC: post.html]
#3

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

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.



[TOPIC: post.html]
#4

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

@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.



[TOPIC: post.html]
#5

primoz.cerar

[GLOBAL: userInfoPane.html]
primoz.cerar
  • Contributor

  • 455 posts
  • Corona SDK

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.



[TOPIC: post.html]
#6

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

@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.



[TOPIC: post.html]
#7

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

@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.anchorChildren = true;
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.

 

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 :-)

 

Thanks a lot for the help.



[TOPIC: post.html]
#8

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

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.



[TOPIC: post.html]
#9

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

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.



[TOPIC: post.html]
#10

primoz.cerar

[GLOBAL: userInfoPane.html]
primoz.cerar
  • Contributor

  • 455 posts
  • Corona SDK

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.



[TOPIC: post.html]
#11

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

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.

 

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



[TOPIC: post.html]
#12

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

@primoz.cerar

 

Yeah, that's true. 

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



[TOPIC: post.html]
#13

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

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.

 

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



[TOPIC: post.html]
#14

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

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.

 

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.



[TOPIC: post.html]
#15

primoz.cerar

[GLOBAL: userInfoPane.html]
primoz.cerar
  • Contributor

  • 455 posts
  • Corona SDK

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.



[TOPIC: post.html]
#16

primoz.cerar

[GLOBAL: userInfoPane.html]
primoz.cerar
  • Contributor

  • 455 posts
  • Corona SDK

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.



[TOPIC: post.html]
#17

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

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?

[TOPIC: post.html]
#18

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

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?



[TOPIC: post.html]
#19

Skatan

[GLOBAL: userInfoPane.html]
Skatan
  • Contributor

  • 547 posts
  • Corona SDK

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.



[TOPIC: post.html]
#20

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,328 posts
  • Corona Staff

Director has issues with Graphics 2.0 and it has not been updated to work with the new engine.  If you need to use Director, it's best to keep the graphicsCompatibility = 1 flag going.  If you're going to use Graphics 2.0, you probably should upgrade to Composer at the same time. 

 

Rob



[TOPIC: post.html]
#21

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

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?



[TOPIC: post.html]
#22

kilopop

[GLOBAL: userInfoPane.html]
kilopop
  • Contributor

  • 257 posts
  • Corona SDK

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/


[topic_controls]
[/topic_controls]