DefineClass.ScreenshotDiffViewer = { __parents = { "GedApp" }, Translate = true, Title = "Screenshot Diff Viewer", AppId = "ScreenshotDiffViewer", InitialWidth = 1600, InitialHeight = 900, selected_image_paths = false, view_mode = "cycle", diff_scale = 2, } function ScreenshotDiffViewer:Init(parent, context) XAction:new({ ActionId = "TakeScreenshot", ActionToolbar = "main", ActionName = "Take Screenshot", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/new.tga", OnAction = function(action, host) host:Op("rfnCreateNewScreenshot", "root") end, }, self) XAction:new({ ActionId = "OpenFolder", ActionToolbar = "main", ActionName = "Open Folder", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/explorer.tga", OnAction = function(action, host) AsyncExec("explorer " .. ConvertToOSPath(g_ScreenshotViewerFolder)) end, }, self) XAction:new({ ActionId = "RefreshList", ActionToolbar = "main", ActionToolbarSplit = true, ActionName = "Refresh List", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/undo.tga", OnAction = function(action, host) host:Op("rfnReloadScreenshotItems", "root") end, }, self) XAction:new({ ActionId = "FitImage", ActionToolbar = "main", ActionName = "Fit Image", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/fit.tga", OnAction = function(action, host) host:SetImageFitScale(nil, true) end, }, self) XAction:new({ ActionId = "ShowOriginalSize", ActionToolbar = "main", ActionName = "Original Size", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/original.tga", OnAction = function(action, host) host:SetImageFitScale() end, }, self) XAction:new({ ActionId = "MagnifyImage", ActionToolbar = "main", ActionToolbarSplit = true, ActionName = "200%", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/x2.tga", OnAction = function(action, host) host:SetImageFitScale(point(2000, 2000)) end, }, self) XAction:new({ ActionId = "ToggleVStripComp", ActionToolbar = "main", ActionToolbarSplit = true, ActionName = "Toggle Vertical Strips Comparison", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/collection.tga", ActionToggle = true, ActionToggled = function (self, host) return host.view_mode == "vstrips" end, OnAction = function(action, host) if action:ActionToggled(host) then host:SetViewMode("cycle") else host:SetViewMode("vstrips") end end, }, self)--]] XAction:new({ ActionId = "ToggleCycleDiff", ActionToolbar = "main", ActionToolbarSplit = true, ActionName = "Toggle Screenshot Difference", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/view.tga", ActionToggle = true, ActionToggled = function (self, host) return host.view_mode == "diff" end, OnAction = function(action, host) if action:ActionToggled(host) then host:SetViewMode("cycle") else host:SetViewMode("diff") end end, }, self) XAction:new({ ActionId = "SetDiff2", ActionToolbar = "main", ActionName = "2x Difference Scale", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/2x.tga", ActionToggle = true, ActionToggled = function (self, host) return host.diff_scale == 2 end, OnAction = function(action, host) host:SetDiffScale(2) end, }, self) XAction:new({ ActionId = "SetDiff2", ActionToolbar = "main", ActionName = "4x Difference Scale", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/4x.tga", ActionToggle = true, ActionToggled = function (self, host) return host.diff_scale == 4 end, OnAction = function(action, host) host:SetDiffScale(4) end, }, self) XAction:new({ ActionId = "SetDiff2", ActionToolbar = "main", ActionName = "16x Difference Scale", ActionTranslate = false, ActionIcon = "CommonAssets/UI/Ged/16x.tga", ActionToggle = true, ActionToggled = function (self, host) return host.diff_scale == 16 end, OnAction = function(action, host) host:SetDiffScale(16) end, }, self) self.LayoutHSpacing = 0 GedListPanel:new({ Id = "idScreenshots", Title = "Screenshots", TitleFormatFunc = "GedFormatPresets", Format = "", SelectionBind = "SelectedObject,SelectedPreset", MultipleSelection = true, SearchHistory = 20, PersistentSearch = true, }, self, "root") XPanelSizer:new({ }, self) local win = XWindow:new({ }, self) XImage:new({ Id = "idImageFit", ImageFit = "smallest", FoldWhenHidden = true, }, win) local container = XWindow:new({ Id = "idScrollContainer", FoldWhenHidden = true, }, win) container:SetVisible(false) local area = XScrollArea:new({ Id = "idScrollArea", IdNode = false, HScroll = "idHScroll", VScroll = "idScroll", }, container) XImage:new({ Id = "idImage", ImageFit = "none", }, area) XSleekScroll:new({ Id = "idHScroll", Target = "idScrollArea", Dock = "bottom", Margins = box(0, 2, 7, 0), Horizontal = true, AutoHide = true, FoldWhenHidden = true, }, container) XSleekScroll:new({ Id = "idScroll", Target = "idScrollArea", Dock = "right", Margins = box(2, 0, 0, 0), Horizontal = false, AutoHide = true, FoldWhenHidden = true, }, container) end function ScreenshotDiffViewer:SetViewMode(mode) self.view_mode = mode self:UpdateShownImages() end function ScreenshotDiffViewer:SetDiffScale(scale) self.diff_scale = scale self:UpdateShownImages() end function ScreenshotDiffViewer:UpdateShownImages() self:DeleteThread("cycle_thread") local images = self.selected_image_paths if #(images or "") > 1 then if self.view_mode == "cycle" then self:CreateThread("cycle_thread", function(self) local idx = 1 local count = #images while true do self:SetImage(images[idx]) Sleep(500) idx = idx % count + 1 end end, self) elseif self.view_mode == "diff" then self:ShowDiffImage() elseif self.view_mode == "vstrips" then self:ShowVStripsComparison() end elseif #(images or "") > 0 then self:SetImage(images[1]) end end function ScreenshotDiffViewer:ShowVStripsComparison() local images = self.selected_image_paths local hash = "" for i, img in ipairs(images) do hash = hash..xxhash(img) end local result_path = string.format("%s%d%s.png", g_ScreenshotViewerCacheFolder, #images, hash) if not io.exists(result_path) then AsyncCreatePath(g_ScreenshotViewerCacheFolder) CreateRealTimeThread(function() local err = self.connection:Call("rfnOp", self:GetState(), "rfnCompareScreenshotItemsVstrips", "root", images, result_path) if not err and io.exists(result_path) then self:SetImage(result_path) end end, self, images, result_path) return end self:SetImage(result_path) end function ScreenshotDiffViewer:ShowDiffImage() local images = self.selected_image_paths local diff_path = string.format("%s%d_%d_%d.png", g_ScreenshotViewerCacheFolder, xxhash(images[1]), xxhash(images[2]), self.diff_scale) if not io.exists(diff_path) then AsyncCreatePath(g_ScreenshotViewerCacheFolder) CreateRealTimeThread(function() local err = self.connection:Call("rfnOp", self:GetState(), "rfnCompareScreenshotItemsDiff", "root", images[1], images[2], diff_path, self.diff_scale) if not err and io.exists(diff_path) then self:SetImage(diff_path) end end, self, images, diff_path) return end self:SetImage(diff_path) end function ScreenshotDiffViewer:SetImage(image) self.idImage:SetImage(image) self.idImageFit:SetImage(image) end function ScreenshotDiffViewer:SetImageFitScale(scale, fit) scale = scale or point(1000, 1000) self.idImage:SetScaleModifier(scale) self.idScrollContainer:SetVisible(not fit) self.idImageFit:SetVisible(fit) end function ScreenshotDiffViewer:rfnSetSelectedFilePath(file_path, selected) self.selected_image_paths = self.selected_image_paths or {} local t = self.selected_image_paths if selected then table.insert_unique(t, file_path) else table.remove_value(t, file_path) end table.sort(t) self:UpdateShownImages() end