multiple layertofronts behavior?

Discuss any general programming issues here

multiple layertofronts behavior?

Postby Bugala » Fri Apr 10, 2015 6:08 pm

I have this simple subroutine which handles fixing cards in nice row.

In short it works so that i have handcards in table, say:

Code: Select all
t_handcards = { "c1", "c2", "c5"}


Those "c1" etc. are actual layer names used for the cards.

in this example, original hand had been c1 to c5, but now c3 and c4 have been discarded, leaving empty space in their place, and then i enter this hand into my subroutine which goes roughly:

Code: Select all
n=0
foreach(t_handcards, function(index, value)
                                                     layertofront(value)
                                                     movelayer(value, #USELAYERPOSITION, #USELAYERPOSITION, x + (spacebetweencards * n), y)
                                                     n=n + 1
                               endfunction)

(this example is forgetting that the index 0 is last one in queue, but in real version, this is considered too)

What I was expecting to happen, was that leftmost card would seemingly be beneath every other card, and right most card, would be the top card.

Since idea is that left most card is put into its place first, and moved to front, and right after the next card is moved to its place, and once again moved to front (making the previous card obviously not the front card anymore).


But now in practice i notice that while right most card correctly is always the top most card, the order of the rest of the cards is not as i expected, but it could be that from rest of the cards, for example middle one might be the one on top of every other card.

I thought layertofront works in such way, that say i have {a, b, c, d} layers in queue, and then i switch layer c to front, that now the table would look like {c, a, b, d}, but seems this is not the case, at least not after multiple layertofronts.

So how does this layertofront work the row? Does it swap their places, for example i switch c to front, and a moves to c:s place, or what?
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Re: multiple layertofronts behavior?

Postby airsoftsoftwair » Sat Apr 18, 2015 11:16 am

No, LayerToFront() doesn't swap places. That's what SwapLayers() is for. LayerToFront() simply removes the layer from its position in the stack and inserts it at the top.
User avatar
airsoftsoftwair
 
Posts: 2198
Joined: Fri Feb 12, 2010 3:33 pm
Location: Germany

Re: multiple layertofronts behavior?

Postby Bugala » Fri Aug 18, 2017 7:17 pm

Now that I noticed I was encountering this same problem again, to make continuation question to your answer.

So say I have two layers. One in Z-pos 36 (top most layer) and one in Z-pos 20.

Now i use LayerToFront() for z-pos 20 layer and it becomes z-pos 36. But where does the previous Z-pos 36 go? For it seems there is some randomness to it.
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Re: multiple layertofronts behavior?

Postby airsoftsoftwair » Sat Aug 19, 2017 12:16 pm

Bugala wrote:Now that I noticed I was encountering this same problem again, to make continuation question to your answer.

So say I have two layers. One in Z-pos 36 (top most layer) and one in Z-pos 20.

Now i use LayerToFront() for z-pos 20 layer and it becomes z-pos 36. But where does the previous Z-pos 36 go?


Well, one below the top z-position of course. Just use DumpLayers() to check.

For it seems there is some randomness to it.


Then you need to post a very small example program that proves this thesis...
User avatar
airsoftsoftwair
 
Posts: 2198
Joined: Fri Feb 12, 2010 3:33 pm
Location: Germany

Re: multiple layertofronts behavior?

Postby Bugala » Sat Aug 19, 2017 1:39 pm

you can try it with this:
Code: Select all
Function StartLayerToFront()
   SetInterval(1, MultipleLayerToFront, 1)
EndFunction


Function MultipleLayerToFront()
   If IsLeftMouse() = False Then ClearInterval(1)
   For n = 1 To 5
      LayerToFront("layer"..n)
   Next
EndFunction




EnableLayers

CreateLayer(100, 100, 200, 300, {Color = #RED, name="layer1"})
CreateLayer(200, 100, 200, 300, {Color = #GREEN, name="layer2"})
CreateLayer(300, 100, 200, 300, {Color = #BLUE, name="layer3"})
CreateLayer(400, 100, 200, 300, {Color = #YELLOW, name="layer4"})
CreateLayer(500, 100, 200, 300, {Color = #WHITE, name="layer5"})

For n = 1 To 5
   MakeButton(Nil, #LAYERBUTTON, "layer"..n, True, False, {OnMouseDown = StartLayerToFront})
Next

Repeat
WaitEvent()
Until quit = True



It seems to me problem is only with the one being replaced from the top position, rest stay in order they should.
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Re: multiple layertofronts behavior?

Postby Bugala » Sat Aug 19, 2017 7:14 pm

Here is new and working version now:
Code: Select all
LayerGroup = { Groups = {} }


Function LayerGroup:New()
   Local d = {}
 
   SetMetaTable(d, self)
   self.__index = self

   Return(d)
EndFunction




Function LayerGroup:CreateGroup(GroupID, LayerID) /* is the first Layer, upon which rest will be relative to */
   self.Groups[GroupID] = {}
   self.Groups[GroupID][1] = LayerID
   Local t = GetLayerStyle(layerID)
   userdata = { originalposition = { x = t.x, y = t.y, w = t.width, h = t.height } }
   SetObjectData(#LAYER, LayerID, "userdata", userdata)
EndFunction



Function LayerGroup:DeleteGroup(GroupID)
   self.groups[GroupID] = Nil
EndFunction



Function LayerGroup:AddLayer(GroupID, ...) /* Each ... is LayerID to be added to the specified group */
   Local base_t = GetLayerStyle(LayerGroup.groups[GroupID][1]) /*Baselayers current stylesettings */
   Local userdata = GetObjectData(#LAYER, LayerGroup.groups[GroupID][1], "userdata")
   Local t_orig = userdata.originalposition
   Local origwidthmultiplier  = t_orig.w / base_t.width
   Local origheightmultiplier = t_orig.h / base_t.height

   For Local n = 0 To arg.n-1
      Local t = GetLayerStyle(arg[n])
      Local userdata = {
               originaldata = { x = (t.x - base_t.x) * origwidthmultiplier,   y = (t.y - base_t.y) * origheightmultiplier,   w = t.width * origwidthmultiplier,   h = t.height * Origheightmultiplier }, 
                         lastposition = { x = t.x,   y = t.y,   w = t.width,   h = t.height }
                       }
      SetObjectData(#LAYER, arg[n], "userdata", userdata)
      InsertItem(self.Groups[GroupID], arg[n])
   Next
EndFunction



Function LayerGroup:RemoveLayer(GroupID, ...) /* each ... is LayerID to be removed from specified Group */
   For Local n = 0 To arg.n-1
      Local found = -1
      ForEach(self.Groups[GroupID], Function (Index, LayerID)
                     If arg[n] = LayerID Then found = Index
                     EndFunction)
      If found <> -1 Then RemoveItem(self.Groups[GroupID], found)
   Next   
EndFunction



Function LayerGroup:ShowGroup(GroupID, Positiontable)
   Local baselayer = self.groups[GroupID][1]
   Local userdata = GetObjectData(#LAYER, baselayer, "userdata")
   baseorig = userdata.originalposition
   
   Local t = GetLayerStyle(baselayer)  /* Can use GetLayerStyle instead of userdata, because baselayer is always on round() pixels. */

   Local new_x = t.x
   Local new_y = t.y
   Local new_w = t.width
   Local new_h = t.height
   
   If HaveItem(Positiontable, "x") Then new_x = Positiontable.x
   If HaveItem(Positiontable, "y") Then new_y = Positiontable.y
   If HaveItem(Positiontable, "w") Then new_w = Positiontable.w
   If HaveItem(Positiontable, "h") Then new_h = Positiontable.h

   SetLayerStyle(baselayer, { x = new_x, y = new_y, width = new_w, height = new_h } )

   widthmultiplier  = new_w / baseorig.w
   heightmultiplier = new_h / baseorig.h

   Local changedpositionlist = {}
   
   ForEach(self.groups[GroupID], Function (index, layerID)
      If layerID <> baselayer
         Local t = GetLayerStyle(LayerID)
         Local userdata = GetObjectData(#LAYER, layerID, "userdata")
         Local lastposition = userdata.lastposition
         If t.x <> lastposition.x Or t.y <> lastposition.y Or t.width  <> lastposition.w Or  t.height <> lastposition.h  Then InsertItem(changedpositionlist, layerID)   
      EndIf
                  EndFunction)


   ForEach(changedpositionlist, Function (index, layerID)
         LayerGroup:RemoveLayer(GroupID, layerID)
         LayerGroup:AddLayer(GroupID, layerID)
              EndFunction)

      
   ForEach(self.groups[GroupID], Function (index, layerID)
         If layerID <> baselayer
           Local userdata = GetObjectData(#LAYER, layerID, "userdata")
           Local orig_t = userdata.originaldata
          
           Local xpos = new_x + ( orig_t.x * widthmultiplier  )
           Local ypos = new_y + ( orig_t.y * heightmultiplier )
           Local wpos = orig_t.w * widthmultiplier
           Local hpos = orig_t.h * heightmultiplier
           SetLayerStyle(LayerID, {  x = xpos,  y = ypos,  width = wpos,   height = hpos} )
           Local temp = GetLayerStyle(LayerID)
           Local lastposition = { x = temp.x, y = temp.y, w = temp.width, h = temp.height }
           userdata.lastposition = lastposition
           SetObjectData(#LAYER, layerID, "userdata", userdata)
         EndIf
                  EndFunction)      
EndFunction


I havent fully tested this. I do know if you form a group and then move them, that it will work just fine.

However, if you move one of them independently and then do the group move again I havent properly tested, maybe works, maybe wont.
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Re: multiple layertofronts behavior?

Postby Bugala » Sat Aug 19, 2017 9:09 pm

Forget the post above this one, i meant that to other place in forum.
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Re: multiple layertofronts behavior?

Postby Bugala » Sun Aug 27, 2017 5:36 pm

Adding to the multiplelayertofront problem behavior some new info I just noticed.

By the way, you did notice i posted three posts above this an example where the layertofront behaves wrong?

I just noticed that it seems like the problem isnt actually to do with the layer positioning necessarily, but with graphics positioning.

For moment ago I was able to click on a layerbutton that was behind another layer button. And the point is, if graphics had updated correctly, then that layers graphics should have been on top of the other layers graphics, meaning that basically the buttons behavior was correct, although graphics were showing different.
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Re: multiple layertofronts behavior?

Postby airsoftsoftwair » Tue Aug 29, 2017 5:37 pm

Yes, I saw that example but it makes me dizzy :) Please try to come up with something that is easier to understand and you also have to describe in detail what is the expected result and what is the actual result. But the code is very weird to say the least....
User avatar
airsoftsoftwair
 
Posts: 2198
Joined: Fri Feb 12, 2010 3:33 pm
Location: Germany

Re: multiple layertofronts behavior?

Postby Bugala » Tue Aug 29, 2017 8:28 pm

I think you are looking at wrong code, you are probably looking the one i accidentally posted which was meant for other part of forum.

Heres the right example code again:
Code: Select all
Function StartLayerToFront()
   SetInterval(1, MultipleLayerToFront, 1)
EndFunction


Function MultipleLayerToFront()
   If IsLeftMouse() = False Then ClearInterval(1)
   For n = 1 To 5
      LayerToFront("layer"..n)
   Next
EndFunction




EnableLayers

CreateLayer(100, 100, 200, 300, {Color = #RED, name="layer1"})
CreateLayer(200, 100, 200, 300, {Color = #GREEN, name="layer2"})
CreateLayer(300, 100, 200, 300, {Color = #BLUE, name="layer3"})
CreateLayer(400, 100, 200, 300, {Color = #YELLOW, name="layer4"})
CreateLayer(500, 100, 200, 300, {Color = #WHITE, name="layer5"})

For n = 1 To 5
   MakeButton(Nil, #LAYERBUTTON, "layer"..n, True, False, {OnMouseDown = StartLayerToFront})
Next

Repeat
WaitEvent()
Until quit = True


In case you really are feeling dizzy about this code, then let me cut it down to pieces to understand what is important what is not:

Code: Select all
EnableLayers

CreateLayer(100, 100, 200, 300, {Color = #RED, name="layer1"})
CreateLayer(200, 100, 200, 300, {Color = #GREEN, name="layer2"})
CreateLayer(300, 100, 200, 300, {Color = #BLUE, name="layer3"})
CreateLayer(400, 100, 200, 300, {Color = #YELLOW, name="layer4"})
CreateLayer(500, 100, 200, 300, {Color = #WHITE, name="layer5"})

For n = 1 To 5
   MakeButton(Nil, #LAYERBUTTON, "layer"..n, True, False, {OnMouseDown = StartLayerToFront})
Next

Repeat
WaitEvent()
Until quit = True


This is simply creating 5 layer boxes, each one is partially overlapping another box (to demonstrate the problem).

Then each layer is made into a button. They all do the exact same thing, which is to call the "StartLayerToFront()" function when pushing left mouse button down.


Code: Select all
]Function StartLayerToFront()
   SetInterval(1, MultipleLayerToFront, 1)
EndFunction


This is simply using setinterval so that the function would be repeatedly being executed until you release left mouse button.

Code: Select all
Function MultipleLayerToFront()
   If IsLeftMouse() = False Then ClearInterval(1)
   For n = 1 To 5
      LayerToFront("layer"..n)
   Next
EndFunction


And this is whichj causes the bug to happen.

Each layer is put being the top most in order. First the box number 1, then number 2, then number 3.

What I expect to be the result is that box number 1 would be the bottom most box, and number 5 would be the top most, and every number between in that order. As example, number 2 should be below number 3, and number 4 should be on top of 3.

However, in practice by starting this small piece of code, and pushing left mouse button down on top of any of those boxes and releasing the left mouse button, you can see that most of time the z-order of boxes is wrong. Only rarely does it actually end to 1, 2, 3, 4, 5 order as it should, but rather it could be 1, 4, 2, 3, 5 as example.

However, interestingly even if one of the box layers is completely covered by other button layers, it is however still activating the layer button that it should, if the graphics would be showing right. This behavior however cant be tested with this piece of code, I am mentioning that only as extra info.
Bugala
 
Posts: 642
Joined: Sun Feb 14, 2010 8:11 pm

Next

Return to General programming

Who is online

Users browsing this forum: No registered users and 2 guests