Hi. I know you are happy with what you have now, but in case you ever get curious I am posting my latest version. Just ignore if not interested. In addition to cleaning up the code and adding lots off comments, I've added some enhancements.
1. The cursor now disappears after a specified time.
2. You can toggle between random and sequential display modes by double clicking the middle mouse button.
3. You can toggle auto cycle on and off by double clicking the left mouse button.
4. You can toggle between cycling on a track change and auto cycle on with shift-left mouse button.
window.DefinePanel("LoadImageAsyncV2", { author: "TheQwertiest" });
include(`${fb.ComponentPath}docs\\Flags.js`);
include(`${fb.ComponentPath}docs\\Helpers.js`);
// INITIALIZATION
// Cycle mode (cyc = 0 turns autocycle off, cyc = 1 turns autocycle on, cyc = 2 cycles on track change)
// Display mode (mode = 0 is sequential, mode = 1 is random)
// cyctm is the image auto cycle time in milliseconds
/*
nn = -1 is the start pos for sequential mode (nn is the index used to access the image list array loaded by utils.Glob)
Sequential mode processes image files in the sequence in which they are loaded into the image list array
This is not neccessarily the file name sequence from the folder, although it usually appears to be close
*/
//
let ww = 0, wh = 0, nn = -1, cyc = 1, mode = 0, cyctm = 10000; // Switches
let g_img = null; // Initialize image
let hideCursorTimer; // Timer for hiding cursor
let g_leave = 0; // Switch to prevent cursor hiding after leaving panel
var col = {}; // Colors
font = gdi.Font('Segoe Ui Black', 28, 0); // Font for displayed text (may need to change font size for non-4K display
// Get an image list of jpg files from a folder and load into an array
const g_image_list = utils.Glob('c:\\wallpaper\\*.jpg');
// Trigger image auto cycle every 10 seconds
let g_timer = window.SetInterval(function () {
if (fb.IsPlaying && !fb.IsPaused && cyc == 1)
if (mode == 0)
load_seq_image_async_a();
else
load_random_image_async();
}, cyctm);
// Trigger image cycle on track change
function on_playback_new_track() {
if (cyc == 2) {
if (mode == 0)
load_seq_image_async_a();
else
load_random_image_async();
}
}
function on_mouse_leave() {
g_leave = 1;
}
// Hide cursur after 2 seconds
function on_mouse_move(x, y, m) {
if (x >= 0 && x < ww && y >= 0 && y < wh)
g_leave = 0;
window.SetCursor(32512); // arrow
clearTimeout(hideCursorTimer);
hideCursorTimer = setTimeout(() => {
if (g_leave == 0)
window.SetCursor(-1); // hide cursor
}, 2000);
}
// Load a sequential image from the image list on autocycle
const load_seq_image_async_a = async (metadb, art_id) =>
{
nn = nn + 1
let path = g_image_list[nn];
g_img = await gdi.LoadImageAsyncV2(window.ID, path);
if (!g_img) {
nn = 0;
let path = g_image_list[nn];
g_img = await gdi.LoadImageAsyncV2(window.ID, path);
}
window.Repaint();
};
// Load a sequential image from the image list on mouse wheel
const load_seq_image_async_m = async (metadb, art_id) =>
{
let path = g_image_list[nn];
g_img = await gdi.LoadImageAsyncV2(window.ID, path);
window.Repaint();
};
// Load a random image from the image list
const load_random_image_async = async (metadb, art_id) =>
{
let path = g_image_list[Math.floor(Math.random() * g_image_list.length)];
g_img = await gdi.LoadImageAsyncV2(window.ID, path);
window.Repaint();
};
// Initial image load
if (mode == 0)
load_seq_image_async_a();
else
load_random_image_async();
// Initialize window dimensions
function on_size() {
ww = window.Width;
wh = window.Height;
}
// Display previous/next image with mouse wheel
function on_mouse_wheel(delta) {
if (mode == 0) {
if (delta > 0) {
nn = nn - 1;
//if (nn == -1) {nn = 0};
if (nn == -1)
nn = g_image_list.length - 1;
load_seq_image_async_m();
}
else {
nn = nn + 1;
if (nn == g_image_list.length)
nn = 0;
load_seq_image_async_m();
}
}
else
load_random_image_async();
}
// Toggle auto cycle with left mouse button double click (0 = autocycle off, 1 = autocycle on)
function on_mouse_lbtn_dblclk(x, y) {
if (cyc == 1)
cyc = 0;
else
cyc = 1;
window.Repaint();
}
// Toggle between track cycle and auto cycle with shift-left mouse button up (1 = autocycle on, 2 = treck cycle)
function on_mouse_lbtn_up(x, y) {
if (utils.IsKeyPressed(VK_SHIFT)) {
if (cyc == 2)
cyc = 1;
else
cyc = 2;
window.Repaint();}
//else if (utils.IsKeyPressed(VK_CONTROL)) {
// fieldname = utils.InputBox(window.ID, "prompt", "caption", "");
// window.Repaint();
//}
}
// Toggle display mode with middle mouse button double click (0 = sequential, 1 = random)
function on_mouse_mbtn_dblclk(x, y) {
if (mode == 0)
mode = 1;
else
mode = 0;
if (mode == 0)
load_seq_image_async_m();
else
load_random_image_async();
}
// Repaint window
function on_paint(gr) {
if (!g_img) { // reset image list index and return if no image
nn = 0;
return 1;
}
let scale_w = ww / g_img.Width;
let scale_h = wh / g_img.Height;
let scale = Math.min(scale_w, scale_h);
let pos_x = 0, pos_y = 0;
if (scale_w < scale_h) {
pos_y = (wh - g_img.Height * scale) / 2;
}
else if (scale_w > scale_h) {
pos_x = (ww - g_img.Width * scale) / 2;
}
// May need to change DrawString positions for non-4K display (x-horizontal, y-vertical, w-width, h-heigth)
col.bg = RGB(0, 0, 0); // Black background
gr.FillSolidRect(0, 1, ww, wh, col.bg);
gr.DrawImage(g_img, pos_x, pos_y, g_img.Width * scale, g_img.Height * scale, 0, 0, g_img.Width, g_img.Height);
if (mode == 0) // Sequential mode
gr.DrawString((nn + 1) + ' of ' + g_image_list.length, font, RGB(0,255,255), 15, 10, 200, 25, 0);
else // Random mode
gr.DrawString('Random', font, RGB(0,255,255), 15, 10, 200, 25, 0);
if (cyc == 0) {
gr.DrawString('Auto Cycle Off', font, RGB(0,255,255), 15, 35, 250, 25, 0);}
else if (cyc == 1) {
gr.DrawString('Auto Cycle On', font, RGB(0,255,255), 15, 35, 250, 25, 0);}
else if (cyc == 2) {
gr.DrawString('Track Cycle On', font, RGB(0,255,255), 15, 35, 250, 25, 0);}
}