|
DefineClass.XFrame = { |
|
__parents = { "XControl" }, |
|
|
|
properties = { |
|
{ category = "Image", id = "Image", name = "Frame image", editor = "ui_image", default = "", invalidate = true, }, |
|
{ category = "Image", id = "ImageScale", name = "Frame scale", editor = "point2d", default = point(1000, 1000), invalidate = true, lock_ratio = true, }, |
|
{ category = "Image", id = "FrameBox", name = "Frame box", editor = "padding", default = box(0, 0, 0, 0), invalidate = true, }, |
|
{ category = "Image", id = "Rows", editor = "number", default = 1, invalidate = true, }, |
|
{ category = "Image", id = "Columns", editor = "number", default = 1, invalidate = true, }, |
|
{ category = "Image", id = "Row", editor = "number", default = 1, invalidate = true, }, |
|
{ category = "Image", id = "Column", editor = "number", default = 1, invalidate = true, }, |
|
{ category = "Image", id = "TileFrame", editor = "bool", default = false, invalidate = true, }, |
|
{ category = "Image", id = "SqueezeX", editor = "bool", default = true, invalidate = true, }, |
|
{ category = "Image", id = "SqueezeY", editor = "bool", default = true, invalidate = true, }, |
|
{ category = "Image", id = "TransparentCenter", editor = "bool", default = false, invalidate = true, }, |
|
{ category = "Image", id = "FlipX", editor = "bool", default = false, invalidate = true, }, |
|
{ category = "Image", id = "FlipY", editor = "bool", default = false, invalidate = true, }, |
|
{ category = "Image", id = "Desaturation", editor = "number", default = 0, min = 0, max = 255, slider = true, invalidate = true, }, |
|
}, |
|
Background = RGB(255, 255, 255), |
|
FocusedBackground = RGB(255, 255, 255), |
|
HandleMouse = false, |
|
image_id = const.InvalidResourceID, |
|
image_obj = false, |
|
} |
|
|
|
function XFrame:Init() |
|
self:SetImage(self.Image, true) |
|
end |
|
|
|
function XFrame:Done() |
|
if self.image_obj ~= false then |
|
self.image_obj:ReleaseRef() |
|
self.image_obj = false |
|
end |
|
end |
|
|
|
local InvalidResourceID = const.InvalidResourceID |
|
function XFrame:SetImage(image, force) |
|
if self.Image == (image or "") and not force then return end |
|
self.Image = image or nil |
|
|
|
self:DeleteThread("LoadImage") |
|
if (self.Image or "") == "" then |
|
return |
|
end |
|
|
|
if self.image_obj ~= false then |
|
self.image_obj:ReleaseRef() |
|
self.image_obj = false |
|
end |
|
|
|
self.image_id = ResourceManager.GetResourceID(self.Image) |
|
if self.image_id == InvalidResourceID then |
|
printf("once", "Could not load image %s!", self.Image or "") |
|
return |
|
end |
|
|
|
self.image_obj = ResourceManager.GetResource(self.image_id) |
|
if self.image_obj then |
|
self:InvalidateMeasure() |
|
self:Invalidate() |
|
else |
|
self:CreateThread("LoadImage", function(self) |
|
self.image_obj = AsyncGetResource(self.image_id) |
|
self:InvalidateMeasure() |
|
self:Invalidate() |
|
end, self) |
|
end |
|
end |
|
|
|
function XFrame:Measure(preferred_width, preferred_height) |
|
local width, height = XControl.Measure(self, preferred_width, preferred_height) |
|
if self.image_id ~= InvalidResourceID and (not self.SqueezeX or not self.SqueezeY) then |
|
local image_width, image_height = ResourceManager.GetMetadataTextureSizeXY(self.image_id) |
|
image_width, image_height = ScaleXY(self.scale, ScaleXY(self.ImageScale, (image_width or 0) / self.Columns, (image_height or 0) / self.Rows)) |
|
if not self.SqueezeX then |
|
width = Max(image_width, width) |
|
end |
|
if not self.SqueezeY then |
|
height = Max(image_height, height) |
|
end |
|
end |
|
return width, height |
|
end |
|
|
|
local UIL = UIL |
|
local rgbWhite = RGB(255, 255, 255) |
|
function XFrame:DrawBackground() |
|
if self.image_id ~= InvalidResourceID then |
|
local color = self:CalcBackground() |
|
if GetAlpha(color) == 0 then return end |
|
local desaturation = UIL.GetDesaturation() |
|
UIL.SetDesaturation(self.Desaturation) |
|
UIL.SetColor(color) |
|
local scaleX, scaleY = ScaleXY(self.scale, self.ImageScale:xy()) |
|
UIL.DrawFrame(self.image_id, self.box, self.Rows, self.Columns, self:GetRow(), self:GetColumn(), |
|
self.FrameBox, not self.TileFrame, self.TransparentCenter, scaleX, scaleY, self.FlipX, self.FlipY) |
|
UIL.SetColor(rgbWhite) |
|
UIL.SetDesaturation(desaturation) |
|
else |
|
XControl.DrawBackground(self) |
|
end |
|
end |
|
|
|
|
|
|
|
|
|
local PushClipRect = UIL.PushClipRect |
|
local PopClipRect = UIL.PopClipRect |
|
|
|
DefineClass.XFrameProgress = { |
|
__parents = { "XFrame", "XProgress" }, |
|
properties = { |
|
{ category = "Image", id = "ProgressImage", name = "Progress frame image", editor = "ui_image", default = "", invalidate = true, }, |
|
{ category = "Image", id = "ProgressFrameBox", name = "Progress frame box", editor = "padding", default = box(0, 0, 0, 0), invalidate = true, }, |
|
{ category = "Image", id = "ProgressTileFrame", editor = "bool", default = false, invalidate = true, }, |
|
{ category = "Image", id = "SeparatorImage", name = "Separator Image", editor = "ui_image", default = "", invalidate = true, }, |
|
{ category = "Image", id = "SeparatorOffset", name = "Separator Offset", editor = "number", default = 0, invalidate = true, }, |
|
}, |
|
SqueezeY = false, |
|
separator_x = 0, |
|
separator_y = 0, |
|
TimeProgressInt = false, |
|
} |
|
|
|
function XFrameProgress:Init(parent, context) |
|
local progress = XFrame:new({ |
|
Id = "idProgress", |
|
HAlign = self.ProgressClip and "stretch" or "left", |
|
VAlign = "center", |
|
SqueezeY = false, |
|
DrawBackground = function(self) |
|
local clip = self.parent.ProgressClip and not self.TimeProgressInt |
|
if clip then |
|
local parent = self.parent |
|
local progress, max_progress = parent.Progress, Max(1, parent.MaxProgress) |
|
local min = ScaleXY(self.scale, parent.MinProgressSize) |
|
local min_x, min_y = self.content_box:minxyz() |
|
local width, height = self.content_box:sizexyz() |
|
if parent.Horizontal then |
|
local clip_width = (max_progress == 0) and min or min + (width - min) * progress / max_progress |
|
PushClipRect(min_x, min_y, min_x + clip_width, min_y + height, true) |
|
else |
|
local clip_height = (max_progress == 0) and min or min + (height - min) * progress / max_progress |
|
PushClipRect(min_x, min_y + height - clip_height, min_x + width, min_y + height, true) |
|
end |
|
end |
|
XFrame.DrawBackground(self) |
|
if clip then |
|
PopClipRect() |
|
end |
|
end, |
|
DrawContent = function(self) |
|
local parent = self.parent |
|
local image = parent.SeparatorImage |
|
if image ~= "" then |
|
local separator_x, separator_y = parent.separator_x, parent.separator_y |
|
local b = self.box |
|
local scale_x, scale_y = self.scale:xy() |
|
local offset = parent.SeparatorOffset * scale_x / 1000 |
|
local rect |
|
local progressRatio = MulDivRound(parent.Progress, 1000, parent.MaxProgress) |
|
if parent.Horizontal then |
|
local w = MulDivRound(b:sizex(), progressRatio, 1000) |
|
b = sizebox(b:minx(), b:miny(), w, b:sizey()) |
|
local right_spill = offset - ((parent.measure_width - self.measure_width) * scale_x / 1000) |
|
right_spill = Max(right_spill, 0) |
|
rect = box(Max(b:minx(), b:maxx() - separator_x - offset) + offset, b:miny(), Max(b:minx() + offset, b:maxx() - right_spill), b:maxy()) |
|
else |
|
local h = MulDivRound(b:sizey(), progressRatio, 1000) |
|
b = sizebox(b:minx(), b:miny(), b:sizex(), h) |
|
local up_spill = offset - (b:miny() * scale_y / 1000) |
|
up_spill = Max(up_spill, 0) |
|
rect = box(b:minx(), Min(b:maxy() - offset, b:miny() + up_spill), b:maxx(), Min(b:maxy(), b:miny() + separator_y + offset) - offset) |
|
end |
|
UIL.DrawImage(image, rect, box(0, 0, separator_x, separator_y)) |
|
end |
|
end, |
|
}, self, context) |
|
progress:SetImage(self.ProgressImage) |
|
progress:SetFrameBox(self.ProgressFrameBox) |
|
progress:SetTileFrame(self.ProgressTileFrame) |
|
end |
|
|
|
LinkPropertyToChild(XFrameProgress, "ProgressImage", "idProgress", "Image") |
|
LinkPropertyToChild(XFrameProgress, "ProgressFrameBox", "idProgress", "FrameBox") |
|
LinkPropertyToChild(XFrameProgress, "ProgressTileFrame", "idProgress", "TileFrame") |
|
|
|
function XFrameProgress:SetHorizontal(h) |
|
self.Horizontal = h |
|
local progress = self.idProgress |
|
if self.ProgressClip then |
|
progress:SetHAlign(h and "stretch" or "center") |
|
progress:SetVAlign(h and "center" or "stretch") |
|
else |
|
progress:SetHAlign(h and "left" or "center") |
|
progress:SetVAlign(h and "center" or "bottom") |
|
end |
|
progress:SetSqueezeY(not h) |
|
progress:SetSqueezeX(h) |
|
self:SetSqueezeY(not h) |
|
self:SetSqueezeX(h) |
|
self:InvalidateMeasure() |
|
end |
|
|
|
function XFrameProgress:SetSeparatorImage(image) |
|
image = image or false |
|
if self.SeparatorImage ~= image then |
|
self.SeparatorImage = image |
|
self.separator_x, self.separator_y = UIL.MeasureImage(image) |
|
self:Invalidate() |
|
end |
|
end |
|
|
|
function XFrameProgress:OnPropUpdate(context, prop_meta, value) |
|
if not self.TimeProgressInt then |
|
XProgress.OnPropUpdate(self, context, prop_meta, value) |
|
end |
|
end |
|
|
|
function XFrameProgress:SetTimeProgress(start_time, end_time, bGameTime) |
|
local prev = self.TimeProgressInt |
|
if prev and prev.start == start_time and prev.duration + prev.start == end_time and |
|
not bGameTime == not IsFlagSet(prev.flags or 0, const.intfGameTime) then |
|
|
|
return |
|
end |
|
self.idProgress:RemoveModifier(prev) |
|
self.TimeProgressInt = nil |
|
if start_time and end_time then |
|
self.TimeProgressInt = { |
|
id = "TimeProgressBar", |
|
type = const.intRect, |
|
OnLayoutComplete = IntRectTopLeftRelative, |
|
OnWindowMove = IntRectTopLeftRelative, |
|
targetRect = sizebox(0, 0, 0, 100), |
|
originalRect = sizebox(0, 0, 100, 100), |
|
duration = end_time - start_time, |
|
start = start_time, |
|
interpolate_clip = self.UseClipBox and const.interpolateClipOnly or true, |
|
flags = const.intfInverse + (bGameTime and const.intfGameTime or 0), |
|
} |
|
self.idProgress:AddInterpolation(self.TimeProgressInt) |
|
self:SetMaxProgress(100) |
|
self:SetProgress(100) |
|
end |
|
end |