changeset 87:27db212af783

- polished position management code; goes something like: - core:Reanchor() to soft fix all anchors - module:Reanchor() or core:InternalReanchor(module) to position a specific set of neighboring frames
author Nenue
date Wed, 19 Oct 2016 16:51:17 -0400
parents 48182978d1c6
children b107b4df7eb6
files Modules/WorldState.lua Modules/WorldState.xml Veneer.lua
diffstat 3 files changed, 303 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/Modules/WorldState.lua	Tue Oct 18 19:53:24 2016 -0400
+++ b/Modules/WorldState.lua	Wed Oct 19 16:51:17 2016 -0400
@@ -4,16 +4,31 @@
 -- %file-revision%
 --
 
-VeneerWorldStateCurrencyMixin = {}
+local WorldStateBlockMixin = {}
+VeneerOrderHallMixin = {
+  anchorPoint = 'TOP',
+}
+VeneerWorldStateCurrencyMixin = {
+}
 VeneerWorldStateProgressMixin = {
   keepOpen = true
 }
 VeneerWorldStateMixin = {
   maxHeight = 0,
-  detectedFrames = {}
+  detectedFrames = {},
+  anchorPoint = 'TOP',
 }
 local print = DEVIAN_WORKSPACE and function(...) print('VnWorldState', ...) end or nop
 
+function VeneerWorldStateMixin:Reset()
+  for i, frame in ipairs(self.modules) do
+    if frame.Reset then
+      frame:Reset()
+    end
+  end
+  self:Update()
+end
+
 function VeneerWorldStateMixin:Setup()
   --DEFAULT_CHAT_FRAME:AddMessage('Loaded')
   print('|cFFFFFF00'..self:GetName()..'|r:Setup()')
@@ -26,85 +41,41 @@
       frame:Setup()
     end
 
-    frame:SetScript('OnSizeChanged', function()
-      local h = frame:GetHeight()
-      if h > self.maxHeight then
-        self.maxHeight = h
-        self:SetHeight(h)
-        print('updating max height:', h)
-      elseif h < self.maxHeight then
-        self:UpdateSize()
+
+    for k,v in pairs(WorldStateBlockMixin) do
+      if not frame[k] then
+        frame[k] = v
+        if k:match('^On') then
+          frame:SetScript(k, v)
+        end
       end
-    end)
-    frame:SetScript('OnHide', function()
-      print('|cFF0088FF'..frame:GetName()..':OnHide()')
-      self:UpdateSize()
-    end)
-    frame:SetScript('OnShow', function()
-      frame.timeLived = 0
-      print('|cFF0088FF'..frame:GetName()..':OnShow()')
-      self:UpdateSize()
-    end)
+    end
 
-    function frame.ShowPanel(frame)
-      frame:SetShown(true)
-      self:Show()
-    end
-    function frame.HidePanel(frame)
-      frame:SetShown(false)
-      self:UpdateSize()
-    end
   end
-  self:SetOrderHallUIMods()
   self:UnregisterEvent('PLAYER_LOGIN')
 end
 
 function VeneerWorldStateMixin:SetOrderHallUIMods()
-  if OrderHallCommandBar then
-    if not self.detectedFrames[OrderHallCommandBar] then
-      self.detectedFrames[OrderHallCommandBar] = true
-      hooksecurefunc(OrderHallCommandBar,'Show', function()
-        self:SetOrderHallUIMods()
-      end)
-      hooksecurefunc(OrderHallCommandBar,'Hide', function()
-        self:SetOrderHallUIMods()
-        self:UpdateSize()
-      end)
-    end
-
-
-    OrderHallCommandBar:ClearAllPoints()
-    OrderHallCommandBar:SetPoint('TOP')
-    OrderHallCommandBar:SetWidth(600)
-    OrderHallCommandBar.Background:SetColorTexture(0,0,0,0.5)
-    OrderHallCommandBar.WorldMapButton:Hide()
-    OrderHallCommandBar:EnableMouse(false)
-
-    if OrderHallCommandBar:IsVisible() then
-      self:SetPoint('TOP', OrderHallCommandBar, 'BOTTOM')
-      print('anchoring to CommandBar')
-    else
-      self:SetPoint('TOP', UIParent, 'TOP')
-      print('anchoring to UIParent')
-    end
-
-    self:UnregisterEvent('ADDON_LOADED')
-  else
-    self:SetPoint('TOP', UIParent, 'TOP')
-    print('anchoring to UIParent')
-  end
+  print('|cFFFF4400remove me', debugstack())
 end
 
 
 function VeneerWorldStateMixin:OnLoad ()
