## LayerGroup Problem

Discuss any general programming issues here
Bugala
Posts: 962
Joined: Sun Feb 14, 2010 7:11 pm

### LayerGroup Problem

I have made this LayerGroup which can be useful to others too:

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
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 stylesettings */
For Local n = 0 To arg.n-1
Local t = GetLayerStyle(arg[n])
/*Local userdata = { x = t.x - base_t.x, y = t.y - base_t.y, w = base_t.width / t.width, h = t.height - base_t.height } /* positions are saved relative to baselayer */
Local userdata = { 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, Dimensionstable)
Local baselayer = self.groups[GroupID][1]

Local t = GetLayerStyle(baselayer)

Local bl_x = t.x
Local bl_y = t.y
Local bl_w = t.width
Local bl_h = t.height

Local new_x = t.x
Local new_y = t.y
Local new_w = t.width
Local new_h = t.height

If HaveItem(Dimensionstable, "x") Then new_x = dimensionstable.x
If HaveItem(Dimensionstable, "y") Then new_y = dimensionstable.y
If HaveItem(Dimensionstable, "w") Then new_w = dimensionstable.w
If HaveItem(Dimensionstable, "h") Then new_h = dimensionstable.h

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

Local xmovement = new_x - bl_x
Local ymovement = new_y - bl_y
Local  widthmultiplier = new_w / bl_w
Local heightmultiplier = new_h / bl_h

ForEach(self.groups[GroupID], Function (index, layerID)
If layerID <> baselayer
Local t = GetLayerStyle(layerID)
Local userdata = GetObjectData(#LAYER, layerID, "userdata")
DebugPrint("x: "..userdata.x.." y: "..userdata.y.." h: "..userdata.h.." w: "..userdata.w)
If t.x <> Round(userdata.x) Then userdata.x = t.x
If t.y <> Round(userdata.y) Then userdata.y = t.y
If t.width <> Round(userdata.w) Then userdata.w = t.width
If t.height <> Round(userdata.h) Then userdata.h = t.height
DebugPrint("x: "..userdata.x.." y: "..userdata.y.." h: "..userdata.h.." w: "..userdata.w)

Local relativeXpos = userdata.x - bl_x
userdata.x = bl_x + (  (relativeXpos + xmovement) *  widthmultiplier  )
Local relativeYpos = userdata.y - bl_y
userdata.y = bl_y + (  (relativeYpos + ymovement) * heightmultiplier  )
userdata.w = userdata.w * widthmultiplier
userdata.h = userdata.h * heightmultiplier
SetObjectData(#LAYER, layerID, "userdata", userdata)
SetLayerStyle(LayerID, {   x = userdata.x,   y = userdata.y,   width = userdata.w,   height = userdata.h} )
EndIf
EndFunction)
EndFunction

Code: Select all

Function LayerGroup:CreateGroup("mytestgroup", "mylayer1")

temptable = { x=100, y=200 }
LayerGroup:ShowGroup("mytestgroup", temptable)

However, I am still having a bug there in LayerGroup:ShowGroup that I am currently working on but I am having trouble locating where the problem actually is.

I am using this myself to move sort of menu with layers for highlight and buttons purposes, and when i change that menu into inactive state, i halve its width and height size, and after that I am getting troubles.

I have made so that i can move this meny with mouse. Push left mouse button and drag around. What I notice is that if i drag it up, down or right, it works correctly, but if i use highspeed to move it to the left, then those highlight buttons move just a little bit to the left, and I am not sure what exactly is causing it or how to fix it. However, if one of you are interested in having GroupLayer option as well, perhaps you have interest enough to fix that bug.

EDIT: I think I have found the cause for problem.
When putting x and y coordinates, it rounds it differently than when using Round() command.

For example, if i use Round(100.8) it will give me result of 101, but if i put layer to position 100.8, it ends up at pixel 100.

Changed Round() to Int() but still having problem, now towards the other direction.

Bugala
Posts: 962
Joined: Sun Feb 14, 2010 7:11 pm

### Re: LayerGroup Problem

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