From bd46a81a386712e854ff5c3cb9b0efc48b2dea23 Mon Sep 17 00:00:00 2001 From: Valeria Fadeeva Date: Thu, 6 Aug 2026 22:18:38 +0500 Subject: [PATCH] Update --- LICENSE | 5 +- dev/d0.sh | 11 +- dev/d1.sh | 59 +- dev/install.sh | 4 +- dev/make.sh | 25 +- dev/script.js | 709 ----------------------- dev/test_quick.sh | 56 ++ melawy-nier-a2/MAIN_LOGO.png | Bin 7271 -> 26251 bytes melawy-nier-a2/MAIN_LOGO_.png | Bin 0 -> 7271 bytes melawy-nier-a2/Melawy_Linux_640x320.png | Bin 14463 -> 0 bytes melawy-nier-a2/script.script | 724 ++++++++++++++---------- 11 files changed, 552 insertions(+), 1041 deletions(-) delete mode 100644 dev/script.js create mode 100755 dev/test_quick.sh create mode 100644 melawy-nier-a2/MAIN_LOGO_.png delete mode 100644 melawy-nier-a2/Melawy_Linux_640x320.png diff --git a/LICENSE b/LICENSE index 0ad25db..81dddc7 100644 --- a/LICENSE +++ b/LICENSE @@ -629,8 +629,9 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - - Copyright (C) + melawy-plymouth-theme-nier-a2 (nier-a2): Plymouth boot splash + theme for Melawy OS. + Copyright (C) 2026 Valeria Fadeeva This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published diff --git a/dev/d0.sh b/dev/d0.sh index 507c408..bce16c3 100755 --- a/dev/d0.sh +++ b/dev/d0.sh @@ -1,5 +1,14 @@ #!/bin/bash -./install.sh +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." + +echo "=== Installing theme ===" +bash install.sh + +echo "" +echo "=== Starting Plymouth daemon (debug mode) ===" +echo "Press Ctrl+C to stop" sudo plymouthd --debug --no-daemon --tty=/dev/tty7 diff --git a/dev/d1.sh b/dev/d1.sh index 87bf8cd..db19d3f 100755 --- a/dev/d1.sh +++ b/dev/d1.sh @@ -1,43 +1,62 @@ #!/bin/bash +set -e + +echo "=== Plymouth Theme Test Script ===" + +# --- Запуск --- +echo "[1] Showing splash..." sudo plymouth --show-splash + +echo "[2] Setting boot mode..." sudo plymouth change-mode --boot-up + +echo "[3] Setting normal status..." sudo plymouth update --status="normal" +# --- Тест паузы прогресса --- +echo "[4] Testing progress pause/resume..." sudo plymouth pause-progress sudo plymouth message --text="pausing boot - press 'c' or space bar to continue" sleep 2 -# sudo plymouth watch-keystroke --keys="cC " --command="tee /tmp/c_key_pressed" sudo plymouth message --text="resuming boot" sudo plymouth unpause-progress -#sudo plymouth ask-question --prompt "what is your name? " | /usr/bin/tee -sudo plymouth ask-for-password --prompt "specify password: /dev/sda8: LABEL=\"Data\" UUID=\"2fd2a700-319b-41f2-853f-c57667d4081d\" UUID_SUB=\"62109da7-2b4b-4c2d-b590-1c0436c7c3a4\" PARTUUID=\"c05c942b-bd7e-487a-87a0-592df3334ff5\"" | /usr/bin/tee +# --- Тест запроса пароля --- +echo "[5] Testing password prompt..." +sudo plymouth ask-for-password \ + --prompt "specify password: /dev/sda8: LABEL=\"Data\" UUID=\"2fd2a700-319b-41f2-853f-c57667d4081d\" UUID_SUB=\"62109da7-2b4b-4c2d-b590-1c0436c7c3a4\" PARTUUID=\"c05c942b-bd7e-487a-87a0-592df3334ff5\"" \ + | /usr/bin/tee || true -#sudo plymouth message --text="Hello" +sleep 1 -sudo plymouth --update=fsck:sda1:0 -sudo plymouth --update=fsck:sda1:1 -sudo plymouth --update=fsck:sda1:2 -sudo plymouth --update=fsck:sda1:3 -sudo plymouth --update=fsck:sda1:4 -sudo plymouth --update=fsck:sda1:5 -sudo plymouth --update=fsck:sda1:6 -sudo plymouth --update=fsck:sda1:7 -sudo plymouth --update=fsck:sda1:8 -sudo plymouth --update=fsck:sda1:9 -sudo plymouth --update=fsck:sda1:10 -sudo plymouth --update=fsck:sda1:11 -sudo plymouth --update=fsck:sda1:12 -sudo plymouth --update=fsck:sda1:27 -sudo plymouth --update=fsck:sda1:54 -sudo plymouth --update=fsck:sda1:100 +sudo plymouth ask-for-password \ + --prompt "specify password: /dev/sda8: LABEL=\"Data\" UUID=\"c57667d4081d-319b-41f2-853f-2fd2a700\" UUID_SUB=\"1c0436c7c3a4-2b4b-4c2d-b590-62109da7\" PARTUUID=\"592df3334ff5-bd7e-487a-87a0-c05c942b\"" \ + | /usr/bin/tee || true +# Возвращаемся к нормальному режиму после пароля +sudo plymouth update --status="normal" + +# --- Тест FSCK прогресса --- +echo "[6] Testing fsck progress (0→100%)..." +for pct in 0 1 2 3 4 5 6 7 8 9 10 11 12 27 54 100; do + sudo plymouth --update="fsck:sda1:$pct" +done + +# --- Тест скроллящегося лога --- END=50 +echo "[7] Testing scroll log ($END lines)..." for i in $(seq 1 $END); do sudo plymouth --update="$i длинная_строка_предлинная_строка_прямо_вот_такая" sudo plymouth --update="$i long_str_long_strlong_str_long_strlong_str_long_str" done +# --- Ожидание и завершение --- +echo "[8] Waiting 5 seconds before quit..." sleep 5 + +echo "[9] Quitting Plymouth..." sudo plymouth --quit + +echo "" +echo "=== Test complete ===" diff --git a/dev/install.sh b/dev/install.sh index a1e9ff4..99de090 100755 --- a/dev/install.sh +++ b/dev/install.sh @@ -11,9 +11,9 @@ fi ./make.sh -sudo rm -rf /usr/share/plymouth/themes/$THEME_NAME +sudo rm -vrf /usr/share/plymouth/themes/$THEME_NAME sudo mkdir -p /usr/share/plymouth/themes/$THEME_NAME -sudo cp -r ../$THEME_NAME /usr/share/plymouth/themes/ +sudo cp -vr ../$THEME_NAME /usr/share/plymouth/themes/ ls -plash /usr/share/plymouth/themes/$THEME_NAME diff --git a/dev/make.sh b/dev/make.sh index d4259c7..0ca0c89 100755 --- a/dev/make.sh +++ b/dev/make.sh @@ -2,18 +2,25 @@ THEME_NAME="melawy-nier-a2" -if [[ -n "$THEME_NAME" ]]; then - echo "Non empty" -else +if [[ -z "$THEME_NAME" ]]; then echo "Theme name is empty. Exit" - exit + exit 1 fi -cp -f script.js ../$THEME_NAME/script.script -sed -i 's/function/fun/g' ../$THEME_NAME/script.script +SRC="../$THEME_NAME/script.script" +DST="$SRC" -if [[ "$?" == 0 ]]; then - echo "Make successed" +if [[ ! -f "$SRC" ]]; then + echo "Theme script $SRC not found. Exit" + exit 1 +fi + +# Проверяем наличие script.script в теме (без конвертации из JS) +cp -f "$SRC" "$DST" + +if [[ $? -eq 0 ]]; then + echo "Make succeeded: $DST updated from $SRC" else - echo "Make failed?" + echo "Make failed!" + exit 1 fi diff --git a/dev/script.js b/dev/script.js deleted file mode 100644 index a7a1900..0000000 --- a/dev/script.js +++ /dev/null @@ -1,709 +0,0 @@ -/* -Theme Name: Melawy -Version: 1.0 -Description: My theme -Author: Valeria Fadeeva - https://github.com/Valeria-Fadeeva -Date: 2023.04.04 -License: GNU AFFERO GENERAL PUBLIC LICENSE, see -*/ - -Window.GetMaxWidth = function() { - i = 0; - width = 0; - while (Window.GetWidth(i)){ - width = Math.Max(width, Window.GetWidth(i)); - i++; - } - return width; -}; - -Window.GetMaxHeight = function() { - i = 0; - height = 0; - while (Window.GetHeight(i)){ - height = Math.Max(height, Window.GetHeight(i)); - i++; - } - return height; -}; - -Percent = function(perc, pixels) { - result = Math.Int(Math.Abs(Math.Int(pixels)) / 100 * Math.Abs(Math.Int(perc))); - return result; -}; - -Limit = function(width, height, perc) { - local.this; - this.width = width; - this.height = height; - this.perc = perc; - - this.GetWidth = function() { - width = Percent(this.perc, this.width); - return width; - }; - - this.GetHeight = function() { - height = Percent(this.perc, this.height); - return height; - }; - - return this; -}; - -ScaleImage = function(image1, image2) { - img1.width = image1.GetWidth(); - img1.height = image1.GetHeight(); - img1.ratio = img1.width / img1.height; - - img2.width = image2.GetWidth(); - img2.height = image2.GetHeight(); - img2.ratio = img2.width / img2.height; - - if (img1.ratio == 1 || (img1.width < 200 && img1.height < 200)) { - img1.scaled = image1.Scale(img2.width, img2.height); - return img1.scaled; - } - - if (img1.width == img2.width && img1.height == img2.height) { - return image1; - } - - if (img2.ratio < img1.ratio) { - factor = img2.height / img1.height; - } else { - factor = img2.width / img1.width; - } - - img1.scaled = image1.Scale(img1.width * factor, img1.height * factor); - - return img1.scaled; -}; - -FitIntoDimensions = function(image1, image2) { - img1.width = image1.GetWidth(); - img1.height = image1.GetHeight(); - - img2.width = image2.GetWidth(); - img2.height = image2.GetHeight(); - - ma = Math.Max(img1.width, img2.height); - mi = Math.Min(img1.height, img2.height); - factor = ma / mi; - - img1.fit = image1.Scale(Math.Int(img1.width / factor), Math.Int(img1.height / factor)); - -}; - -SetSpriteImage = function(asset, x, y, z) { - local.sprite = Sprite(); - sprite.image = Image(asset); - sprite.width = sprite.image.GetWidth(); - sprite.height = sprite.image.GetHeight(); - sprite.SetImage(sprite.image); - sprite.SetPosition(x, y, z); - return sprite; -}; - -Blur = function(background_src, foreground_src, x, y, z, width, height, scale_width, scale_height) { - index = 0; - local.image[index]; - - image[index].image = Image(background_src); - image[index].image = ScaleImage(image[index].image, Limit(scale_width, scale_height, 100)); - image[index].image = image[index].image.Crop(x, y, width, height); - image[index].image = ScaleImage(image[index].image, Limit(Percent(120, width), Percent(120, height), 100)); - image[index].image = image[index].image.Crop(x, y, width, height); - - image[index].sprite0 = Sprite(image[index].image); - image[index].sprite1 = Sprite(image[index].image); - image[index].sprite2 = Sprite(image[index].image); - image[index].sprite3 = Sprite(image[index].image); - image[index].sprite4 = Sprite(image[index].image); - - image[index].sprite0.SetOpacity(0.25); - image[index].sprite1.SetOpacity(0.25); - image[index].sprite2.SetOpacity(0.25); - image[index].sprite3.SetOpacity(0.25); - image[index].sprite4.SetOpacity(0.25); - - image[index].sprite0.SetPosition(x, y, z); - image[index].sprite1.SetPosition(x++, y, z++); - image[index].sprite2.SetPosition(x, y++, z++); - image[index].sprite3.SetPosition(x--, y, z++); - image[index].sprite5.SetPosition(x, y--, z++); - - index = 1; - image[index].image = Image(foreground_src); - image[index].image = image[index].image.Scale(width, height); - image[index].sprite = Sprite(image[index].image); - image[index].sprite.SetOpacity(0.75); - image[index].sprite.SetPosition(x, y, z++); - - return local.image; -}; - - -// TEXT -common_font = "Noto Sans Mono Regular 10"; -progress_font = "Noto Sans Mono Regular 12"; -link_font = "Noto Sans Italic 16"; - -common_symbol.image = Image.Text("M", 0.5, 0.5, 0.5, 1, common_font); -common_symbol.height = common_symbol.image.GetHeight(); // высота символа -common_symbol.width = common_symbol.image.GetWidth(); // ширина символа - -progress_symbol.image = Image.Text("M", 0.5, 0.5, 0.5, 1, progress_font); -progress_symbol.height = progress_symbol.image.GetHeight(); // высота символа -progress_symbol.width = progress_symbol.image.GetWidth(); // ширина символа - -link_symbol.image = Image.Text("M", 0.5, 0.5, 0.5, 1, link_font); -link_symbol.height = link_symbol.image.GetHeight(); // высота символа -link_symbol.width = link_symbol.image.GetWidth(); // ширина символа - -starting_text = "Starting up..."; -bye_text = "System is shutting down"; -progress_t= 0; - -// x0 = Window.GetX(); -// y0 = Window.GetY(); -// z0 = Window.GetZ(); - -x0 = 0; -y0 = 0; -z0 = 0; - -Window.SetBackgroundTopColor(0, 0, 0); -Window.SetBackgroundBottomColor(0, 0, 0); - -screen.width = Window.GetMaxWidth(); -screen.height = Window.GetMaxHeight(); - -// BACKGROUND -background.image = Image("BACKGROUND.png"); -background.image = ScaleImage(background.image, Limit(screen.width, screen.height, 100)); - -background.width = background.image.GetWidth(); -background.height = background.image.GetHeight(); - -background.x = x0 + screen.width / 2 - background.width / 2; -background.y = y0 + screen.height / 2 - background.height / 2; - -//background.x = x0; -//background.y = y0; - -background.sprite = SpriteNew(); -background.sprite.SetImage(background.image); -background.sprite.SetOpacity(1); -background.sprite.SetPosition(background.x, background.y, 0); - -// SIDE BACKGROUND -side_panel.background_src = "BACKGROUND.png"; -side_panel.foreground_src = "SIDE_BACKGROUND2.png"; -side_panel.x = x0; -side_panel.y = y0; -side_panel.z = 1; -side_panel.width = Percent(33.33, screen.width); -side_panel.height = Percent(100, screen.height); - -blur = Blur(side_panel.background_src, side_panel.foreground_src, side_panel.x, side_panel.y, side_panel.z, side_panel.width, side_panel.height, screen.width, screen.height); - -// MESSAGES BOX -messages_box.image = Image("MESSAGES_BOX.png"); -messages_box.image = messages_box.image.Scale(Percent(80, side_panel.width), Percent(40, side_panel.height)); - -messages_box.width = messages_box.image.GetWidth(); -messages_box.height = messages_box.image.GetHeight(); - -messages_box.x = Percent(50, side_panel.width) - messages_box.width / 2; -messages_box.y = Percent(45, side_panel.height) - messages_box.height; - -messages_box.sprite = Sprite(messages_box.image); -messages_box.sprite.SetOpacity(1); -messages_box.sprite.SetPosition(messages_box.x, messages_box.y, 12); - -// Sise Logo -side_logo.image = Image("Melawy_Linux_640x320.png"); -side_logo.image = ScaleImage(side_logo.image, Limit(screen.width, screen.height, 20)); - -side_logo.width = side_logo.image.GetWidth(); -side_logo.height = side_logo.image.GetHeight(); - -side_logo.x = (side_panel.width - side_logo.width) / 2; -side_logo.y = side_panel.height - side_panel.height * 0.25; - -side_logo.sprite = Sprite(side_logo.image); -side_logo.sprite.SetOpacity(1); -side_logo.sprite.SetPosition(side_logo.x, side_logo.y, 12); - -// **************************************** // - -project_link.image = Image.Text("https://Melawy.ru", 0.5, 0.5, 0.5, 1, link_font); - -project_link.width = project_link.image.GetWidth(); -project_link.height = project_link.image.GetHeight(); - -project_link.sprite = Sprite(project_link.image); -project_link.x = (side_panel.width - project_link.width) / 2; -project_link.y = side_logo.y + side_logo.height; - -project_link.sprite.SetOpacity(1); -project_link.sprite.SetPosition(project_link.x, project_link.y, 12); - -// **************************************** // - -// LOGO -logo.image = Image("MAIN_LOGO.png"); -logo.image = FitIntoDimensions(logo.image, Limit(screen.width, screen.height, 35)); - -logo.sprite = Sprite(logo.image); -logo.x = screen.width / 2 - logo.image.GetWidth() / 2; // позиция логотипа X -logo.y = Percent(10, screen.height); // позиция логотипа Y -logo.sprite.SetOpacity(1); -logo.sprite.SetPosition(logo.x, logo.y, 12); - -// PROGRESS FORM -progress_form.image = Image("PROGRESS_FORM.png"); -progress_form.image = progress_form.image.Scale(Percent(80, side_panel.width), Percent(10, side_panel.height)); - -progress_form.width = progress_form.image.GetWidth(); -progress_form.height = progress_form.image.GetHeight(); - -progress_form.x = Percent(50, side_panel.width) - progress_form.width / 2; -progress_form.y = Percent(75, side_panel.height) - progress_form.height; - -progress_form.sprite = Sprite(progress_form.image); -progress_form.sprite.SetOpacity(1); -progress_form.sprite.SetPosition(progress_form.x, progress_form.y, 12); - -// SPINNER -spinner.image = Image("SPINNER.png"); -spinner.image = spinner.image.Scale(Percent(1, screen.width), Percent(1, screen.width)); - -spinner.width = spinner.image.GetWidth(); -spinner.height = spinner.image.GetHeight(); - -spinner.x = progress_form.x + progress_form.width - Percent(10, progress_form.width); -spinner.y = progress_form.y + Percent(10, progress_form.height); - -spinner.sprite = Sprite(spinner.image); -spinner.sprite.SetPosition(spinner.x, spinner.y, 13); // позиция за или перед - - -// PROGRESS TEXT -progress_text.image = Image.Text(progress_t + "%", 0.5, 0.5, 0.5, 1, progress_font); - -progress_text.width = progress_text.image.GetWidth(); -progress_text.height = progress_text.image.GetHeight(); - -progress_text.x = progress_form.x + Percent(5, progress_form.width); // позиция % по X -progress_text.y = progress_form.y + Percent(10, progress_form.height); // позиция % по Y - -progress_text.sprite = SpriteNew(); -progress_text.sprite.SetPosition(progress_text.x, progress_text.y, 13); - -// PROGRESS BOX -progress_box.image = Image("PROGRESS_BOX.png"); -progress_box.image = progress_box.image.Scale(Percent(90, progress_form.width), Percent(15, progress_form.height)); - -progress_box.width = progress_box.image.GetWidth(); -progress_box.height = progress_box.image.GetHeight(); - -progress_box.x = progress_form.x + (progress_form.width - progress_box.width) / 2; -progress_box.y = progress_form.y + (progress_form.height - progress_box.height) / 2; - -progress_box.sprite = Sprite(progress_box.image); -progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 13); - -// PROGRESS BAR -progress_bar.original_image = Image("PROGRESS_BAR.png"); -progress_bar.original_image = progress_bar.original_image.Scale(Percent(90, progress_form.width), Percent(15, progress_form.height)); - -progress_bar.width = progress_bar.original_image.GetWidth(); -progress_bar.height = progress_bar.original_image.GetHeight(); - -progress_bar.x = progress_form.x + (progress_form.width - progress_bar.original_image.GetWidth()) / 2; -progress_bar.y = progress_form.y + (progress_form.height - progress_bar.original_image.GetHeight()) / 2; - -progress_bar.sprite = Sprite(); -progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 14); - -// PROGRESS FADE -progress_fade.image = Image("PROGRESS_FADE.png"); -progress_fade.image = progress_fade.image.Scale(Percent(10, progress_form.width), Percent(15, progress_form.height)); - -progress_fade.width = progress_fade.image.GetWidth(); -progress_fade.height = progress_fade.image.GetHeight(); - -progress_fade.sprite = Sprite(progress_fade.image); - -fade_dir = 0; // 0 = right, 1 = left -counter = 0; -max_counter = progress_box.width - progress_fade.width; - - -function progress_callback(duration, progress) { - if (progress_bar.image.GetWidth() != Math.Int(progress_bar.original_image.GetWidth() * progress)) { - progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress, progress_bar.original_image.GetHeight()); - progress_bar.sprite.SetImage(progress_bar.image); - - f = Math.Int(progress_bar.image.GetWidth() /progress_bar.original_image.GetWidth() * 100); - progress_t.image = Image.Text(f + "%", 0.5, 0.5, 0.5, 1, progress_font); - progress_text.sprite.SetImage(progress_t.image); - } -} - -Plymouth.SetBootProgressFunction(progress_callback); - - -// DIALOG -status = "normal"; -//count = 0; - - -function dialog_setup() { - local.box_form; - local.lock; - local.entry; - local.hint; - local.bullet_i; - - box_form.image = Image("BOX.png"); - box_form.image = box_form.image.Scale(Percent(80, side_panel.width), Percent(18, side_panel.height)); - - box_form.width = box_form.image.GetWidth(); - box_form.height = box_form.image.GetHeight(); - - box_form.x = progress_form.x; - box_form.y = progress_form.y - box_form.height - Percent(1, side_panel.height); - box_form.z = 10000; - - box_form.sprite = Sprite(box_form.image); - box_form.sprite.SetOpacity(1); - box_form.sprite.SetPosition(box_form.x, box_form.y, box_form.z); - - - entry.image = Image("ENTRY.png"); - entry.image = entry.image.Scale(Percent(90, box_form.width), Percent(20, box_form.height)); - entry.width = entry.image.GetWidth(); - entry.height = entry.image.GetHeight(); - - entry.x = box_form.x + box_form.width/2 - entry.width/2; - entry.y = box_form.y + (box_form.height/3 * 2) - entry.height/2; - entry.z = box_form.z + 1; - - entry.sprite = Sprite(entry.image); - entry.sprite.SetPosition(entry.x, entry.y, entry.z); - - - lock.image = Image("LOCK.png"); - lock.image = lock.image.Scale(Percent(95, entry.height), Percent(95, entry.height)); - lock.width = lock.image.GetWidth(); - lock.height = lock.image.GetHeight(); - - lock.x = entry.x + entry.width - lock.width - (entry.height - lock.height); - lock.y = entry.y + entry.height/2 - lock.height/2; - lock.z = box_form.z + 2; - - lock.sprite = Sprite(lock.image); - lock.sprite.SetPosition(lock.x, lock.y, lock.z); - - - hint.sprite = SpriteNew(); - hint.sprite.SetPosition(entry.x, box_form.y + Percent(5, box_form.height), box_form.z + 1); - - - bullet_i.image = Image("BULLET.png"); - bullet_i.image = bullet_i.image.Scale(Percent(50, entry.height), Percent(50, entry.height)); - bullet_i.width = bullet_i.image.GetWidth(); - bullet_i.height = bullet_i.image.GetHeight(); - - - global.dialog.box_form = box_form; - global.dialog.lock = lock; - global.dialog.entry = entry; - global.dialog.hint = hint; - global.dialog.bullet_i = bullet_i; - dialog_opacity(1); -} - - -function dialog_opacity(opacity) { - if (opacity == 0) { - dialog.box_form.sprite.SetOpacity(opacity); - dialog.lock.sprite.SetOpacity(opacity); - dialog.entry.sprite.SetOpacity(opacity); - } - else { - dialog.lock.sprite.SetOpacity(opacity); - dialog.entry.sprite.SetOpacity(opacity); - } - - dialog.hint.sprite.SetOpacity(opacity); - - for (index = 0; dialog.bullet[index]; index++) { - dialog.bullet[index].sprite.SetOpacity(opacity); - } -} - - -function display_normal_callback() { - global.status = "normal"; - - if (global.dialog) - dialog_opacity(0); -} - -Plymouth.SetDisplayNormalFunction(display_normal_callback); - - -function display_password_callback(prompt_text, bullets) { - global.status = "password"; - - if (!global.dialog) - dialog_setup(); - else - dialog_opacity(1); - - padding_top_bottom = Percent(10, dialog.box_form.height); // отступы сверху и снизу - padding_left_right = Percent(5, dialog.box_form.width); // отступы слева и справа - - LINE_WIDTH = 100; - - for (index = LINE_WIDTH; index > 0; index--) { - if ((LINE_WIDTH * common_symbol.width) > (dialog.box_form.width - (padding_left_right * 2))) { - LINE_WIDTH = LINE_WIDTH - 1; - } - else { - break; - } - } - - str_len = StringLength(prompt_text); - - for (i = 1; LINE_WIDTH * i <= str_len; i++) { - line_count = i; - } - - if (str_len > LINE_WIDTH) { - if (str_len % LINE_WIDTH > 0) { - line_count = line_count + 1; - } - } - - i = 1; - start = 0; - end = LINE_WIDTH; - - text = ""; - - for (i = 1; i <= line_count; i++) { - text += prompt_text.SubString(start, end); - text += "\n"; - - start = end; - if (LINE_WIDTH * i < str_len) { - end = end + LINE_WIDTH; - } - else { - end = str_len - 1; - } - } - - prompt_text = text; - - dialog.hint.image = Image.Text(prompt_text, 0.5, 0.5, 0.5, 1, common_font); - dialog.hint.sprite.SetImage(dialog.hint.image); - - for (index = 0; dialog.bullet[index] || index < bullets; index++) { - if (!dialog.bullet[index]) { - dialog.bullet[index].sprite = Sprite(dialog.bullet_i.image); - dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_i.width / 0.9 - dialog.entry.height * -0.2; // отступ точки от точки и от поля(modified) - dialog.bullet[index].y = dialog.entry.y + (dialog.entry.height - dialog.bullet_i.height) / 2; - dialog.bullet[index].z = dialog.entry.z + 1; - dialog.bullet[index].sprite.SetPosition(dialog.bullet[index].x, dialog.bullet[index].y, dialog.bullet[index].z); - } - if (index < bullets) - dialog.bullet[index].sprite.SetOpacity(1); - else - dialog.bullet[index].sprite.SetOpacity(0); - } -} - -Plymouth.SetDisplayPasswordFunction(display_password_callback); - - -time = 1; - -function refreshHandler() { - if (global.status == "normal" && Plymouth.GetMode() == "boot") { - progress_fade.sprite.SetOpacity (0); // полностью прозрачный - progress_bar.sprite.SetOpacity (1); - text.image = Image.Text(starting_text, 0.5, 0.5, 0.5, 1, common_font); - text.sprite = Sprite(text.image); - text.x = progress_box.x; - text.y = progress_box.y - progress_text.image.GetHeight() * 2; - text.sprite.SetPosition(text.x, text.y, 13); - } - else { - progress_fade.sprite.SetOpacity (1); - progress_bar.sprite.SetOpacity (0); - text_end.image = Image.Text(bye_text, 0.5, 0.5, 0.5, 1, common_font); - text_end.sprite = Sprite(text_end.image); - text_end.x = progress_box.x; - text_end.y = progress_box.y - progress_text.image.GetHeight() * 2; - text_end.sprite.SetPosition(text_end.x, text_end.y, 13); - } - - progress_fade.x = progress_bar.x; - progress_fade.y = progress_bar.y; - progress_fade.sprite.SetPosition(counter + progress_fade.x, progress_fade.y, 14); - - if (fade_dir == 0) { - counter++; - if (counter >= max_counter) { - fade_dir = 1; - } - } - else { - counter--; - if (counter <= 0) { - fade_dir = 0; - } - } - - /* if fsck is running or the password is prompted, hide the spinner */ - if (fsck_running == 1 || passw_dialog_input_sprite.GetOpacity() == 1) { - spinner.sprite.SetOpacity(0); - } - else { - spinner.sprite.SetOpacity(1); - time++; - theta = time / (Math.Pi * 2); - spinner.sprite.SetImage(spinner.image.Rotate(theta)); - } - - if ((fsck_running == 1) && (fsck_done_fading == 0)) { - fsck_progress_meter_sprite.SetOpacity(fsck_fade_in_counter); - fsck_progress_fade_sprite.SetOpacity(fsck_fade_in_counter); - - if (fsck_fade_in_counter < 1) { - fsck_fade_in_counter+= 0.025; - } - else { - fsck_done_fading = 1; - } - } -} - -Plymouth.SetRefreshFunction(refreshHandler); - - -message_status.sprite = SpriteNew(); - -function message_callback(prompt_text) { - message_status.image = Image.Text(prompt_text, 0.5, 0.5, 0.5, 1, common_font); - message_status.sprite.SetImage(message_status.image); - message_status.height = message_status.image.GetHeight(); - message_status.x = messages_box.x + Percent(5, messages_box.width); - message_status.y = messages_box.y + messages_box.height - Percent(7, messages_box.height); - message_status.sprite.SetOpacity(1); - message_status.sprite.SetPosition(message_status.x, message_status.y, 13); -} - -Plymouth.SetMessageFunction(message_callback); - - -// высота messages_box = screen.height - 40% (1080 * 0,4 = 432) -// высота всех сообщений = NUM_SCROLL_LINES (20) * (LINE_HEIGHT) 17 = 340 -// 10 процентов сверху от начала messages_box.x = 432 - 10% (432 * 0,1) = 432 - 43 = 389 -// конечная точка, где допустимо показывать сообщения = 389 - 43 (10% от высоты messages_box.x) = 346 -// если высота всех сообщений выше, чем высота (messages_box.height - 20%), то уменьшать количество строк, пока высота всех сообщений не быдет меньше (messages_box.height - 20%) - -// высота символа = common_font = 10pt, предположим что 10px -// предположим, что ширина символа = 60% от высоты символа = 6px -// ширина side_panel = 25% от screen.width = 1080 * 0.25 = 270 -// ширина messages_box = 80 % от side_panel = 270 * 0.8 = 216 -// ширина всех сообщений = LINE_WIDTH * ширину символа = 40 * 6 = 240 -// необходимо снижать количество LINE_WIDTH пока реальная ширина сообщения не будет меньше или равно ширине messages_box - -padding_top_bottom = Percent(10, messages_box.height); // отступы сверху и снизу -padding_left_right = Percent(5, messages_box.width); // отступы слева и справа - -message_sprite_.x = messages_box.x + (padding_left_right); // позиция % по X (слева направо) -message_sprite_.y = messages_box.y + (padding_top_bottom); // позиция % по Y (сверху вниз) - -// LOG // -NUM_SCROLL_LINES=100; //количество строк лога -LINE_WIDTH=100; //ширина строк лога -LINE_HEIGHT = common_symbol.height * 1.5; // межстрочный интервал x1,5 - -for (index = NUM_SCROLL_LINES; index > 0; index--) { - if ((NUM_SCROLL_LINES * LINE_HEIGHT) > (messages_box.height - (padding_top_bottom * 2))) { - NUM_SCROLL_LINES=NUM_SCROLL_LINES-1; - } - else { - break; - } -} - -for (index = LINE_WIDTH; index > 0; index--) { - if ((LINE_WIDTH * common_symbol.width) > (messages_box.width - (padding_left_right * 2))) { - LINE_WIDTH=LINE_WIDTH-1; - } - else { - break; - } -} - -// Initialising text images and their positions -// 20 is the height(including line spacing) of each line -for (i=0; i < NUM_SCROLL_LINES; i++) { - lines[i]= Image.Text("", 0.5, 0.5, 0.5, 1, common_font); //цвет строк - message_sprite[i] = SpriteNew(); - message_sprite[i].SetPosition(message_sprite_.x, message_sprite_.y + (i * LINE_HEIGHT), 13); -} //высота строк //отступ строк - - -function StringLength(string) { - index = 0; - str = String(string); - while(str.CharAt(index)) index++; - return index; -} - - -function scroll_message_callback(text) { - // Truncate the message if too long - if (StringLength(text) > LINE_WIDTH) { - text = text.SubString(0, LINE_WIDTH - 3); - text += "..."; - } - - // Shift message one up - for (i = 0; i < NUM_SCROLL_LINES - 1; i++) { - lines[i] = lines[i+1]; - } - - // Create the image for the latest message - lines[i] = Image.Text(text, 0.5, 0.5, 0.5, 1, common_font); - - // Re-positioning the text images - for (i = 0; i < NUM_SCROLL_LINES; i++) { - message_sprite[i].SetImage(lines[i]); - } -} - -Plymouth.SetUpdateStatusFunction(scroll_message_callback); - - -// QUIT -function quit_callback() { - progress_fade.sprite.SetOpacity (1); - progress_bar.sprite.SetOpacity (0); - if (Plymouth.GetMode() == "shutdown") { - logo.sprite.SetOpacity(0); - } -} - -Plymouth.SetQuitFunction(quit_callback); diff --git a/dev/test_quick.sh b/dev/test_quick.sh new file mode 100755 index 0000000..bea5203 --- /dev/null +++ b/dev/test_quick.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Быстрый режим тестирования Plymouth-темы БЕЗ пересборки initramfs +# Просто копирует файлы и запускает демон для интерактивного тестирования +# +# Использование: +# Окно 1: ./test_quick.sh (запуск демона) +# Окно 2: ./d1.sh (тестовые команды) +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$SCRIPT_DIR/.." + +THEME_NAME="melawy-nier-a2" +THEME_PATH="/usr/share/plymouth/themes/$THEME_NAME" + +echo "============================================" +echo " Быстрое тестирование Plymouth-темы" +echo " Тема: $THEME_NAME" +echo "============================================" +echo "" + +# --- Проверка прав --- +if [[ "$UID" != 0 ]]; then + echo "[!] Требуется root, перезапуск через sudo..." + exec sudo "$0" "$@" +fi + +# --- Копирование файлов --- +echo "[1] Копирование темы в $THEME_PATH ..." +mkdir -p "$THEME_PATH" +cp -vrf --remove-destination --no-dereference --preserve=links \ + "$PROJECT_DIR/$THEME_NAME/." "$THEME_PATH/." +echo " ✓ Файлы скопированы" + +# --- Установка темы по умолчанию (без -R = без пересборки initramfs!) --- +echo "[2] Установка темы по умолчанию (БЕЗ пересборки initramfs)..." +plymouth-set-default-theme "$THEME_NAME" +echo " ✓ Тема установлена" + +echo "" +echo "============================================" +echo " Запуск Plymouth daemon (debug mode)" +echo " В ДРУГОМ ОКНЕ выполните:" +echo " cd $(dirname "$0")" +echo " bash d1.sh" +echo "" +echo " Нажмите Ctrl+C для остановки" +echo "============================================" +echo "" +sleep 2 + +# --- Запуск демона --- +exec sudo plymouthd --debug --no-daemon --tty=/dev/tty7 diff --git a/melawy-nier-a2/MAIN_LOGO.png b/melawy-nier-a2/MAIN_LOGO.png index 3b63a5e9652ac62fcd8198e76b18756f2e81b73a..f080f1025e9600ce9722fc007a6596d568bf0759 100644 GIT binary patch literal 26251 zcmX_o1yqz<_xA&cD6KS7UI_&$3F$C^p-Ye!kfA#UX%nR#8VQ9Vm68StML`4x7&-?* z7zdC6>HeR=_xoJSb)DzbK70RmoPGAWuk>}*X(-t#Aqb*@Y1}b{Akqlp-*acd7wX=w zE8supy)?{xAt*7A_?Kkh<5~y!$mVzVzMqjN+z(;v;{YKL2oYxwS6_QuF9#7%AICSV z3hWTX1Hta78V6>sOe4}Pw?cQ0`UpL42IKkc2`U$P&c~1loTZMtbiJS~z>&A2GcG6L ztM_Y80TJ)6L3lZ4K#7~0&!UnIeGuAXr5&mnU-NpWwpOF5Pe5Iy1zDk zqxocvsmLwe2fde-{;0LAd(;8$h~9Jhkxn=)k&qx!$&kTK<)>N)J>*Z69g;;9`L622 zA~of-G4E_ySDW2mqxg`_Z_FZn%Pb5{Fz?U}0TLEBx_>tDIndUZUU&9OIap1RVCY-~H1m{i`sh0f5YhbUqBoOM`Vyno6gGtd(!QFRa9z=Vt&^s|j@P~^vx zNCfxGB689ddGOg{)ODg}A0HmHwY7O*Nk}9qC{>_)c<^UsbyewGkM-|N3w!wcUbj+T zj~Y~7D9+UGk-