+  self.modules = {self:GetChildren()}
   print('|cFFFFFF00'..self:GetName()..'|r!')
-  self:RegisterEvent('PLAYER_LOGIN')
-  self:RegisterEvent('ADDON_LOADED')
   self:RegisterEvent('ARTIFACT_UPDATE')
   self:RegisterEvent('ARTIFACT_XP_UPDATE')
   self:RegisterEvent('PLAYER_ENTERING_WORLD')
   self:RegisterEvent('PLAYER_REGEN_ENABLED')
   self:RegisterEvent('PLAYER_REGEN_DISABLED')
+  self:RegisterEvent('ZONE_CHANGED_NEW_AREA')
+  self:RegisterEvent('ADDON_LOADED')
+  Veneer:AddHandler(self, self.anchorPoint, true)
+  SLASH_VENEERWORLDSTATE1 = "/vws"
+  SLASH_VENEERWORLDSTATE2 = "/worldstate"
+  SlashCmdList.VENEERWORLDSTATE = function()
+    self:Reset()
+  end
 end
 
 function VeneerWorldStateMixin:OnEvent(event, arg)
@@ -115,9 +86,11 @@
       self.initialized = true
       self:Setup()
     end
-  elseif event == 'ADDON_LOADED' then
-    if self.initialized and IsAddOnLoaded('Blizzard_OrderHallUI') then
-      self:SetOrderHallUIMods()
+  elseif event == 'ZONE_CHANGED_NEW_AREA' or event == 'ADDON_LOADED' then
+    if OrderHallCommandBar then
+      self:UnregisterEvent('ZONE_CHANGED_NEW_AREA')
+      self:UnregisterEvent('ADDON_LOADED')
+      Veneer:AddHandler(VeneerOrderHallHandler, 'TOP', true)
     end
   elseif event == 'PLAYER_ENTERING_WORLD' then
     self:Update()
@@ -129,22 +102,17 @@
 end
 
 function VeneerWorldStateMixin:Update()
-  self.modules = {self:GetChildren()}
   print('|cFFFFFF00All:Update()|r')
-  print(self:GetChildren())
   for i, frame in ipairs(self.modules) do
     if frame.Update then
       print('  |cFFFF00FF'.. frame:GetName() .. ':Update()')
       frame:Update()
     end
   end
-  self:SetOrderHallUIMods()
 end
 
