beta
This commit is contained in:
@@ -120,19 +120,22 @@ local function ConstructIconPicker(frame)
|
||||
iconLabel:SetPoint("RIGHT", input, "LEFT", -50, 0);
|
||||
|
||||
function group.Pick(self, texturePath)
|
||||
if(not self.groupIcon and self.data.controlledChildren) then
|
||||
for index, childId in pairs(self.data.controlledChildren) do
|
||||
local valueToPath = OptionsPrivate.Private.ValueToPath
|
||||
if(not self.groupIcon and self.baseObject.controlledChildren) then
|
||||
for index, childId in pairs(self.baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
childData[self.field] = texturePath;
|
||||
WeakAuras.Add(childData);
|
||||
valueToPath(childData, self.paths[childId], texturePath)
|
||||
WeakAuras.Add(childData)
|
||||
WeakAuras.ClearAndUpdateOptions(childData.id)
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
end
|
||||
end
|
||||
else
|
||||
self.data[self.field] = texturePath;
|
||||
WeakAuras.Add(self.data);
|
||||
WeakAuras.UpdateThumbnail(self.data);
|
||||
valueToPath(self.baseObject, self.paths[self.baseObject.id], texturePath)
|
||||
WeakAuras.Add(self.baseObject)
|
||||
WeakAuras.ClearAndUpdateOptions(self.baseObject.id)
|
||||
WeakAuras.UpdateThumbnail(self.baseObject)
|
||||
end
|
||||
local success = icon:SetTexture(texturePath) and texturePath;
|
||||
if(success) then
|
||||
@@ -142,20 +145,23 @@ local function ConstructIconPicker(frame)
|
||||
end
|
||||
end
|
||||
|
||||
function group.Open(self, data, field, groupIcon)
|
||||
self.data = data;
|
||||
self.field = field;
|
||||
function group.Open(self, baseObject, paths, groupIcon)
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
self.baseObject = baseObject
|
||||
self.paths = paths
|
||||
self.groupIcon = groupIcon
|
||||
if(not groupIcon and data.controlledChildren) then
|
||||
if(not groupIcon and baseObject.controlledChildren) then
|
||||
self.givenPath = {};
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
for index, childId in pairs(baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
self.givenPath[childId] = childData[field];
|
||||
local value = valueFromPath(childData, paths[childId])
|
||||
self.givenPath[childId] = value;
|
||||
end
|
||||
end
|
||||
else
|
||||
self.givenPath = self.data[self.field];
|
||||
local value = valueFromPath(self.baseObject, paths[self.baseObject.id])
|
||||
self.givenPath = value
|
||||
end
|
||||
-- group:Pick(self.givenPath);
|
||||
frame.window = "icon";
|
||||
@@ -170,17 +176,24 @@ local function ConstructIconPicker(frame)
|
||||
end
|
||||
|
||||
function group.CancelClose()
|
||||
if(not group.groupIcon and group.data.controlledChildren) then
|
||||
for index, childId in pairs(group.data.controlledChildren) do
|
||||
local valueToPath = OptionsPrivate.Private.ValueToPath
|
||||
if(not group.groupIcon and group.baseObject.controlledChildren) then
|
||||
for index, childId in pairs(group.baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
childData[group.field] = group.givenPath[childId] or childData[group.field];
|
||||
WeakAuras.Add(childData);
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
if (group.givenPath[childId]) then
|
||||
valueToPath(childData, group.paths[childId], group.givenPath[childId])
|
||||
WeakAuras.Add(childData);
|
||||
WeakAuras.ClearAndUpdateOptions(childData.id)
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
group:Pick(group.givenPath);
|
||||
valueToPath(group.baseObject, group.paths[group.baseObject.id], group.givenPath)
|
||||
WeakAuras.Add(group.baseObject)
|
||||
WeakAuras.ClearAndUpdateOptions(group.baseObject.id)
|
||||
WeakAuras.UpdateThumbnail(group.baseObject)
|
||||
end
|
||||
group.Close();
|
||||
end
|
||||
|
||||
@@ -15,6 +15,38 @@ local L = WeakAuras.L
|
||||
|
||||
local modelPicker
|
||||
|
||||
local function GetAll(baseObject, path, property, default)
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
if not property then
|
||||
return default
|
||||
end
|
||||
if baseObject.controlledChildren then
|
||||
local result
|
||||
local first = true
|
||||
for index, childId in pairs(baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId)
|
||||
local childObject = valueFromPath(childData, path)
|
||||
if childObject and childObject[property] then
|
||||
if first then
|
||||
result = childObject[property]
|
||||
first = false
|
||||
else
|
||||
if result ~= childObject[property] then
|
||||
return default
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
else
|
||||
local object = valueFromPath(baseObject, path)
|
||||
if object and object[property] then
|
||||
return object[property]
|
||||
end
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
local function ConstructModelPicker(frame)
|
||||
local group = AceGUI:Create("InlineGroup");
|
||||
group.frame:SetParent(frame);
|
||||
@@ -80,83 +112,101 @@ local function ConstructModelPicker(frame)
|
||||
model:SetFrameStrata("FULLSCREEN");
|
||||
group.model = model;
|
||||
|
||||
local function SetOnObject(object, model_path, model_z, model_x, model_y)
|
||||
if model_path then
|
||||
object.model_path = model_path
|
||||
end
|
||||
if model_z then
|
||||
object.model_z = model_z
|
||||
end
|
||||
if model_x then
|
||||
object.model_x = model_x
|
||||
end
|
||||
if model_y then
|
||||
object.model_y = model_y
|
||||
end
|
||||
end
|
||||
|
||||
function group.Pick(self, model_path, model_z, model_x, model_y)
|
||||
model_path = model_path or self.data.model_path;
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
|
||||
model_z = model_z or self.data.model_z;
|
||||
model_x = model_x or self.data.model_x;
|
||||
model_y = model_y or self.data.model_y;
|
||||
self.selectedValues.model_path = model_path or self.selectedValues.model_path
|
||||
self.selectedValues.model_x = model_x or self.selectedValues.model_x
|
||||
self.selectedValues.model_y = model_y or self.selectedValues.model_y
|
||||
self.selectedValues.model_z = model_z or self.selectedValues.model_z
|
||||
|
||||
WeakAuras.SetModel(self.model, model_path)
|
||||
WeakAuras.SetModel(self.model, self.selectedValues.model_path)
|
||||
|
||||
self.model:SetPosition(model_z, model_x, model_y);
|
||||
self.model:SetFacing(rad(self.data.rotation));
|
||||
self.model:SetPosition(self.selectedValues.model_z, self.selectedValues.model_x, self.selectedValues.model_y);
|
||||
self.model:SetFacing(rad(self.selectedValues.rotation));
|
||||
|
||||
if(not self.parentData and self.data.controlledChildren) then
|
||||
for index, childId in pairs(self.data.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
childData.model_path = model_path;
|
||||
childData.model_z = model_z;
|
||||
childData.model_x = model_x;
|
||||
childData.model_y = model_y;
|
||||
WeakAuras.Add(childData);
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
if(self.baseObject.controlledChildren) then
|
||||
for index, childId in pairs(self.baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId)
|
||||
local object = valueFromPath(childData, self.path)
|
||||
if(object) then
|
||||
SetOnObject(object, model_path, model_z, model_x, model_y)
|
||||
WeakAuras.Add(childData)
|
||||
WeakAuras.UpdateThumbnail(childData)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.data.model_path = model_path;
|
||||
self.data.model_z = model_z;
|
||||
self.data.model_x = model_x;
|
||||
self.data.model_y = model_y;
|
||||
|
||||
if self.parentData then
|
||||
WeakAuras.Add(self.parentData)
|
||||
else
|
||||
WeakAuras.Add(self.data);
|
||||
WeakAuras.UpdateThumbnail(self.data);
|
||||
local object = valueFromPath(self.baseObject, self.path)
|
||||
if object then
|
||||
SetOnObject(object, model_path, model_z, model_x, model_y)
|
||||
WeakAuras.Add(self.baseObject)
|
||||
WeakAuras.UpdateThumbnail(self.baseObject)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function group.Open(self, data, parentData)
|
||||
self.data = data;
|
||||
self.parentData = parentData
|
||||
WeakAuras.SetModel(self.model, data.model_path)
|
||||
function group.Open(self, baseObject, path)
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
|
||||
self.model:SetPosition(data.model_z, data.model_x, data.model_y);
|
||||
self.model:SetFacing(rad(data.rotation));
|
||||
modelPickerZ:SetValue(data.model_z);
|
||||
modelPickerZ.editbox:SetText(("%.2f"):format(data.model_z));
|
||||
modelPickerX:SetValue(data.model_x);
|
||||
modelPickerX.editbox:SetText(("%.2f"):format(data.model_x));
|
||||
modelPickerY:SetValue(data.model_y);
|
||||
modelPickerY.editbox:SetText(("%.2f"):format(data.model_y));
|
||||
self.baseObject = baseObject
|
||||
self.path = path
|
||||
self.selectedValues = {}
|
||||
|
||||
modelPickerZ.frame:Show();
|
||||
modelPickerY.frame:Show();
|
||||
modelPickerX.frame:Show();
|
||||
self.selectedValues.model_path = GetAll(baseObject, path, "model_path", "spells/arcanepower_state_chest.m2")
|
||||
|
||||
if(not parentData and data.controlledChildren) then
|
||||
WeakAuras.SetModel(self.model, self.selectedValues.model_path)
|
||||
|
||||
self.selectedValues.model_x = GetAll(baseObject, path, "model_x", 0)
|
||||
self.selectedValues.model_y = GetAll(baseObject, path, "model_y", 0)
|
||||
self.selectedValues.model_z = GetAll(baseObject, path, "model_z", 0)
|
||||
self.selectedValues.rotation = GetAll(baseObject, path, "rotation", 0)
|
||||
|
||||
self.model:SetPosition(self.selectedValues.model_z, self.selectedValues.model_x, self.selectedValues.model_y);
|
||||
self.model:SetFacing(rad(self.selectedValues.rotation));
|
||||
modelPickerZ:SetValue(self.selectedValues.model_z);
|
||||
modelPickerZ.editbox:SetText(("%.2f"):format(self.selectedValues.model_z));
|
||||
modelPickerX:SetValue(self.selectedValues.model_x);
|
||||
modelPickerX.editbox:SetText(("%.2f"):format(self.selectedValues.model_x));
|
||||
modelPickerY:SetValue(self.selectedValues.model_y);
|
||||
modelPickerY.editbox:SetText(("%.2f"):format(self.selectedValues.model_y));
|
||||
|
||||
if(baseObject.controlledChildren) then
|
||||
self.givenModel = {};
|
||||
self.givenZ = {};
|
||||
self.givenX = {};
|
||||
self.givenY = {};
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
self.givenModel[childId] = childData.model_path;
|
||||
self.givenZ[childId] = childData.model_z;
|
||||
self.givenX[childId] = childData.model_x;
|
||||
self.givenY[childId] = childData.model_y;
|
||||
for index, childId in pairs(baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId)
|
||||
local object = valueFromPath(childData, path)
|
||||
if(object) then
|
||||
self.givenModel[childId] = object.model_path;
|
||||
self.givenZ[childId] = object.model_z;
|
||||
self.givenX[childId] = object.model_x;
|
||||
self.givenY[childId] = object.model_y;
|
||||
end
|
||||
end
|
||||
else
|
||||
self.givenModel = data.model_path;
|
||||
local object = valueFromPath(baseObject, path)
|
||||
|
||||
self.givenZ = data.model_z;
|
||||
self.givenX = data.model_x;
|
||||
self.givenY = data.model_y;
|
||||
self.givenModel = object.model_path;
|
||||
self.givenZ = object.model_z;
|
||||
self.givenX = object.model_x;
|
||||
self.givenY = object.model_y;
|
||||
end
|
||||
frame.window = "model";
|
||||
frame:UpdateFrameVisible()
|
||||
@@ -169,20 +219,31 @@ local function ConstructModelPicker(frame)
|
||||
end
|
||||
|
||||
function group.CancelClose(self)
|
||||
if(not group.parentData and group.data.controlledChildren) then
|
||||
for index, childId in pairs(group.data.controlledChildren) do
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
if(group.baseObject.controlledChildren) then
|
||||
for index, childId in pairs(group.baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
childData.model_path = group.givenModel[childId];
|
||||
childData.model_z = group.givenZ[childId];
|
||||
childData.model_x = group.givenX[childId];
|
||||
childData.model_y = group.givenY[childId];
|
||||
local object = valueFromPath(childData, self.path)
|
||||
if(object) then
|
||||
object.model_path = group.givenModel[childId];
|
||||
object.model_z = group.givenZ[childId];
|
||||
object.model_x = group.givenX[childId];
|
||||
object.model_y = group.givenY[childId];
|
||||
WeakAuras.Add(childData);
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
end
|
||||
end
|
||||
else
|
||||
group:Pick(group.givenModel, group.givenZ, group.givenX, group.givenY);
|
||||
local object = valueFromPath(self.baseObject, self.path)
|
||||
|
||||
if(object) then
|
||||
object.model_path = group.givenModel
|
||||
object.model_z = group.givenZ
|
||||
object.model_x = group.givenX
|
||||
object.model_y = group.givenY
|
||||
WeakAuras.Add(self.baseObject);
|
||||
WeakAuras.UpdateThumbnail(self.baseObject);
|
||||
end
|
||||
end
|
||||
group.Close();
|
||||
end
|
||||
|
||||
@@ -10,6 +10,7 @@ local IsShiftKeyDown, CreateFrame = IsShiftKeyDown, CreateFrame
|
||||
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
|
||||
|
||||
local WeakAuras = WeakAuras
|
||||
local L = WeakAuras.L
|
||||
|
||||
local moversizer
|
||||
local mover
|
||||
@@ -63,9 +64,11 @@ local function ConstructMover(frame)
|
||||
local top = CreateFrame("BUTTON", nil, topAndBottom)
|
||||
top:SetSize(25, 25)
|
||||
top:SetPoint("TOP", topAndBottom)
|
||||
top:SetFrameStrata("BACKGROUND")
|
||||
local bottom = CreateFrame("BUTTON", nil, topAndBottom)
|
||||
bottom:SetSize(25, 25)
|
||||
bottom:SetPoint("BOTTOM", topAndBottom)
|
||||
bottom:SetFrameStrata("BACKGROUND")
|
||||
|
||||
local leftAndRight = CreateFrame("Frame", nil, frame)
|
||||
leftAndRight:SetClampedToScreen(true)
|
||||
@@ -74,9 +77,11 @@ local function ConstructMover(frame)
|
||||
local left = CreateFrame("BUTTON", nil, leftAndRight)
|
||||
left:SetSize(25, 25)
|
||||
left:SetPoint("LEFT", leftAndRight)
|
||||
left:SetFrameStrata("BACKGROUND")
|
||||
local right = CreateFrame("BUTTON", nil, leftAndRight)
|
||||
right:SetSize(25, 25)
|
||||
right:SetPoint("RIGHT", leftAndRight)
|
||||
right:SetFrameStrata("BACKGROUND")
|
||||
|
||||
top:SetNormalTexture("interface\\buttons\\ui-scrollbar-scrollupbutton-up.blp")
|
||||
top:SetHighlightTexture("interface\\buttons\\ui-scrollbar-scrollupbutton-highlight.blp")
|
||||
@@ -107,6 +112,23 @@ local function ConstructMover(frame)
|
||||
right:GetPushedTexture():SetRotation(-math.pi/2)
|
||||
right:SetScript("OnClick", function() moveOnePxl("right") end)
|
||||
|
||||
local arrow = CreateFrame("frame", nil, frame)
|
||||
arrow:SetClampedToScreen(true)
|
||||
arrow:SetSize(196, 196)
|
||||
arrow:SetPoint("CENTER", frame, "CENTER")
|
||||
arrow:SetFrameStrata("HIGH")
|
||||
local arrowTexture = arrow:CreateTexture()
|
||||
arrowTexture:SetTexture("Interface\\Addons\\WeakAuras\\Media\\Textures\\offscreen.tga")
|
||||
arrowTexture:SetSize(128, 128)
|
||||
arrowTexture:SetPoint("CENTER", arrow, "CENTER")
|
||||
arrowTexture:SetVertexColor(0.8, 0.8, 0.2)
|
||||
arrowTexture:Hide()
|
||||
local offscreenText = arrow:CreateFontString(nil, "OVERLAY")
|
||||
offscreenText:SetFont(STANDARD_TEXT_FONT, 14, "THICKOUTLINE");
|
||||
offscreenText:SetText(L["Aura is\nOff Screen"])
|
||||
offscreenText:Hide()
|
||||
offscreenText:SetPoint("CENTER", arrow, "CENTER")
|
||||
|
||||
--local lineX = frame:CreateLine(nil, "OVERLAY", 7)
|
||||
local lineX = frame:CreateTexture(nil, "OVERLAY", 7)
|
||||
lineX:SetSize(2, 2)
|
||||
@@ -123,7 +145,7 @@ local function ConstructMover(frame)
|
||||
lineY:SetPoint("BOTTOMLEFT", UIParent)
|
||||
lineY:Hide()
|
||||
|
||||
return lineX, lineY
|
||||
return lineX, lineY, arrowTexture, offscreenText
|
||||
end
|
||||
|
||||
local function ConstructSizer(frame)
|
||||
@@ -150,6 +172,9 @@ local function ConstructSizer(frame)
|
||||
texTR2:SetPoint("BOTTOMLEFT", topright, "LEFT")
|
||||
|
||||
topright.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texTR1:Show()
|
||||
texTR2:Show()
|
||||
end
|
||||
@@ -179,6 +204,9 @@ local function ConstructSizer(frame)
|
||||
texBR2:SetPoint("TOPLEFT", bottomright, "LEFT")
|
||||
|
||||
bottomright.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texBR1:Show()
|
||||
texBR2:Show()
|
||||
end
|
||||
@@ -208,6 +236,9 @@ local function ConstructSizer(frame)
|
||||
texBL2:SetPoint("TOPRIGHT", bottomleft, "RIGHT")
|
||||
|
||||
bottomleft.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texBL1:Show()
|
||||
texBL2:Show()
|
||||
end
|
||||
@@ -237,6 +268,9 @@ local function ConstructSizer(frame)
|
||||
texTL2:SetPoint("BOTTOMRIGHT", topleft, "RIGHT")
|
||||
|
||||
topleft.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texTL1:Show()
|
||||
texTL2:Show()
|
||||
end
|
||||
@@ -260,6 +294,9 @@ local function ConstructSizer(frame)
|
||||
texT:SetPoint("BOTTOMLEFT", topleft, "LEFT", 3, 0)
|
||||
|
||||
top.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texT:Show()
|
||||
end
|
||||
top.Clear = function()
|
||||
@@ -279,6 +316,9 @@ local function ConstructSizer(frame)
|
||||
texR:SetPoint("TOPLEFT", topright, "TOP", 0, -3)
|
||||
|
||||
right.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texR:Show()
|
||||
end
|
||||
right.Clear = function()
|
||||
@@ -299,6 +339,9 @@ local function ConstructSizer(frame)
|
||||
texB:SetPoint("TOPRIGHT", bottomright, "RIGHT", -3, 0)
|
||||
|
||||
bottom.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texB:Show()
|
||||
end
|
||||
bottom.Clear = function()
|
||||
@@ -319,6 +362,9 @@ local function ConstructSizer(frame)
|
||||
texL:SetPoint("TOPRIGHT", topleft, "TOP", 0, -3)
|
||||
|
||||
left.Highlight = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
texL:Show()
|
||||
end
|
||||
left.Clear = function()
|
||||
@@ -389,7 +435,7 @@ local function ConstructMoverSizer(parent)
|
||||
frame.top, frame.topright, frame.right, frame.bottomright, frame.bottom, frame.bottomleft, frame.left, frame.topleft
|
||||
= ConstructSizer(frame)
|
||||
|
||||
frame.lineX, frame.lineY = ConstructMover(frame)
|
||||
frame.lineX, frame.lineY, frame.arrowTexture, frame.offscreenText = ConstructMover(frame)
|
||||
|
||||
frame.top.Clear()
|
||||
frame.topright.Clear()
|
||||
@@ -481,7 +527,7 @@ local function ConstructMoverSizer(parent)
|
||||
if data.regionType == "group" then
|
||||
mover:SetWidth((region.trx - region.blx) * scale)
|
||||
mover:SetHeight((region.try - region.bly) * scale)
|
||||
mover:SetPoint(mover.selfPoint or "CENTER", mover.anchor or UIParent, mover.anchorPoint or "CENTER", (xOff + region.blx) * scale, (yOff + region.bly) * scale)
|
||||
mover:SetPoint("BOTTOMLEFT", mover.anchor or UIParent, mover.anchorPoint or "CENTER", (xOff + region.blx) * scale, (yOff + region.bly) * scale)
|
||||
else
|
||||
mover:SetWidth(region:GetWidth() * scale)
|
||||
mover:SetHeight(region:GetHeight() * scale)
|
||||
@@ -499,10 +545,13 @@ local function ConstructMoverSizer(parent)
|
||||
|
||||
local db = OptionsPrivate.savedVars.db
|
||||
mover.startMoving = function()
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
OptionsPrivate.Private.CancelAnimation(region, true, true, true, true, true)
|
||||
mover:ClearAllPoints()
|
||||
if data.regionType == "group" then
|
||||
mover:SetPoint(mover.selfPoint, region, mover.anchorPoint, region.blx * scale, region.bly * scale)
|
||||
mover:SetPoint("BOTTOMLEFT", region, mover.anchorPoint, region.blx * scale, region.bly * scale)
|
||||
else
|
||||
mover:SetPoint(mover.selfPoint, region, mover.selfPoint)
|
||||
end
|
||||
@@ -602,7 +651,7 @@ local function ConstructMoverSizer(parent)
|
||||
if data.regionType == "group" then
|
||||
mover:SetWidth((region.trx - region.blx) * scale)
|
||||
mover:SetHeight((region.try - region.bly) * scale)
|
||||
mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, (xOff + region.blx) * scale, (yOff + region.bly) * scale)
|
||||
mover:SetPoint("BOTTOMLEFT", mover.anchor, mover.anchorPoint, (xOff + region.blx) * scale, (yOff + region.bly) * scale)
|
||||
else
|
||||
mover:SetWidth(region:GetWidth() * scale)
|
||||
mover:SetHeight(region:GetHeight() * scale)
|
||||
@@ -636,6 +685,9 @@ local function ConstructMoverSizer(parent)
|
||||
|
||||
if region:IsResizable() then
|
||||
frame.startSizing = function(point)
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
return
|
||||
end
|
||||
mover.isMoving = true
|
||||
OptionsPrivate.Private.CancelAnimation(region, true, true, true, true, true)
|
||||
local rSelfPoint, rAnchor, rAnchorPoint, rXOffset, rYOffset = region:GetPoint(1)
|
||||
@@ -726,7 +778,7 @@ local function ConstructMoverSizer(parent)
|
||||
if data.regionType == "group" then
|
||||
mover:SetWidth((region.trx - region.blx) * scale)
|
||||
mover:SetHeight((region.try - region.bly) * scale)
|
||||
mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, (xOff + region.blx) * scale, (yOff + region.bly) * scale)
|
||||
mover:SetPoint("BOTTOMLEFT", mover.anchor, mover.anchorPoint, (xOff + region.blx) * scale, (yOff + region.bly) * scale)
|
||||
else
|
||||
mover:SetWidth(region:GetWidth() * scale)
|
||||
mover:SetHeight(region:GetHeight() * scale)
|
||||
@@ -878,6 +930,23 @@ local function ConstructMoverSizer(parent)
|
||||
self.interims[i]:SetPoint("CENTER", self.anchorPointIcon, "CENTER", x, y)
|
||||
self.interims[i]:Show()
|
||||
end
|
||||
|
||||
-- HERE
|
||||
frame.arrowTexture:Hide()
|
||||
frame.offscreenText:Hide()
|
||||
|
||||
-- Check if the center is offscreen
|
||||
local x, y = mover:GetCenter()
|
||||
if x and y then
|
||||
if x < 0 or x > GetScreenWidth() or y < 0 or y > GetScreenHeight() then
|
||||
local arrowX, arrowY = frame.arrowTexture:GetCenter()
|
||||
local arrowAngle = atan2(selfY - arrowY, selfX - arrowX)
|
||||
frame.offscreenText:Show()
|
||||
frame.arrowTexture:Show()
|
||||
frame.arrowTexture:SetRotation( (arrowAngle - 90) / 180 * math.pi)
|
||||
end
|
||||
end
|
||||
|
||||
local regionScale = self.moving.region:GetScale()
|
||||
self.text:SetText(("(%.2f, %.2f)"):format(dX*1/regionScale, dY*1/regionScale))
|
||||
local midX = (distance / 2) * cos(angle)
|
||||
|
||||
@@ -171,11 +171,11 @@ function OptionsPrivate.CreateFrame()
|
||||
frame:Hide()
|
||||
|
||||
frame:SetScript("OnHide", function()
|
||||
OptionsPrivate.Private.ClearFakeStates()
|
||||
OptionsPrivate.SetDragging()
|
||||
|
||||
OptionsPrivate.Private.PauseAllDynamicGroups()
|
||||
|
||||
OptionsPrivate.Private.ClearFakeStates()
|
||||
|
||||
|
||||
for id, data in pairs(WeakAuras.regions) do
|
||||
data.region:Collapse()
|
||||
data.region:OptionsClosed()
|
||||
@@ -446,7 +446,7 @@ function OptionsPrivate.CreateFrame()
|
||||
tipPopupCtrlC:SetPoint("TOPRIGHT", urlWidget, "BOTTOMRIGHT", 0, 0)
|
||||
tipPopupCtrlC:SetJustifyH("LEFT")
|
||||
tipPopupCtrlC:SetJustifyV("TOP")
|
||||
tipPopupCtrlC:SetText("Press Ctrl+C to copy the URL")
|
||||
tipPopupCtrlC:SetText(L["Press Ctrl+C to copy the URL"])
|
||||
|
||||
local function ToggleTip(referenceWidget, url, title, description)
|
||||
if tipPopup:IsVisible() and urlWidget.text == url then
|
||||
@@ -476,10 +476,12 @@ function OptionsPrivate.CreateFrame()
|
||||
tipFrame:AddChild(button)
|
||||
end
|
||||
|
||||
addFooter(L["Get Help"], [[Interface\AddOns\WeakAuras\Media\Textures\discord.tga]], "https://discord.gg/wa2",
|
||||
addFooter(L["Get Help"], [[Interface\AddOns\WeakAuras\Media\Textures\discord.tga]], "https://discord.gg/weakauras",
|
||||
L["Chat with WeakAuras experts on our Discord server."])
|
||||
|
||||
addFooter(L["Documentation"], [[Interface\AddOns\WeakAuras\Media\Textures\GitHub.tga]], "https://github.com/WeakAuras/WeakAuras2/wiki",
|
||||
L["Check out our wiki for a large collection of examples and snippets."])
|
||||
|
||||
addFooter(L["Find Auras"], [[Interface\AddOns\WeakAuras\Media\Textures\wagoupdate_logo.tga]], "https://wago.io",
|
||||
L["Browse Wago, the largest collection of auras."])
|
||||
|
||||
@@ -487,8 +489,9 @@ function OptionsPrivate.CreateFrame()
|
||||
addFooter(L["Update Auras"], [[Interface\AddOns\WeakAuras\Media\Textures\wagoupdate_refresh.tga]], "https://weakauras.wtf",
|
||||
L["Keep your Wago imports up to date with the Companion App."])
|
||||
end
|
||||
addFooter(L["Found a Bug?"], [[Interface\AddOns\WeakAuras\Media\Textures\bug_report.tga]], "https://github.com/WeakAuras/WeakAuras2/issues/new",
|
||||
L["Report bugs our our issue tracker."])
|
||||
|
||||
addFooter(L["Found a Bug?"], [[Interface\AddOns\WeakAuras\Media\Textures\bug_report.tga]], "https://github.com/WeakAuras/WeakAuras2/issues/new?assignees=&labels=%F0%9F%90%9B+Bug&template=bug_report.md&title=",
|
||||
L["Report bugs on our issue tracker."])
|
||||
|
||||
-- Disable for now
|
||||
--local closeTipButton = CreateFrame("Button", nil, tipFrame.frame, "UIPanelCloseButton")
|
||||
@@ -601,6 +604,25 @@ function OptionsPrivate.CreateFrame()
|
||||
importButton:SetCallback("OnClick", OptionsPrivate.ImportFromString)
|
||||
toolbarContainer:AddChild(importButton)
|
||||
|
||||
local lockButton = AceGUI:Create("WeakAurasToolbarButton")
|
||||
lockButton:SetText(L["Lock Positions"])
|
||||
lockButton:SetTexture("Interface\\AddOns\\WeakAuras\\Media\\Textures\\lockPosition")
|
||||
lockButton:SetCallback("OnClick", function(self)
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
lockButton:SetStrongHighlight(false)
|
||||
lockButton:UnlockHighlight()
|
||||
WeakAurasOptionsSaved.lockPositions = false
|
||||
else
|
||||
lockButton:SetStrongHighlight(true)
|
||||
lockButton:LockHighlight()
|
||||
WeakAurasOptionsSaved.lockPositions = true
|
||||
end
|
||||
end)
|
||||
if WeakAurasOptionsSaved.lockPositions then
|
||||
lockButton:LockHighlight()
|
||||
end
|
||||
toolbarContainer:AddChild(lockButton)
|
||||
|
||||
local magnetButton = AceGUI:Create("WeakAurasToolbarButton")
|
||||
magnetButton:SetText(L["Magnetically Align"])
|
||||
magnetButton:SetTexture("Interface\\AddOns\\WeakAuras\\Media\\Textures\\magnetic")
|
||||
@@ -781,6 +803,7 @@ function OptionsPrivate.CreateFrame()
|
||||
unloadedButton:SetExpandDescription(L["Expand all non-loaded displays"])
|
||||
unloadedButton:SetCollapseDescription(L["Collapse all non-loaded displays"])
|
||||
unloadedButton:SetViewClick(function()
|
||||
OptionsPrivate.Private.PauseAllDynamicGroups()
|
||||
if unloadedButton.view.func() == 2 then
|
||||
for id, child in pairs(displayButtons) do
|
||||
if OptionsPrivate.Private.loaded[id] == nil then
|
||||
@@ -794,6 +817,7 @@ function OptionsPrivate.CreateFrame()
|
||||
end
|
||||
end
|
||||
end
|
||||
OptionsPrivate.Private.ResumeAllDynamicGroups()
|
||||
end)
|
||||
unloadedButton:SetViewTest(function()
|
||||
local none, all = true, true
|
||||
@@ -821,6 +845,7 @@ function OptionsPrivate.CreateFrame()
|
||||
|
||||
frame.ClearOptions = function(self, id)
|
||||
aceOptions[id] = nil
|
||||
OptionsPrivate.commonOptionsCache:Clear()
|
||||
if type(id) == "string" then
|
||||
local data = WeakAuras.GetData(id)
|
||||
if data and data.parent then
|
||||
@@ -862,6 +887,7 @@ function OptionsPrivate.CreateFrame()
|
||||
if not self.pickedDisplay then
|
||||
return
|
||||
end
|
||||
OptionsPrivate.commonOptionsCache:Clear()
|
||||
self.selectedTab = self.selectedTab or "region"
|
||||
local data
|
||||
if type(self.pickedDisplay) == "string" then
|
||||
@@ -916,6 +942,8 @@ function OptionsPrivate.CreateFrame()
|
||||
return
|
||||
end
|
||||
|
||||
OptionsPrivate.commonOptionsCache:Clear()
|
||||
|
||||
frame:UpdateOptions()
|
||||
|
||||
local data
|
||||
@@ -1179,6 +1207,9 @@ function OptionsPrivate.CreateFrame()
|
||||
if self.pickedDisplay == id then
|
||||
return
|
||||
end
|
||||
|
||||
OptionsPrivate.Private.PauseAllDynamicGroups()
|
||||
|
||||
self:ClearPicks(noHide)
|
||||
local data = WeakAuras.GetData(id)
|
||||
|
||||
@@ -1206,7 +1237,6 @@ function OptionsPrivate.CreateFrame()
|
||||
self.selectedTab = tab
|
||||
end
|
||||
self:FillOptions()
|
||||
|
||||
WeakAuras.SetMoverSizer(id)
|
||||
|
||||
local _, _, _, _, yOffset = displayButtons[id].frame:GetPoint(1)
|
||||
@@ -1216,6 +1246,7 @@ function OptionsPrivate.CreateFrame()
|
||||
if yOffset then
|
||||
self.buttonsScroll:SetScrollPos(yOffset, yOffset - 32)
|
||||
end
|
||||
|
||||
if data.controlledChildren then
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
displayButtons[childId]:PriorityShow(1)
|
||||
@@ -1225,6 +1256,8 @@ function OptionsPrivate.CreateFrame()
|
||||
if data.controlledChildren and #data.controlledChildren == 0 then
|
||||
WeakAurasOptions:NewAura(true)
|
||||
end
|
||||
|
||||
OptionsPrivate.Private.ResumeAllDynamicGroups()
|
||||
end
|
||||
|
||||
frame.CenterOnPicked = function(self)
|
||||
|
||||
@@ -559,7 +559,7 @@ local function ConstructTextEditor(frame)
|
||||
end
|
||||
)
|
||||
|
||||
function group.Open(self, data, path, enclose, multipath, reloadOptions, setOnParent, url)
|
||||
function group.Open(self, data, path, enclose, multipath, reloadOptions, setOnParent, url, validator)
|
||||
self.data = data
|
||||
self.path = path
|
||||
self.multipath = multipath
|
||||
@@ -602,14 +602,17 @@ local function ConstructTextEditor(frame)
|
||||
"OnTextChanged",
|
||||
function(...)
|
||||
local str = editor.editBox:GetText()
|
||||
if not (str) or editor.combinedText == true then
|
||||
if not str or str:trim() == "" or editor.combinedText == true then
|
||||
editorError:SetText("")
|
||||
else
|
||||
local _, errorString
|
||||
local func, errorString
|
||||
if (enclose) then
|
||||
_, errorString = loadstring("return function() " .. str .. "\n end")
|
||||
func, errorString = loadstring("return function() " .. str .. "\n end")
|
||||
else
|
||||
_, errorString = loadstring("return " .. str)
|
||||
func, errorString = loadstring("return " .. str)
|
||||
end
|
||||
if not errorString and validator then
|
||||
errorString = validator(func())
|
||||
end
|
||||
if errorString then
|
||||
urlText:Hide()
|
||||
@@ -632,7 +635,12 @@ local function ConstructTextEditor(frame)
|
||||
local combinedText = ""
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId)
|
||||
local text = OptionsPrivate.Private.ValueFromPath(childData, multipath and path[childId] or path)
|
||||
local text
|
||||
if multipath then
|
||||
text = path[childId] and OptionsPrivate.Private.ValueFromPath(childData, path[childId])
|
||||
else
|
||||
text = OptionsPrivate.Private.ValueFromPath(childData, path)
|
||||
end
|
||||
if text then
|
||||
if not (singleText) then
|
||||
singleText = text
|
||||
|
||||
@@ -37,18 +37,23 @@ local function CompareValues(a, b)
|
||||
end
|
||||
end
|
||||
|
||||
local function GetAll(data, property, default)
|
||||
if data.controlledChildren then
|
||||
local function GetAll(baseObject, path, property, default)
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
if not property then
|
||||
return default
|
||||
end
|
||||
if baseObject.controlledChildren then
|
||||
local result
|
||||
local first = true
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
for index, childId in pairs(baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId)
|
||||
if childData[property] ~= nil then
|
||||
local childObject = valueFromPath(childData, path)
|
||||
if childObject and childObject[property] then
|
||||
if first then
|
||||
result = childData[property]
|
||||
result = childObject[property]
|
||||
first = false
|
||||
else
|
||||
if not CompareValues(result, childData[property]) then
|
||||
if not CompareValues(result, childObject[property]) then
|
||||
return default
|
||||
end
|
||||
end
|
||||
@@ -56,23 +61,33 @@ local function GetAll(data, property, default)
|
||||
end
|
||||
return result
|
||||
else
|
||||
if data[property] ~= nil then
|
||||
return data[property]
|
||||
local object = valueFromPath(baseObject, path)
|
||||
if object and object[property] then
|
||||
return object[property]
|
||||
end
|
||||
return default
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function SetAll(data, property, value)
|
||||
if data.controlledChildren then
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
local function SetAll(baseObject, path, property, value)
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
if baseObject.controlledChildren then
|
||||
for index, childId in pairs(baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId)
|
||||
childData[property] = value
|
||||
WeakAuras.Add(childData)
|
||||
local object = valueFromPath(childData, path)
|
||||
if object then
|
||||
object[property] = value
|
||||
WeakAuras.Add(childData)
|
||||
WeakAuras.UpdateThumbnail(childData)
|
||||
end
|
||||
end
|
||||
else
|
||||
data[property] = value
|
||||
local object = valueFromPath(baseObject, path)
|
||||
if object then
|
||||
object[property] = value
|
||||
WeakAuras.Add(baseObject)
|
||||
WeakAuras.UpdateThumbnail(baseObject)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -114,6 +129,10 @@ local function ConstructTexturePicker(frame)
|
||||
textureWidget:ChangeTexture(d.r, d.g, d.b, d.a, d.rotate, d.discrete_rotation, d.rotation, d.mirror, d.blendMode);
|
||||
end
|
||||
|
||||
if group.selectedTextures[texturePath] then
|
||||
textureWidget:Pick()
|
||||
end
|
||||
|
||||
textureWidget:SetClick(function()
|
||||
group:Pick(texturePath);
|
||||
end);
|
||||
@@ -129,7 +148,6 @@ local function ConstructTexturePicker(frame)
|
||||
end
|
||||
end);
|
||||
end
|
||||
group:Pick(group.data[group.field]);
|
||||
end
|
||||
|
||||
dropdown:SetCallback("OnGroupSelected", texturePickerGroupSelected)
|
||||
@@ -139,7 +157,7 @@ local function ConstructTexturePicker(frame)
|
||||
for categoryName, category in pairs(self.textures) do
|
||||
local match = false;
|
||||
for texturePath, textureName in pairs(category) do
|
||||
if(texturePath == self.data[self.field]) then
|
||||
if(self.selectedTextures[texturePath]) then
|
||||
match = true;
|
||||
break;
|
||||
end
|
||||
@@ -161,72 +179,67 @@ local function ConstructTexturePicker(frame)
|
||||
pickedwidget:Pick();
|
||||
end
|
||||
|
||||
SetAll(self.data, self.field, texturePath);
|
||||
if(type(self.parentData.id) == "string") then
|
||||
WeakAuras.Add(self.parentData);
|
||||
WeakAuras.UpdateThumbnail(self.parentData);
|
||||
end
|
||||
wipe(group.selectedTextures)
|
||||
group.selectedTextures[texturePath] = true
|
||||
|
||||
SetAll(self.baseObject, self.path, self.properties.texture, texturePath)
|
||||
|
||||
group:UpdateList();
|
||||
local status = dropdown.status or dropdown.localstatus
|
||||
dropdown.dropdown:SetText(dropdown.list[status.selected]);
|
||||
end
|
||||
|
||||
function group.Open(self, data, parentData, field, textures, SetTextureFunc)
|
||||
self.data = data
|
||||
self.parentData = parentData
|
||||
self.field = field;
|
||||
function group.Open(self, baseObject, path, properties, textures, SetTextureFunc)
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
self.baseObject = baseObject
|
||||
self.path = path
|
||||
self.properties = properties
|
||||
self.textures = textures;
|
||||
self.SetTextureFunc = SetTextureFunc
|
||||
if(data.controlledChildren) then
|
||||
self.givenPath = {};
|
||||
for index, childId in pairs(data.controlledChildren) do
|
||||
self.givenPath = {};
|
||||
self.selectedTextures = {}
|
||||
if(baseObject.controlledChildren) then
|
||||
for index, childId in pairs(baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
self.givenPath[childId] = childData[field];
|
||||
local childObject = valueFromPath(childData, path)
|
||||
if childObject and childObject[properties.texture] then
|
||||
self.givenPath[childId] = childObject[properties.texture]
|
||||
self.selectedTextures[childObject[properties.texture]] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
local colorAll = GetAll(data, "color", {1, 1, 1, 1});
|
||||
self.textureData = {
|
||||
r = colorAll[1] or 1,
|
||||
g = colorAll[2] or 1,
|
||||
b = colorAll[3] or 1,
|
||||
a = colorAll[4] or 1,
|
||||
rotate = GetAll(data, "rotate", false),
|
||||
discrete_rotation = GetAll(data, "discrete_rotation", 0),
|
||||
rotation = GetAll(data, "rotation", 0),
|
||||
mirror = GetAll(data, "mirror", false),
|
||||
blendMode = GetAll(data, "blendMode", "ADD")
|
||||
};
|
||||
else
|
||||
self.givenPath = data[field];
|
||||
data.color = data.color or {};
|
||||
self.textureData = {
|
||||
r = data.color[1] or 1,
|
||||
g = data.color[2] or 1,
|
||||
b = data.color[3] or 1,
|
||||
a = data.color[4] or 1,
|
||||
rotate = data.rotate,
|
||||
discrete_rotation = data.discrete_rotation or 0,
|
||||
rotation = data.rotation or 0,
|
||||
mirror = data.mirror,
|
||||
blendMode = data.blendMode or "ADD"
|
||||
};
|
||||
local object = valueFromPath(baseObject, path)
|
||||
if object and object[properties.texture] then
|
||||
self.givenPath[baseObject.id] = object[properties.texture]
|
||||
self.selectedTextures[object[properties.texture]] = true
|
||||
end
|
||||
end
|
||||
|
||||
local colorAll = GetAll(baseObject, path, properties.color, {1, 1, 1, 1});
|
||||
self.textureData = {
|
||||
r = colorAll[1] or 1,
|
||||
g = colorAll[2] or 1,
|
||||
b = colorAll[3] or 1,
|
||||
a = colorAll[4] or 1,
|
||||
rotate = GetAll(baseObject, path, properties.rotate, true),
|
||||
discrete_rotation = GetAll(baseObject, path, properties.discrete_rotation, 0),
|
||||
rotation = GetAll(baseObject, path, properties.rotation, 0),
|
||||
mirror = GetAll(baseObject, path, properties.mirror, false),
|
||||
blendMode = GetAll(baseObject, path, properties.blendMode, "ADD")
|
||||
}
|
||||
|
||||
frame.window = "texture";
|
||||
frame:UpdateFrameVisible()
|
||||
group:UpdateList()
|
||||
local _, givenPath = next(self.givenPath)
|
||||
local picked = false;
|
||||
local _, givenPath
|
||||
if type(self.givenPath) == "string" then
|
||||
givenPath = self.givenPath;
|
||||
else
|
||||
_, givenPath = next(self.givenPath);
|
||||
end
|
||||
for categoryName, category in pairs(self.textures) do
|
||||
if not(picked) then
|
||||
for texturePath, textureName in pairs(category) do
|
||||
if(texturePath == givenPath) then
|
||||
if(self.selectedTextures[texturePath]) then
|
||||
dropdown:SetGroup(categoryName);
|
||||
self:Pick(givenPath);
|
||||
picked = true;
|
||||
break;
|
||||
end
|
||||
@@ -248,17 +261,26 @@ local function ConstructTexturePicker(frame)
|
||||
end
|
||||
|
||||
function group.CancelClose()
|
||||
if(group.parentData.controlledChildren) then
|
||||
for index, childId in pairs(group.parentData.controlledChildren) do
|
||||
local valueFromPath = OptionsPrivate.Private.ValueFromPath
|
||||
if(group.baseObject.controlledChildren) then
|
||||
for index, childId in pairs(group.baseObject.controlledChildren) do
|
||||
local childData = WeakAuras.GetData(childId);
|
||||
if(childData) then
|
||||
childData[group.field] = group.givenPath[childId];
|
||||
WeakAuras.Add(childData);
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
local childObject = valueFromPath(childData, group.path)
|
||||
if childObject then
|
||||
childObject[group.properties.texture] = group.givenPath[childId]
|
||||
WeakAuras.Add(childData);
|
||||
WeakAuras.UpdateThumbnail(childData);
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
group:Pick(group.givenPath);
|
||||
local object = valueFromPath(group.baseObject, group.path)
|
||||
if object then
|
||||
object[group.properties.texture] = group.givenPath[group.baseObject.id]
|
||||
WeakAuras.Add(group.baseObject)
|
||||
WeakAuras.UpdateThumbnail(group.baseObject)
|
||||
end
|
||||
end
|
||||
group.Close();
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user