vjh&1iqJAEf^Zf=|9%;483qu!Of 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

uRi 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 OgD&fvq8fDF6aNRSg0R8> literal 7271 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 yqZ%Uz0w>lZ3I77O*WR1} diff --git a/melawy-nier-a2/MAIN_LOGO_.png b/melawy-nier-a2/MAIN_LOGO_.png new file mode 100644 index 0000000000000000000000000000000000000000..3b63a5e9652ac62fcd8198e76b18756f2e81b73a GIT binary patch literal 7271 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 yqZ%Uz0w>lZ3I77O*WR1} literal 0 HcmV?d00001 diff --git a/melawy-nier-a2/Melawy_Linux_640x320.png b/melawy-nier-a2/Melawy_Linux_640x320.png deleted file mode 100644 index 5fb656fae4198330ca4c039388d25820b97c6749..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14463 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 -*/ + Theme Name: melawy-plymouth-theme-neon-recline (neon-recline) + Version: 3.0 + Description: Plymouth boot splash theme for Melawy OS + Author: Valeria Fadeeva + https://github.com/Valeria-Fadeeva + https://github.com/Melawy + https://gitlab.com/melawy/ + Date: 2026.07.24 + License: GNU AFFERO GENERAL PUBLIC LICENSE, see + */ + +// ============================================================ +// УТИЛИТЫ +// ============================================================ Window.GetMaxWidth = fun() { i = 0; width = 0; - while (Window.GetWidth(i)){ + while (Window.GetWidth(i)) { width = Math.Max(width, Window.GetWidth(i)); i++; } @@ -20,7 +27,7 @@ Window.GetMaxWidth = fun() { Window.GetMaxHeight = fun() { i = 0; height = 0; - while (Window.GetHeight(i)){ + while (Window.GetHeight(i)) { height = Math.Max(height, Window.GetHeight(i)); i++; } @@ -28,8 +35,7 @@ Window.GetMaxHeight = fun() { }; Percent = fun(perc, pixels) { - result = Math.Int(Math.Abs(Math.Int(pixels)) / 100 * Math.Abs(Math.Int(perc))); - return result; + return Math.Int(Math.Abs(Math.Int(pixels)) / 100 * Math.Abs(Math.Int(perc))); }; Limit = fun(width, height, perc) { @@ -39,135 +45,143 @@ Limit = fun(width, height, perc) { this.perc = perc; this.GetWidth = fun() { - width = Percent(this.perc, this.width); - return width; + return Percent(this.perc, this.width); }; this.GetHeight = fun() { - height = Percent(this.perc, this.height); - return height; + return Percent(this.perc, this.height); }; return this; }; ScaleImage = fun(image1, image2) { - img1.width = image1.GetWidth(); - img1.height = image1.GetHeight(); - img1.ratio = img1.width / img1.height; + local.img1_w = image1.GetWidth(); + local.img1_h = image1.GetHeight(); + local.img1_ratio = img1_w / img1_h; - img2.width = image2.GetWidth(); - img2.height = image2.GetHeight(); - img2.ratio = img2.width / img2.height; + local.img2_w = image2.GetWidth(); + local.img2_h = image2.GetHeight(); + local.img2_ratio = img2_w / img2_h; - if (img1.ratio == 1 || (img1.width < 200 && img1.height < 200)) { - img1.scaled = image1.Scale(img2.width, img2.height); - return img1.scaled; + // Если изображение уже маленькое или квадратное — масштабируем напрямую + if (img1_ratio == 1 || (img1_w < 200 && img1_h < 200)) { + return image1.Scale(img2_w, img2_h); } - if (img1.width == img2.width && img1.height == img2.height) { + // Размеры совпадают — ничего не делаем + if (img2_w == img1_w && img2_h == img1_h) { return image1; } - if (img2.ratio < img1.ratio) { - factor = img2.height / img1.height; + // Сохраняем пропорции + local.factor; + if (img2_ratio < img1_ratio) { + factor = img2_h / img1_h; } else { - factor = img2.width / img1.width; + factor = img2_w / img1_w; } - img1.scaled = image1.Scale(img1.width * factor, img1.height * factor); - - return img1.scaled; + return image1.Scale(Math.Int(img1_w * factor), Math.Int(img1_h * factor)); }; FitIntoDimensions = fun(image1, image2) { - img1.width = image1.GetWidth(); - img1.height = image1.GetHeight(); + local.img1_w = image1.GetWidth(); + local.img1_h = image1.GetHeight(); - img2.width = image2.GetWidth(); - img2.height = image2.GetHeight(); + local.img2_w = image2.GetWidth(); + local.img2_h = image2.GetHeight(); - ma = Math.Max(img1.width, img2.height); - mi = Math.Min(img1.height, img2.height); - factor = ma / mi; + local.ma = Math.Max(img1_w, img1_h); + local.mi = Math.Min(img2_w, img2_h); + if (mi == 0) return image1; - img1.fit = image1.Scale(Math.Int(img1.width / factor), Math.Int(img1.height / factor)); + local.factor = ma / mi; + return image1.Scale(Math.Int(img1_w / factor), Math.Int(img1_h / factor)); }; SetSpriteImage = fun(asset, x, y, z) { local.sprite = Sprite(); - sprite.image = Image(asset); - sprite.width = sprite.image.GetWidth(); - sprite.height = sprite.image.GetHeight(); - sprite.SetImage(sprite.image); + local.img = Image(asset); + sprite.SetImage(img); sprite.SetPosition(x, y, z); return sprite; }; +// Улучшенный blur: больше слоёв с меньшим смещением для более плавного эффекта Blur = fun(background_src, foreground_src, x, y, z, width, height, scale_width, scale_height) { - index = 0; - local.image[index]; + local.result = []; - image[index].image = Image(background_src); - image[index].image = ScaleImage(image[index].image, Limit(scale_width, scale_height, 100)); - image[index].image = image[index].image.Crop(x, y, width, height); - image[index].image = ScaleImage(image[index].image, Limit(Percent(120, width), Percent(120, height), 100)); - image[index].image = image[index].image.Crop(x, y, width, height); + // --- Фон (размытие через многослойное наложение) --- + local.bg_image = Image(background_src); + bg_image = ScaleImage(bg_image, Limit(scale_width, scale_height, 100)); + bg_image = bg_image.Crop(x, y, width, height); + bg_image = ScaleImage(bg_image, Limit(Percent(120, width), Percent(120, height), 100)); + bg_image = bg_image.Crop(x, y, width, height); - image[index].sprite0 = Sprite(image[index].image); - image[index].sprite1 = Sprite(image[index].image); - image[index].sprite2 = Sprite(image[index].image); - image[index].sprite3 = Sprite(image[index].image); - image[index].sprite4 = Sprite(image[index].image); + // Создаём 9 слоёв для более качественного размытия (3x3 сетка со смещением ±1) + local.blur_layers = [ + [-1, -1], [0, -1], [1, -1], + [-1, 0], [0, 0], [1, 0], + [-1, 1], [0, 1], [1, 1] + ]; - image[index].sprite0.SetOpacity(0.25); - image[index].sprite1.SetOpacity(0.25); - image[index].sprite2.SetOpacity(0.25); - image[index].sprite3.SetOpacity(0.25); - image[index].sprite4.SetOpacity(0.25); + local.layer_opacity = 1.0 / 9.0; - image[index].sprite0.SetPosition(x, y, z); - image[index].sprite1.SetPosition(x++, y, z++); - image[index].sprite2.SetPosition(x, y++, z++); - image[index].sprite3.SetPosition(x--, y, z++); - image[index].sprite5.SetPosition(x, y--, z++); + local.i; + for (i = 0; i < 9; i++) { + result[i].sprite = Sprite(bg_image); + result[i].sprite.SetOpacity(layer_opacity); + result[i].sprite.SetPosition( + x + blur_layers[i][0], + y + blur_layers[i][1], + z + i + ); + } - index = 1; - image[index].image = Image(foreground_src); - image[index].image = image[index].image.Scale(width, height); - image[index].sprite = Sprite(image[index].image); - image[index].sprite.SetOpacity(0.75); - image[index].sprite.SetPosition(x, y, z++); + // --- Передний план --- + local.fg_image = Image(foreground_src); + fg_image = fg_image.Scale(width, height); + result[9].sprite = Sprite(fg_image); + result[9].sprite.SetOpacity(0.75); + result[9].sprite.SetPosition(x, y, z + 9); - return local.image; + return result; }; +// ============================================================ +// ШРИФТЫ И ТЕКСТ (масштабируются от высоты экрана) +// ============================================================ -// TEXT -common_font = "Noto Sans Mono Regular 10"; -progress_font = "Noto Sans Mono Regular 12"; -link_font = "Noto Sans Italic 16"; +screen.width = Window.GetMaxWidth(); +screen.height = Window.GetMaxHeight(); + +aspect_ratio = screen.width / screen.height; + +// Базовый размер шрифта зависит от высоты экрана +base_font_size = Math.Max(Math.Int(screen.height / 110), 10); +if (base_font_size > 32) base_font_size = 32; + +common_font = "Noto Sans Mono Regular " + base_font_size; +progress_font = "Noto Sans Mono Regular " + Math.Int(base_font_size * 1.2); +link_font = "Noto Sans Italic " + Math.Int(base_font_size * 1.2); common_symbol.image = Image.Text("M", 0.5, 0.5, 0.5, 1, common_font); -common_symbol.height = common_symbol.image.GetHeight(); // высота символа -common_symbol.width = common_symbol.image.GetWidth(); // ширина символа +common_symbol.height = common_symbol.image.GetHeight(); +common_symbol.width = common_symbol.image.GetWidth(); progress_symbol.image = Image.Text("M", 0.5, 0.5, 0.5, 1, progress_font); -progress_symbol.height = progress_symbol.image.GetHeight(); // высота символа -progress_symbol.width = progress_symbol.image.GetWidth(); // ширина символа +progress_symbol.height = progress_symbol.image.GetHeight(); +progress_symbol.width = progress_symbol.image.GetWidth(); link_symbol.image = Image.Text("M", 0.5, 0.5, 0.5, 1, link_font); -link_symbol.height = link_symbol.image.GetHeight(); // высота символа -link_symbol.width = link_symbol.image.GetWidth(); // ширина символа +link_symbol.height = link_symbol.image.GetHeight(); +link_symbol.width = link_symbol.image.GetWidth(); -starting_text = "Starting up..."; +starting_text = "Starting up…"; bye_text = "System is shutting down"; -progress_t= 0; - -// x0 = Window.GetX(); -// y0 = Window.GetY(); -// z0 = Window.GetZ(); +progress_t = 0; x0 = 0; y0 = 0; @@ -176,11 +190,18 @@ z0 = 0; Window.SetBackgroundTopColor(0, 0, 0); Window.SetBackgroundBottomColor(0, 0, 0); -screen.width = Window.GetMaxWidth(); -screen.height = Window.GetMaxHeight(); +// ============================================================ +// ФОН +// ============================================================ + +if (aspect_ratio == 3440 / 1440) { + background.image = Image("0EkLvkiE_4g_3440x1440.png"); +} else if (aspect_ratio == 1920 / 1080) { + background.image = Image("0EkLvkiE_4g_2564x1440.png"); +} else { + background.image = Image("BACKGROUND.png"); +} -// BACKGROUND -background.image = Image("BACKGROUND.png"); background.image = ScaleImage(background.image, Limit(screen.width, screen.height, 100)); background.width = background.image.GetWidth(); @@ -189,96 +210,89 @@ background.height = background.image.GetHeight(); background.x = x0 + screen.width / 2 - background.width / 2; background.y = y0 + screen.height / 2 - background.height / 2; -//background.x = x0; -//background.y = y0; - -background.sprite = SpriteNew(); +background.sprite = Sprite(); background.sprite.SetImage(background.image); background.sprite.SetOpacity(1); background.sprite.SetPosition(background.x, background.y, 0); -// SIDE BACKGROUND +// ============================================================ +// БОКОВАЯ ПАНЕЛЬ (BLUR) +// ============================================================ + side_panel.background_src = "BACKGROUND.png"; side_panel.foreground_src = "SIDE_BACKGROUND2.png"; side_panel.x = x0; side_panel.y = y0; side_panel.z = 1; -side_panel.width = Percent(33.33, screen.width); +side_panel.width = Percent(25, screen.width); side_panel.height = Percent(100, screen.height); -blur = Blur(side_panel.background_src, side_panel.foreground_src, side_panel.x, side_panel.y, side_panel.z, side_panel.width, side_panel.height, screen.width, screen.height); +blur_result = Blur( + side_panel.background_src, + side_panel.foreground_src, + side_panel.x, side_panel.y, side_panel.z, + side_panel.width, side_panel.height, + screen.width, screen.height +); + +// ============================================================ +// БЛОК СООБЩЕНИЙ +// ============================================================ + +side_block.width = 0; +side_block.height = 0; -// MESSAGES BOX messages_box.image = Image("MESSAGES_BOX.png"); -messages_box.image = messages_box.image.Scale(Percent(80, side_panel.width), Percent(40, side_panel.height)); +messages_box.image = messages_box.image.Scale( + Percent(80, side_panel.width), + Percent(50, side_panel.height) +); messages_box.width = messages_box.image.GetWidth(); messages_box.height = messages_box.image.GetHeight(); -messages_box.x = Percent(50, side_panel.width) - messages_box.width / 2; -messages_box.y = Percent(45, side_panel.height) - messages_box.height; +messages_box.x = Percent(50, side_panel.width) - Percent(50, messages_box.width); +// messages_box.y = Percent(aspect_ratio, side_panel.height); +messages_box.y = 0; messages_box.sprite = Sprite(messages_box.image); messages_box.sprite.SetOpacity(1); messages_box.sprite.SetPosition(messages_box.x, messages_box.y, 12); -// Sise Logo -side_logo.image = Image("Melawy_Linux_640x320.png"); -side_logo.image = ScaleImage(side_logo.image, Limit(screen.width, screen.height, 20)); +side_block.width = messages_box.width; +side_block.height = messages_box.height; -side_logo.width = side_logo.image.GetWidth(); -side_logo.height = side_logo.image.GetHeight(); +// ============================================================ +// ФОРМА ПРОГРЕССА +// ============================================================ -side_logo.x = (side_panel.width - side_logo.width) / 2; -side_logo.y = side_panel.height - side_panel.height * 0.25; - -side_logo.sprite = Sprite(side_logo.image); -side_logo.sprite.SetOpacity(1); -side_logo.sprite.SetPosition(side_logo.x, side_logo.y, 12); - -// **************************************** // - -project_link.image = Image.Text("https://Melawy.ru", 0.5, 0.5, 0.5, 1, link_font); - -project_link.width = project_link.image.GetWidth(); -project_link.height = project_link.image.GetHeight(); - -project_link.sprite = Sprite(project_link.image); -project_link.x = (side_panel.width - project_link.width) / 2; -project_link.y = side_logo.y + side_logo.height; - -project_link.sprite.SetOpacity(1); -project_link.sprite.SetPosition(project_link.x, project_link.y, 12); - -// **************************************** // - -// LOGO -logo.image = Image("MAIN_LOGO.png"); -logo.image = FitIntoDimensions(logo.image, Limit(screen.width, screen.height, 35)); - -logo.sprite = Sprite(logo.image); -logo.x = screen.width / 2 - logo.image.GetWidth() / 2; // позиция логотипа X -logo.y = Percent(10, screen.height); // позиция логотипа Y -logo.sprite.SetOpacity(1); -logo.sprite.SetPosition(logo.x, logo.y, 12); - -// PROGRESS FORM progress_form.image = Image("PROGRESS_FORM.png"); -progress_form.image = progress_form.image.Scale(Percent(80, side_panel.width), Percent(10, side_panel.height)); +progress_form.image = progress_form.image.Scale( + Percent(80, side_panel.width), + Percent(15, side_panel.height) +); progress_form.width = progress_form.image.GetWidth(); progress_form.height = progress_form.image.GetHeight(); -progress_form.x = Percent(50, side_panel.width) - progress_form.width / 2; -progress_form.y = Percent(75, side_panel.height) - progress_form.height; +progress_form.x = Percent(50, side_panel.width) - Percent(50, progress_form.width); +progress_form.y = messages_box.y + messages_box.height + Percent(aspect_ratio, side_panel.height); progress_form.sprite = Sprite(progress_form.image); progress_form.sprite.SetOpacity(1); progress_form.sprite.SetPosition(progress_form.x, progress_form.y, 12); -// SPINNER +side_block.height = side_block.height + Percent(aspect_ratio, side_panel.height) + progress_form.height; + +// ============================================================ +// СПИННЕР +// ============================================================ + spinner.image = Image("SPINNER.png"); -spinner.image = spinner.image.Scale(Percent(1, screen.width), Percent(1, screen.width)); +spinner.image = spinner.image.Scale( + Percent(1, screen.width), + Percent(1, screen.width) +); spinner.width = spinner.image.GetWidth(); spinner.height = spinner.image.GetHeight(); @@ -287,24 +301,33 @@ spinner.x = progress_form.x + progress_form.width - Percent(10, progress_form.wi spinner.y = progress_form.y + Percent(10, progress_form.height); spinner.sprite = Sprite(spinner.image); -spinner.sprite.SetPosition(spinner.x, spinner.y, 13); // позиция за или перед +spinner.sprite.SetPosition(spinner.x, spinner.y, 13); +// ============================================================ +// ТЕКСТ ПРОГРЕССА (%) +// ============================================================ -// PROGRESS TEXT progress_text.image = Image.Text(progress_t + "%", 0.5, 0.5, 0.5, 1, progress_font); progress_text.width = progress_text.image.GetWidth(); progress_text.height = progress_text.image.GetHeight(); -progress_text.x = progress_form.x + Percent(5, progress_form.width); // позиция % по X -progress_text.y = progress_form.y + Percent(10, progress_form.height); // позиция % по Y +progress_text.x = progress_form.x + Percent(5, progress_form.width); +progress_text.y = progress_form.y + Percent(10, progress_form.height); -progress_text.sprite = SpriteNew(); +progress_text.sprite = Sprite(); +progress_text.sprite.SetImage(progress_text.image); progress_text.sprite.SetPosition(progress_text.x, progress_text.y, 13); -// PROGRESS BOX +// ============================================================ +// БЛОК ПРОГРЕССА (РАМКА) +// ============================================================ + progress_box.image = Image("PROGRESS_BOX.png"); -progress_box.image = progress_box.image.Scale(Percent(90, progress_form.width), Percent(15, progress_form.height)); +progress_box.image = progress_box.image.Scale( + Percent(90, progress_form.width), + Percent(15, progress_form.height) +); progress_box.width = progress_box.image.GetWidth(); progress_box.height = progress_box.image.GetHeight(); @@ -315,9 +338,15 @@ progress_box.y = progress_form.y + (progress_form.height - progress_box.height) progress_box.sprite = Sprite(progress_box.image); progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 13); -// PROGRESS BAR +// ============================================================ +// ПОЛОСКА ПРОГРЕССА +// ============================================================ + progress_bar.original_image = Image("PROGRESS_BAR.png"); -progress_bar.original_image = progress_bar.original_image.Scale(Percent(90, progress_form.width), Percent(15, progress_form.height)); +progress_bar.original_image = progress_bar.original_image.Scale( + Percent(90, progress_form.width), + Percent(15, progress_form.height) +); progress_bar.width = progress_bar.original_image.GetWidth(); progress_bar.height = progress_bar.original_image.GetHeight(); @@ -328,26 +357,42 @@ progress_bar.y = progress_form.y + (progress_form.height - progress_bar.original progress_bar.sprite = Sprite(); progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 14); -// PROGRESS FADE +// ============================================================ +// FADE ЭФФЕКТ НА ПРОГРЕССЕ +// ============================================================ + progress_fade.image = Image("PROGRESS_FADE.png"); -progress_fade.image = progress_fade.image.Scale(Percent(10, progress_form.width), Percent(15, progress_form.height)); +progress_fade.image = progress_fade.image.Scale( + Percent(10, progress_form.width), + Percent(15, progress_form.height) +); progress_fade.width = progress_fade.image.GetWidth(); progress_fade.height = progress_fade.image.GetHeight(); progress_fade.sprite = Sprite(progress_fade.image); -fade_dir = 0; // 0 = right, 1 = left -counter = 0; max_counter = progress_box.width - progress_fade.width; +// Глобальные переменные анимации fade +counter = 0; +fade_dir = 0; // 0 = вправо, 1 = влево + +// ============================================================ +// CALLBACK: ПРОГРЕСС ЗАГРУЗКИ +// ============================================================ fun progress_callback(duration, progress) { - if (progress_bar.image.GetWidth() != Math.Int(progress_bar.original_image.GetWidth() * progress)) { - progress_bar.image = progress_bar.original_image.Scale(progress_bar.original_image.GetWidth(progress_bar.original_image) * progress, progress_bar.original_image.GetHeight()); + local.new_width = Math.Int(progress_bar.original_image.GetWidth() * progress); + + if (progress_bar.image.GetWidth() != new_width) { + progress_bar.image = progress_bar.original_image.Scale( + new_width, + progress_bar.original_image.GetHeight() + ); progress_bar.sprite.SetImage(progress_bar.image); - f = Math.Int(progress_bar.image.GetWidth() /progress_bar.original_image.GetWidth() * 100); + local.f = Math.Int(progress * 100); progress_t.image = Image.Text(f + "%", 0.5, 0.5, 0.5, 1, progress_font); progress_text.sprite.SetImage(progress_t.image); } @@ -355,70 +400,82 @@ fun progress_callback(duration, progress) { Plymouth.SetBootProgressFunction(progress_callback); +// ============================================================ +// DIALOG: ЗАПРОС ПАРОЛЯ +// ============================================================ -// DIALOG status = "normal"; -//count = 0; +box_form.image = Image("BOX.png"); +box_form.image = box_form.image.Scale( + Percent(80, side_panel.width), + Percent(20, side_panel.height) +); + +box_form.width = box_form.image.GetWidth(); +box_form.height = box_form.image.GetHeight(); + +box_form.x = Percent(50, side_panel.width) - Percent(50, box_form.width); +box_form.y = progress_form.y + progress_form.height + Percent(aspect_ratio, side_panel.height); +box_form.z = 10000; + +box_form.sprite = Sprite(box_form.image); +box_form.sprite.SetPosition(box_form.x, box_form.y, box_form.z); +box_form.sprite.SetOpacity(0); fun dialog_setup() { - local.box_form; + local.box_form = global.box_form; local.lock; local.entry; local.hint; local.bullet_i; - box_form.image = Image("BOX.png"); - box_form.image = box_form.image.Scale(Percent(80, side_panel.width), Percent(18, side_panel.height)); - - box_form.width = box_form.image.GetWidth(); - box_form.height = box_form.image.GetHeight(); - - box_form.x = progress_form.x; - box_form.y = progress_form.y - box_form.height - Percent(1, side_panel.height); - box_form.z = 10000; - - box_form.sprite = Sprite(box_form.image); box_form.sprite.SetOpacity(1); - box_form.sprite.SetPosition(box_form.x, box_form.y, box_form.z); - entry.image = Image("ENTRY.png"); - entry.image = entry.image.Scale(Percent(90, box_form.width), Percent(20, box_form.height)); + entry.image = entry.image.Scale( + Percent(90, box_form.width), + Percent(20, box_form.height) + ); entry.width = entry.image.GetWidth(); entry.height = entry.image.GetHeight(); - entry.x = box_form.x + box_form.width/2 - entry.width/2; - entry.y = box_form.y + (box_form.height/3 * 2) - entry.height/2; + entry.x = box_form.x + box_form.width / 2 - entry.width / 2; + entry.y = box_form.y + (box_form.height / 3 * 2) - entry.height / 2; entry.z = box_form.z + 1; entry.sprite = Sprite(entry.image); entry.sprite.SetPosition(entry.x, entry.y, entry.z); - lock.image = Image("LOCK.png"); - lock.image = lock.image.Scale(Percent(95, entry.height), Percent(95, entry.height)); + lock.image = lock.image.Scale( + Percent(95, entry.height), + Percent(95, entry.height) + ); lock.width = lock.image.GetWidth(); lock.height = lock.image.GetHeight(); lock.x = entry.x + entry.width - lock.width - (entry.height - lock.height); - lock.y = entry.y + entry.height/2 - lock.height/2; + lock.y = entry.y + entry.height / 2 - lock.height / 2; lock.z = box_form.z + 2; lock.sprite = Sprite(lock.image); lock.sprite.SetPosition(lock.x, lock.y, lock.z); - - hint.sprite = SpriteNew(); - hint.sprite.SetPosition(entry.x, box_form.y + Percent(5, box_form.height), box_form.z + 1); - + hint.sprite = Sprite(); + hint.x = entry.x; + hint.y = box_form.y + Percent(5, box_form.height); + hint.z = box_form.z + 1; + hint.sprite.SetPosition(hint.x, hint.y, hint.z); bullet_i.image = Image("BULLET.png"); - bullet_i.image = bullet_i.image.Scale(Percent(50, entry.height), Percent(50, entry.height)); + bullet_i.image = bullet_i.image.Scale( + Percent(50, entry.height), + Percent(50, entry.height) + ); bullet_i.width = bullet_i.image.GetWidth(); bullet_i.height = bullet_i.image.GetHeight(); - global.dialog.box_form = box_form; global.dialog.lock = lock; global.dialog.entry = entry; @@ -427,36 +484,56 @@ fun dialog_setup() { dialog_opacity(1); } - fun dialog_opacity(opacity) { if (opacity == 0) { dialog.box_form.sprite.SetOpacity(opacity); dialog.lock.sprite.SetOpacity(opacity); dialog.entry.sprite.SetOpacity(opacity); - } - else { + } else { + box_form.sprite.SetOpacity(opacity); dialog.lock.sprite.SetOpacity(opacity); dialog.entry.sprite.SetOpacity(opacity); } dialog.hint.sprite.SetOpacity(opacity); + local.index; for (index = 0; dialog.bullet[index]; index++) { dialog.bullet[index].sprite.SetOpacity(opacity); } } +// ============================================================ +// Изменение позиции интерфейса исходя из его общей высоты +// ============================================================ +side_block.height = side_block.height + Percent(aspect_ratio, side_panel.height) + box_form.height; +yyy = (side_panel.height - side_block.height) / 2; + +messages_box.y = messages_box.y + yyy; +progress_form.y = progress_form.y + yyy; +spinner.y = spinner.y + yyy; +progress_text.y = progress_text.y + yyy; +progress_box.y = progress_box.y + yyy; +progress_bar.y = progress_bar.y + yyy; +box_form.y = box_form.y + yyy; + +messages_box.sprite.SetPosition(messages_box.x, messages_box.y, 12); +progress_form.sprite.SetPosition(progress_form.x, progress_form.y, 12); +spinner.sprite.SetPosition(spinner.x, spinner.y, 13); +progress_text.sprite.SetPosition(progress_text.x, progress_text.y, 13); +progress_box.sprite.SetPosition(progress_box.x, progress_box.y, 13); +progress_bar.sprite.SetPosition(progress_bar.x, progress_bar.y, 14); +box_form.sprite.SetPosition(box_form.x, box_form.y, box_form.z); +// ============================================================ fun display_normal_callback() { global.status = "normal"; - if (global.dialog) dialog_opacity(0); } Plymouth.SetDisplayNormalFunction(display_normal_callback); - fun display_password_callback(prompt_text, bullets) { global.status = "password"; @@ -465,22 +542,19 @@ fun display_password_callback(prompt_text, bullets) { else dialog_opacity(1); - padding_top_bottom = Percent(10, dialog.box_form.height); // отступы сверху и снизу - padding_left_right = Percent(5, dialog.box_form.width); // отступы слева и справа + local.padding_top_bottom = Percent(10, dialog.box_form.height); + local.padding_left_right = Percent(5, dialog.box_form.width); - LINE_WIDTH = 100; + local.LINE_WIDTH = 100; - for (index = LINE_WIDTH; index > 0; index--) { - if ((LINE_WIDTH * common_symbol.width) > (dialog.box_form.width - (padding_left_right * 2))) { - LINE_WIDTH = LINE_WIDTH - 1; - } - else { - break; - } + while ((LINE_WIDTH * common_symbol.width) > (dialog.box_form.width - (padding_left_right * 2))) { + LINE_WIDTH = LINE_WIDTH - 1; } - str_len = StringLength(prompt_text); + local.str_len = StringLength(prompt_text); + local.line_count = 0; + local.i; for (i = 1; LINE_WIDTH * i <= str_len; i++) { line_count = i; } @@ -492,10 +566,10 @@ fun display_password_callback(prompt_text, bullets) { } i = 1; - start = 0; - end = LINE_WIDTH; + local.start = 0; + local.end = LINE_WIDTH; - text = ""; + local.text = ""; for (i = 1; i <= line_count; i++) { text += prompt_text.SubString(start, end); @@ -504,9 +578,8 @@ fun display_password_callback(prompt_text, bullets) { start = end; if (LINE_WIDTH * i < str_len) { end = end + LINE_WIDTH; - } - else { - end = str_len - 1; + } else { + end = str_len; } } @@ -514,14 +587,21 @@ fun display_password_callback(prompt_text, bullets) { dialog.hint.image = Image.Text(prompt_text, 0.5, 0.5, 0.5, 1, common_font); dialog.hint.sprite.SetImage(dialog.hint.image); + // Важно: обновляем позицию после смены изображения + dialog.hint.sprite.SetPosition(dialog.hint.x, dialog.hint.y, dialog.hint.z); + local.index; for (index = 0; dialog.bullet[index] || index < bullets; index++) { if (!dialog.bullet[index]) { dialog.bullet[index].sprite = Sprite(dialog.bullet_i.image); - dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_i.width / 0.9 - dialog.entry.height * -0.2; // отступ точки от точки и от поля(modified) + dialog.bullet[index].x = dialog.entry.x + index * dialog.bullet_i.width / 0.9 - dialog.entry.height * -0.2; dialog.bullet[index].y = dialog.entry.y + (dialog.entry.height - dialog.bullet_i.height) / 2; dialog.bullet[index].z = dialog.entry.z + 1; - dialog.bullet[index].sprite.SetPosition(dialog.bullet[index].x, dialog.bullet[index].y, dialog.bullet[index].z); + dialog.bullet[index].sprite.SetPosition( + dialog.bullet[index].x, + dialog.bullet[index].y, + dialog.bullet[index].z + ); } if (index < bullets) dialog.bullet[index].sprite.SetOpacity(1); @@ -532,65 +612,115 @@ fun display_password_callback(prompt_text, bullets) { Plymouth.SetDisplayPasswordFunction(display_password_callback); +// ============================================================ +// ГЛАВНЫЙ ЛОГОТИП +// ============================================================ + +logo.image = Image("MAIN_LOGO.png"); +logo.image = FitIntoDimensions(logo.image, Limit(screen.width, screen.height, 15)); + +logo.width = logo.image.GetWidth(); +logo.height = logo.image.GetHeight(); + +logo.sprite = Sprite(logo.image); + +logo.x = screen.width - logo.image.GetWidth() - messages_box.x; +logo.y = yyy; +logo.sprite.SetOpacity(1); +logo.sprite.SetPosition(logo.x, logo.y, 12); + +// ============================================================ +// ССЫЛКА НА ПРОЕКТ +// ============================================================ + +project_link.image = Image.Text("https://Melawy.ru", 0.5, 0.5, 0.5, 1, link_font); + +project_link.width = project_link.image.GetWidth(); +project_link.height = project_link.image.GetHeight(); + +project_link.sprite = Sprite(project_link.image); +project_link.x = logo.x + logo.width / 2 - project_link.width / 2; +project_link.y = logo.y + logo.height + Percent(aspect_ratio, screen.height); + +project_link.sprite.SetOpacity(1); +project_link.sprite.SetPosition(project_link.x, project_link.y, 15); + +// ============================================================ +// REFRESH: ОСНОВНОЙ ЦИКЛ АНИМАЦИИ +// ============================================================ time = 1; +// FSCK переменные (для совместимости с Plymouth API) +fsck_running = 0; +fsck_done_fading = 0; +fsck_fade_in_counter = 0; +fsck_progress_meter_sprite = Sprite(); +fsck_progress_fade_sprite = Sprite(); + fun refreshHandler() { - if (global.status == "normal" && Plymouth.GetMode() == "boot") { - progress_fade.sprite.SetOpacity (0); // полностью прозрачный - progress_bar.sprite.SetOpacity (1); - text.image = Image.Text(starting_text, 0.5, 0.5, 0.5, 1, common_font); - text.sprite = Sprite(text.image); - text.x = progress_box.x; - text.y = progress_box.y - progress_text.image.GetHeight() * 2; - text.sprite.SetPosition(text.x, text.y, 13); - } - else { - progress_fade.sprite.SetOpacity (1); - progress_bar.sprite.SetOpacity (0); - text_end.image = Image.Text(bye_text, 0.5, 0.5, 0.5, 1, common_font); - text_end.sprite = Sprite(text_end.image); - text_end.x = progress_box.x; - text_end.y = progress_box.y - progress_text.image.GetHeight() * 2; - text_end.sprite.SetPosition(text_end.x, text_end.y, 13); + // Показываем/скрываем элементы в зависимости от режима + if (global.status == "normal" && Plymouth.GetMode() == "boot") { + progress_fade.sprite.SetOpacity(0); + progress_bar.sprite.SetOpacity(1); + + local.text_img = Image.Text(starting_text, 0.5, 0.5, 0.5, 1, common_font); + local.text_spr = Sprite(text_img); + text_spr.SetPosition( + progress_box.x, + progress_box.y - progress_text.image.GetHeight() * 2, + 13 + ); + } else { + progress_fade.sprite.SetOpacity(1); + progress_bar.sprite.SetOpacity(0); + + local.text_end_img = Image.Text(bye_text, 0.5, 0.5, 0.5, 1, common_font); + local.text_end_spr = Sprite(text_end_img); + text_end_spr.SetPosition( + progress_box.x, + progress_box.y - progress_text.image.GetHeight() * 2, + 13 + ); } - progress_fade.x = progress_bar.x; - progress_fade.y = progress_bar.y; - progress_fade.sprite.SetPosition(counter + progress_fade.x, progress_fade.y, 14); + // Анимация fade-полоски + progress_fade.sprite.SetPosition( + counter + progress_bar.x, + progress_bar.y, + 14 + ); if (fade_dir == 0) { counter++; if (counter >= max_counter) { fade_dir = 1; } - } - else { + } else { counter--; if (counter <= 0) { fade_dir = 0; } } - /* if fsck is running or the password is prompted, hide the spinner */ - if (fsck_running == 1 || passw_dialog_input_sprite.GetOpacity() == 1) { + // Скрываем спиннер при fsck или запросе пароля + if (fsck_running == 1 || (global.dialog && dialog.hint.sprite.GetOpacity() == 1)) { spinner.sprite.SetOpacity(0); - } - else { + } else { spinner.sprite.SetOpacity(1); time++; - theta = time / (Math.Pi * 2); + local.theta = time / (Math.Pi * 2); spinner.sprite.SetImage(spinner.image.Rotate(theta)); } + // FSCK анимация плавного появления if ((fsck_running == 1) && (fsck_done_fading == 0)) { fsck_progress_meter_sprite.SetOpacity(fsck_fade_in_counter); fsck_progress_fade_sprite.SetOpacity(fsck_fade_in_counter); if (fsck_fade_in_counter < 1) { - fsck_fade_in_counter+= 0.025; - } - else { + fsck_fade_in_counter += 0.025; + } else { fsck_done_fading = 1; } } @@ -598,8 +728,11 @@ fun refreshHandler() { Plymouth.SetRefreshFunction(refreshHandler); +// ============================================================ +// CALLBACK: ОДИНОЧНОЕ СООБЩЕНИЕ +// ============================================================ -message_status.sprite = SpriteNew(); +message_status.sprite = Sprite(); fun message_callback(prompt_text) { message_status.image = Image.Text(prompt_text, 0.5, 0.5, 0.5, 1, common_font); @@ -613,82 +746,75 @@ fun message_callback(prompt_text) { Plymouth.SetMessageFunction(message_callback); +// ============================================================ +// СКРОЛЛЯЩИЙСЯ ЛОГ +// ============================================================ -// высота messages_box = screen.height - 40% (1080 * 0,4 = 432) -// высота всех сообщений = NUM_SCROLL_LINES (20) * (LINE_HEIGHT) 17 = 340 -// 10 процентов сверху от начала messages_box.x = 432 - 10% (432 * 0,1) = 432 - 43 = 389 -// конечная точка, где допустимо показывать сообщения = 389 - 43 (10% от высоты messages_box.x) = 346 -// если высота всех сообщений выше, чем высота (messages_box.height - 20%), то уменьшать количество строк, пока высота всех сообщений не быдет меньше (messages_box.height - 20%) +local.padding_top_bottom = Percent(10, messages_box.height); +local.padding_left_right = Percent(5, messages_box.width); -// высота символа = common_font = 10pt, предположим что 10px -// предположим, что ширина символа = 60% от высоты символа = 6px -// ширина side_panel = 25% от screen.width = 1080 * 0.25 = 270 -// ширина messages_box = 80 % от side_panel = 270 * 0.8 = 216 -// ширина всех сообщений = LINE_WIDTH * ширину символа = 40 * 6 = 240 -// необходимо снижать количество LINE_WIDTH пока реальная ширина сообщения не будет меньше или равно ширине messages_box +message_sprite_.x = messages_box.x + padding_left_right; +message_sprite_.y = messages_box.y + padding_top_bottom; -padding_top_bottom = Percent(10, messages_box.height); // отступы сверху и снизу -padding_left_right = Percent(5, messages_box.width); // отступы слева и справа - -message_sprite_.x = messages_box.x + (padding_left_right); // позиция % по X (слева направо) -message_sprite_.y = messages_box.y + (padding_top_bottom); // позиция % по Y (сверху вниз) - -// LOG // -NUM_SCROLL_LINES=100; //количество строк лога -LINE_WIDTH=100; //ширина строк лога -LINE_HEIGHT = common_symbol.height * 1.5; // межстрочный интервал x1,5 +NUM_SCROLL_LINES = 100; +LINE_WIDTH_LOG = 100; +LINE_HEIGHT = common_symbol.height * 1.5; +// Подстраиваем количество строк под высоту блока сообщений +local.index; for (index = NUM_SCROLL_LINES; index > 0; index--) { if ((NUM_SCROLL_LINES * LINE_HEIGHT) > (messages_box.height - (padding_top_bottom * 2))) { - NUM_SCROLL_LINES=NUM_SCROLL_LINES-1; - } - else { + NUM_SCROLL_LINES = NUM_SCROLL_LINES - 1; + } else { break; } } -for (index = LINE_WIDTH; index > 0; index--) { - if ((LINE_WIDTH * common_symbol.width) > (messages_box.width - (padding_left_right * 2))) { - LINE_WIDTH=LINE_WIDTH-1; - } - else { +// Подстраиваем ширину строки под ширину блока сообщений +for (index = LINE_WIDTH_LOG; index > 0; index--) { + if ((LINE_WIDTH_LOG * common_symbol.width) > (messages_box.width - (padding_left_right * 2))) { + LINE_WIDTH_LOG = LINE_WIDTH_LOG - 1; + } else { break; } } -// Initialising text images and their positions -// 20 is the height(including line spacing) of each line -for (i=0; i < NUM_SCROLL_LINES; i++) { - lines[i]= Image.Text("", 0.5, 0.5, 0.5, 1, common_font); //цвет строк - message_sprite[i] = SpriteNew(); - message_sprite[i].SetPosition(message_sprite_.x, message_sprite_.y + (i * LINE_HEIGHT), 13); -} //высота строк //отступ строк - +// Инициализация спрайтов для каждой строки лога +local.i; +for (i = 0; i < NUM_SCROLL_LINES; i++) { + lines[i] = Image.Text("", 0.5, 0.5, 0.5, 1, common_font); + message_sprite[i] = Sprite(); + message_sprite[i].SetPosition( + message_sprite_.x, + message_sprite_.y + (i * LINE_HEIGHT), + 13 + ); +} fun StringLength(string) { - index = 0; - str = String(string); - while(str.CharAt(index)) index++; + local.index = 0; + local.str = String(string); + while (str.CharAt(index)) index++; return index; } - fun scroll_message_callback(text) { - // Truncate the message if too long - if (StringLength(text) > LINE_WIDTH) { - text = text.SubString(0, LINE_WIDTH - 3); - text += "..."; + // Обрезаем слишком длинные сообщения + if (StringLength(text) > LINE_WIDTH_LOG) { + text = text.SubString(0, LINE_WIDTH_LOG - 1); + text += "…"; } - // Shift message one up + // Сдвигаем все сообщения вверх на одну строку + local.i; for (i = 0; i < NUM_SCROLL_LINES - 1; i++) { - lines[i] = lines[i+1]; + lines[i] = lines[i + 1]; } - // Create the image for the latest message + // Создаём изображение для последнего сообщения lines[i] = Image.Text(text, 0.5, 0.5, 0.5, 1, common_font); - // Re-positioning the text images + // Обновляем все спрайты for (i = 0; i < NUM_SCROLL_LINES; i++) { message_sprite[i].SetImage(lines[i]); } @@ -696,11 +822,13 @@ fun scroll_message_callback(text) { Plymouth.SetUpdateStatusFunction(scroll_message_callback); +// ============================================================ +// CALLBACK: ЗАВЕРШЕНИЕ +// ============================================================ -// QUIT fun quit_callback() { - progress_fade.sprite.SetOpacity (1); - progress_bar.sprite.SetOpacity (0); + progress_fade.sprite.SetOpacity(1); + progress_bar.sprite.SetOpacity(0); if (Plymouth.GetMode() == "shutdown") { logo.sprite.SetOpacity(0); }