-function VeneerWorldStateMixin:UpdateSize()
-  print('|cFFFFFF00All:UpdateSize()|r')
-  print(self:GetChildren())
-  self.modules = {self:GetChildren()}
+function VeneerWorldStateMixin:Reanchor(isUpdate)
+  print('|cFFFFFF00'..self:GetName()..':Reanchor()|r', #self.modules, 'blocks')
   self.maxHeight = 0
   for i, frame in ipairs(self.modules) do
     print('  '..frame:GetName()..':',frame:IsShown(), frame:IsVisible(), frame:GetHeight())
@@ -153,14 +121,17 @@
     end
   end
   if self.maxHeight == 0 then
-    print ('height zero')
+    print ('  hiding because there are no blocks')
     self:Hide()
   else
     self:Show()
-    print ('height update:', self.maxHeight)
+    print ('  height update:', self.maxHeight)
     self:SetHeight(self.maxHeight)
   end
 
+  if not isUpdate then
+    Veneer:InternalReanchor(self, print)
+  end
 end
 
 
@@ -168,6 +139,34 @@
 function VeneerWorldStateMixin:OnMouseDown()
 end
 
+function VeneerOrderHallMixin:Setup()
+  print('|cFFFFFF00'..self:GetName()..':Setup()')
+  hooksecurefunc(OrderHallCommandBar,'Show', function()
+    self:Update()
+  end)
+  hooksecurefunc(OrderHallCommandBar,'Hide', function()
+    self:Update()
+  end)
+end
+
+function VeneerOrderHallMixin:Update()
+
+  if not OrderHallCommandBar then
+    print('|cFFFF4400'..self:GetName()..' updater called without target')
+    return
+  end
+
+  print('|cFF0044FF'..self:GetName()..' update')
+  OrderHallCommandBar:ClearAllPoints()
+  OrderHallCommandBar:SetPoint('TOP', self, 'TOP')
+  OrderHallCommandBar:SetWidth(600)
+  OrderHallCommandBar.Background:SetColorTexture(0,0,0,0.5)
+  OrderHallCommandBar.WorldMapButton:Hide()
+  OrderHallCommandBar:EnableMouse(false)
+
+  self:SetSize(OrderHallCommandBar:GetSize())
+end
+
 function VeneerWorldStateCurrencyMixin:OnLoad ()
 
   self:RegisterEvent("PLAYER_ENTERING_WORLD");
@@ -203,11 +202,10 @@
 end
 
 function VeneerWorldStateProgressMixin:OnUpdate(sinceLast)
+  self.timeLived = (self.timeLived or 0) + sinceLast
   if self.keepOpen then
     return
   end
-
-  self.timeLived = (self.timeLived or 0) + sinceLast
   if self.timeLived >= 3 and not self.TransitionFadeOut:IsPlaying() then
     if not self.timeOut then
       self.timeOut = true
@@ -239,7 +237,6 @@
 
 function VeneerWorldStateProgressMixin:Setup()
   self:UpdateXPGain()
-
   if self.canGainXP then
     self.mode = 'xp'
   else
@@ -283,6 +280,22 @@
 
 local GetEquippedArtifactInfo = _G.C_ArtifactUI.GetEquippedArtifactInfo
 local GetCostForPointAtRank = _G.C_ArtifactUI.GetCostForPointAtRank
+
+function VeneerWorldStateProgressMixin:AnimateProgress(progressChange)
+
+  local progressWidth = self:GetWidth() * progressChange
+
+  print('  Render change:', progressChange, progressWidth)
+  self.ProgressAdded:Show()
+  self.ProgressAdded:ClearAllPoints()
+  self.ProgressAdded:SetPoint('TOPRIGHT', self.ProgressBar, 'TOPRIGHT', 0, 0)
+  self.ProgressAdded:SetPoint('BOTTOMLEFT', self.ProgressBar, 'BOTTOMRIGHT', - (progressWidth), 0)
+
+
+  self.ProgressFlash.translation:SetOffset(progressWidth, 0)
+  self.ProgressFlash:Play()
+end
+
 function VeneerWorldStateProgressMixin:Update()
   local hasNewInfo = false
   local progressChange = false
@@ -365,11 +378,7 @@
 
 
     if progressChange then
-      print('  Render change:', progressChange)
-      self.ProgressAdded:Show()
-      self.ProgressAdded:SetPoint('BOTTOMLEFT', self.ProgressBar, 'BOTTOMRIGHT', - (self:GetWidth() * progressChange), 0)
-      self.ProgressAdded:SetPoint('TOPRIGHT', self.ProgressBar, 'TOPRIGHT', 0, 0)
-      self.ProgressFlash:Play()
+      self:AnimateProgress(progressChange)
     end
 
 
@@ -400,6 +409,7 @@
   if button == 'RightButton' then
     if self.keepOpen then
       self.keepOpen = nil
+      self.timeLived = 1000
     else
       self.keepOpen = true
     end
@@ -424,4 +434,45 @@
   print('|cFF88FF00'..self:GetName()..'.TransitionFadeOut:Play()')
   self.modeChanged = true
   self.TransitionFadeOut:Play()
+end
+
+do
+  function WorldStateBlockMixin:ShowPanel()
+    print('|cFF0088FF'..self:GetName()..':ShowPanel()')
+    self:SetShown(true)
+    VeneerWorldState:Show()
+  end
+  function WorldStateBlockMixin:HidePanel()
+    print('|cFF0088FF'..self:GetName()..':HidePanel()')
+    self:SetShown(false)
+    VeneerWorldState:Reanchor()
+  end
+
+  function WorldStateBlockMixin:OnSizeChanged ()
+    local h = self:GetHeight()
+    if h > VeneerWorldState.maxHeight then
+      VeneerWorldState.maxHeight = h
+      VeneerWorldState:SetHeight(h)
+      print('updating max height:', h)
+    elseif h < VeneerWorldState.maxHeight then
+      VeneerWorldState:Reanchor()
+    end
+  end
+  function WorldStateBlockMixin:OnHide ()
+    print('|cFF0088FF'..self:GetName()..':OnHide()')
+    VeneerWorldState:Reanchor()
+  end
+  function WorldStateBlockMixin:OnShow ()
+    self.timeLived = 0
+    print('|cFF0088FF'..self:GetName()..':OnShow()')
+    VeneerWorldState:Reanchor()
+  end
+  function WorldStateBlockMixin:Setup()
+    print('|cFF0088FF'..self:GetName()..':Setup()|r -- nop')
+  end
+  function WorldStateBlockMixin:Reset()
+    print('|cFF0088FF'..self:GetName()..':Reset()')
+    self.keepOpen = true
+    self:Setup()
+  end
 end
\ No newline at end of file
--- a/Modules/WorldState.xml	Tue Oct 18 19:53:24 2016 -0400
+++ b/Modules/WorldState.xml	Wed Oct 19 16:51:17 2016 -0400
@@ -57,7 +57,21 @@
 
             <Alpha childKey="Spark" fromAlpha="0" toAlpha="1" duration="0.15" order="1" />
             <Alpha childKey="Spark" fromAlpha="1" toAlpha="0" duration="0.15" order="2" />
-            <Translation childKey="Spark" offsetX="600" offsetY="0" duration="0.30" order="1" />
+            <Translation parentKey="translation" childKey="Spark" offsetX="600" offsetY="0" duration="0.30" order="1" />
+            <Scripts>
+              <OnPlay>
+                self:GetParent().ProgressAdded:Show()
+                self:GetParent().Spark:Show()
+              </OnPlay>
+              <OnStop>
+                self:GetParent().ProgressAdded:Hide()
+                self:GetParent().Spark:Hide()
+              </OnStop>
+              <OnFinished>
+                self:GetParent().ProgressAdded:Hide()
+                self:GetParent().Spark:Hide()
+              </OnFinished>
+            </Scripts>
           </AnimationGroup>
         </Animations>
         <Layers>
@@ -83,24 +97,23 @@
               </Anchors>
               <Color a=".6" r="1" g="0" b=".5" />
             </Texture>
+          </Layer>
+          <Layer level="OVERLAY">
             <Texture parentKey="ProgressAdded" hidden="true">
-
               <Color a="1" r="1" g="1" b="1" />
             </Texture>
-          </Layer>
-          <Layer level="OVERLAY">
+
+            <Texture parentKey="Spark" hidden="false" alpha="0" alphaMode="ADD" atlas="OBJFX_LineBurst">
+              <Size x="60" y="15"/>
+              <Anchors>
+                <Anchor point="CENTER" relativePoint="LEFT" relativeKey="$parent.ProgressAdded" />
+              </Anchors>
+            </Texture>
             <FontString parentKey="Label" inherits="VeneerNumberFont">
               <Anchors>
                 <Anchor point="CENTER" />
               </Anchors>
             </FontString>
-
-            <Texture parentKey="Spark" hidden="false" alpha="0" alphaMode="ADD" atlas="OBJFX_LineBurst">
-              <Size x="60" y="15"/>
-              <Anchors>
-                <Anchor point="LEFT" />
-              </Anchors>
-            </Texture>
           </Layer>
         </Layers>
       </Frame>
@@ -131,4 +144,5 @@
     </Frames>
   </Frame>
 
+  <Frame name="VeneerOrderHallHandler" parent="UIParent" mixin="VeneerOrderHallMixin" inherits="VeneerMixinScripts" />
 </Ui>
\ No newline at end of file
--- a/Veneer.lua	Tue Oct 18 19:53:24 2016 -0400
+++ b/Veneer.lua	Wed Oct 19 16:51:17 2016 -0400
@@ -17,7 +17,9 @@
   pendingCalls = {},
 }
 VeneerHandlerMixin = {
-  Reanchor = nop
+  Reanchor = nop,
+  anchorPoint = 'CENTER', -- indicates the initial cluster group point
+  --anchorPath = 'BOTTOM', -- indicates the point from which the frame is anchored in a cluster arrangement
 }
 local print = DEVIAN_WORKSPACE and function(...) print('Veneer', ...) end or nop
 local wipe = table.wipe
