LayerGroup Problem

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

LayerGroup Problem

Post by Bugala » Sat Aug 19, 2017 2:40 pm

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
To use, suppose you already have three layers made:

Code: Select all

Function LayerGroup:CreateGroup("mytestgroup", "mylayer1")
LayerGroup:AddLayer("mytestgroup", "mylayer2", "mylayer3")

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: 759
Joined: Sun Feb 14, 2010 7:11 pm

Re: LayerGroup Problem

Post by Bugala » Sat Aug 19, 2017 9:11 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.

Post Reply