@@ -48,11 +50,33 @@
   return (IsFrameHandle(table) and table:GetName()) or tostring(table)
 end
 
-local anchor_coefficients = {
-  ['TOP'] = function(x, y) return x, y end,
-  ['BOTTOM'] = function(x, y) return x,y end,
-  ['LEFT'] = function(x, y) return x,y end,
-  ['RIGHT'] = function(x,y) return x,y end,
+local OFFSET_PARALLELS = {
+  TOP = {'LEFT', 'RIGHT', 'SetHeight'},
+  BOTTOM = {'LEFT', 'RIGHT', 'SetHeight'},
+  LEFT = {'TOP', 'BOTTOM', 'SetWidth'},
+  RIGHT = {'TOP', 'BOTTOM', 'SetWidth'},
+}
+local ANCHOR_OFFSET_POINT = {
+  TOP = 'BOTTOM',
+  TOPLEFT = 'BOTTOMRIGHT',
+  TOPRIGHT = 'BOTTOMLEFT',
+  LEFT = 'RIGHT',
+  RIGHT = 'LEFT',
+  CENTER = 'CENTER',
+  BOTTOM = 'TOP',
+  BOTTOMRIGHT = 'TOPLEFT',
+  BOTTOMLEFT = 'TOPRIGHT',
+}
+local ANCHOR_INSET_DELTA = {
+  TOP = {0, -1},
+  TOPLEFT = {1, -1},
+  TOPRIGHT = {-1,-1},
+  LEFT = {1, 0},
+  BOTTOMLEFT = {1, 1},
+  BOTTOM = {0, 1},
+  BOTTOMRIGHT = {-1, 1},
+  RIGHT = {-1, 0},
+  CENTER = {0, 0},
 }
 
 function VeneerCore:print(...)
@@ -76,8 +100,11 @@
 function VeneerCore:OnEvent(event, ...)
   if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then
     if IsLoggedIn() and not self.intialized then
-      self.intialized = true
       self:Setup()
+      self:UnregisterEvent('ADDON_LOADED')
+      self:UnregisterEvent('PLAYER_LOGIN')
+      self:Reanchor()
+      self:Update()
     end
   end
 end
@@ -92,52 +119,145 @@
 end
 
 function VeneerCore:Setup ()
+  self.initialized = true
   if (not VeneerData) or (not VeneerData.version) then
     VeneerData = defaults
   end
   self.data = VeneerData
+  self:ExecuteOnClusters(nil, 'Setup')
+end
 
 
-  self:ExecuteOnClusters(nil, 'Setup')
+function VeneerCore:GetClusterFromArgs (...)
+  local primaryAnchor
+  local insertPosition
+  local clusterTable = self.FrameClusters
+  for i = 1, select('#', ...) do
+    local arg = select(i, ...)
+    local argType = type(arg)
+    if argType == 'string' then
+      if not primaryAnchor then
+        primaryAnchor = arg
+      end
+      clusterTable[arg] = clusterTable[arg] or {}
+      clusterTable = clusterTable[arg]
+      print(string.rep(' ', i)..'anchor cluster', i, arg)
+    elseif argType == 'boolean' then
+      insertPosition = 1
+    end
+  end
+  if not primaryAnchor then
+    primaryAnchor = 'TOPLEFT'
+  end
+  if not insertPosition then
+    insertPosition = #clusterTable + 1
+  end
+
+
+  return primaryAnchor, clusterTable, insertPosition
 end
 
 function VeneerCore:AddHandler(handler, ...)
   print('*** Adding handler:', handler.moduleName or handler:GetName())
-  local clusterTable = self.FrameClusters
-  for i = 1, select('#', ...) do
-    local anchor = select(i, ...)
-    clusterTable[anchor] = clusterTable[anchor] or {}
-    clusterTable = clusterTable[anchor]
-    print('    cluster layer', i, anchor)
+
+  local anchorGroup, clusterTable, clusterIndex = self:GetClusterFromArgs(...)
+  if clusterIndex == 1 then
+    for i, frame in ipairs(clusterTable) do
+      frame.clusterIndex = i + 1
+    end
   end
+  tinsert(clusterTable, clusterIndex, handler)
+  print('cluster', anchorGroup, 'table', clusterTable, 'position', clusterIndex)
+
+
+  handler.anchorCluster = clusterTable
+  handler.anchorIndex = clusterIndex
   for k,v in pairs(VeneerHandlerMixin) do
     if not handler[k] then
+      print(' * from mixin:', k)
       handler[k] = v
     end
   end
-  tinsert(clusterTable, handler)
-  handler:Reanchor()
+  if self.initialized then
+    print('  -- doing initialization')
+    if handler.Setup and not handler.initialized then
+      handler:Setup()
+      handler.initialized = true
+    end
+    if handler.Update then
+      handler:Update()
+    end
+    self:InternalReanchor(handler)
+
+  end
+end
+
+function VeneerCore:Reanchor()
+  self:ExecuteOnClusters(nil, 'Reanchor')
+end
+
+function VeneerCore:Update()
+  self:ExecuteOnClusters(nil, 'Update')
+end
+
+-- updates anchor relations to and from the target handler
+function VeneerCore:GetAnchor(...)
+
+end
+
+function VeneerCore:InternalReanchor(handler, printFunc)
+  print('|cFF00FFFFVeneer:InternalReanchor('..handler:GetName()..')')
+  local anchorPoint = handler.anchorPath or handler.anchorPoint
+  local anchorParent, anchorTo = UIParent, anchorPoint
+  for i, frame in ipairs(handler.anchorCluster) do
+    if frame ~= handler then
+      anchorParent = frame
+      anchorTo = ANCHOR_OFFSET_POINT[anchorPoint]
+
+    else
+      local nextFrame = handler.anchorCluster[i+1]
+      if nextFrame then
+
+        local subPoint = nextFrame.anchorPath or nextFrame.anchorPoint
+        local subTo = ANCHOR_OFFSET_POINT[subPoint]
+        nextFrame:ClearAllPoints()
+        nextFrame:SetPoint(subPoint, handler, subTo, 0, 0)
+        print(' -- pushing '..nextFrame:GetName()..' down the anchor chain', subPoint, subTo)
+      end
+      break
+    end
+  end
+
+  handler:ClearAllPoints()
+  handler:SetPoint(anchorPoint, anchorParent, anchorTo, 0, 0)
+
+  print(handler.anchorPoint, anchorParent, anchorTo)
+  if printFunc then
+    printFunc('|cFF88FF00'..handler:GetName()..':SetPoint(', handler.anchorPoint, anchorParent, anchorTo)
+  end
+
 end
 
 function VeneerCore:ExecuteOnClusters(layer, method)
   self.parserDepth = self.parserDepth + 1
-  layer = layer or self.FrameClusters
   if not layer then
-    if self.parserDepth >= 1 then
+    if self.parserDepth > 1 then
       tinsert(self.pendingCalls, method)
       print('delaying walk for', method)
       return
     end
-    print('|cFF00FFFFVeneer|r:'..method..'('..tostring(layer)..')')
+    print('|cFF00FF00Veneer:ExecuteOnClusters|r('..tostring(layer)..', '..method..')')
   else
-    print(' L'..self.parserDepth)
+    print(' Level '..self.parserDepth)
   end
+
+  layer = layer or self.FrameClusters
   for anchor, cluster in pairs(layer) do
     for index, frame in ipairs(cluster) do
-      print('  '..anchor..'.'..index..' = '..frame:GetName())
+      print(' '..anchor..'.'..index..' = '..frame:GetName())
       if frame[method] then
-        print('  '..frame:GetName()..':'..method..'(...)')
-        frame[method](frame)
+        print('  |cFF00FF00'..frame:GetName())
+        frame[method](frame, true)
       end
     end
     if cluster.FrameClusters then
@@ -153,10 +273,6 @@
   end
 end
 
-function VeneerCore:Update()
-  self:ExecuteOnClusters(nil, 'Update')
-end
-
 local VeneerButton_OnDragStart = function(self)
   self.startingLeft = self:GetLeft()
   self.startingBottom = self:GetBottom()