SHA256
Utilize O5Kit System in Warning and Download Dialogs
This commit is contained in:
2 files changed
+243
-375
No files matched your search
+94
-168
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using MelonLoader;
|
||||||
|
using O5Kit.Core;
|
||||||
|
using O5Kit.Factory;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
using Button = UnityEngine.UI.Button;
|
|
||||||
using Image = UnityEngine.UI.Image;
|
using Image = UnityEngine.UI.Image;
|
||||||
|
|
||||||
namespace ADOFAIRenderer.UI;
|
namespace ADOFAIRenderer.UI;
|
||||||
@@ -29,6 +31,7 @@ internal class CommonWarningDialogUI : MonoBehaviour
|
|||||||
{
|
{
|
||||||
public static CommonWarningDialogUI? Instance { get; private set; }
|
public static CommonWarningDialogUI? Instance { get; private set; }
|
||||||
private readonly List<VisualElement> _disabledElements = new();
|
private readonly List<VisualElement> _disabledElements = new();
|
||||||
|
private O5Window? _window;
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@@ -37,6 +40,9 @@ internal class CommonWarningDialogUI : MonoBehaviour
|
|||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
|
_window?.Dispose();
|
||||||
|
_window = null;
|
||||||
|
|
||||||
foreach (var elem in _disabledElements)
|
foreach (var elem in _disabledElements)
|
||||||
{
|
{
|
||||||
if (elem != null)
|
if (elem != null)
|
||||||
@@ -83,202 +89,122 @@ internal class CommonWarningDialogUI : MonoBehaviour
|
|||||||
|
|
||||||
// Set UI layer (5)
|
// Set UI layer (5)
|
||||||
gameObject.layer = 5;
|
gameObject.layer = 5;
|
||||||
|
|
||||||
// Canvas setup
|
// Canvas setup
|
||||||
var canvas = gameObject.AddComponent<Canvas>();
|
var canvas = gameObject.AddComponent<Canvas>();
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
canvas.sortingOrder = 32766; // Just below FFmpegDownloadUI (32767)
|
canvas.sortingOrder = 32766;
|
||||||
|
|
||||||
// Responsive Canvas Scaler setup
|
|
||||||
var scaler = gameObject.AddComponent<CanvasScaler>();
|
var scaler = gameObject.AddComponent<CanvasScaler>();
|
||||||
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
|
||||||
scaler.referenceResolution = new Vector2(1920, 1080);
|
scaler.referenceResolution = new Vector2(1920, 1080);
|
||||||
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
|
||||||
scaler.matchWidthOrHeight = 0.5f;
|
scaler.matchWidthOrHeight = 0.5f;
|
||||||
|
|
||||||
gameObject.AddComponent<GraphicRaycaster>();
|
gameObject.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
// 1. Create full screen overlay background
|
var ctx = RendererUIManager.Context;
|
||||||
var bgPanelObj = new GameObject("BackgroundPanel");
|
|
||||||
|
// 1. Create full screen backdrop (scrim) to block background input
|
||||||
|
var bgPanelObj = new GameObject("Backdrop");
|
||||||
bgPanelObj.transform.SetParent(transform, false);
|
bgPanelObj.transform.SetParent(transform, false);
|
||||||
bgPanelObj.layer = 5;
|
bgPanelObj.layer = 5;
|
||||||
|
|
||||||
var bgImage = bgPanelObj.AddComponent<Image>();
|
var bgImage = bgPanelObj.AddComponent<Image>();
|
||||||
bgImage.color = new Color(0f, 0f, 0f, 0.65f); // Dark transparent overlay
|
bgImage.color = new Color(0f, 0f, 0f, 0.65f);
|
||||||
bgImage.raycastTarget = true;
|
bgImage.raycastTarget = true;
|
||||||
|
|
||||||
var bgRect = bgPanelObj.GetComponent<RectTransform>();
|
var bgRect = bgPanelObj.GetComponent<RectTransform>();
|
||||||
bgRect.anchorMin = Vector2.zero;
|
bgRect.anchorMin = Vector2.zero;
|
||||||
bgRect.anchorMax = Vector2.one;
|
bgRect.anchorMax = Vector2.one;
|
||||||
bgRect.offsetMin = Vector2.zero;
|
bgRect.offsetMin = Vector2.zero;
|
||||||
bgRect.offsetMax = Vector2.zero;
|
bgRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
var font = ModAssets.NanumSquareNeoNormal;
|
// 2. Create actual native O5Window
|
||||||
|
_window = O5Window.Create(ctx, bgPanelObj.transform, new O5WindowOptions
|
||||||
// 2. Create modal container
|
{
|
||||||
var modalContainerObj = new GameObject("ModalContainer");
|
Id = "RendererMod_WarningDialog",
|
||||||
modalContainerObj.transform.SetParent(bgPanelObj.transform, false);
|
Title = title,
|
||||||
modalContainerObj.layer = 5;
|
Size = new Vector2(540, 240),
|
||||||
|
Draggable = true,
|
||||||
var modalImage = modalContainerObj.AddComponent<Image>();
|
Resizable = false,
|
||||||
modalImage.color = new Color(0.08f, 0.08f, 0.1f, 0.88f); // Matching background tone of existing UI
|
ShowCloseButton = false,
|
||||||
|
ShowOutline = true,
|
||||||
var modalOutline = modalContainerObj.AddComponent<Outline>();
|
Padding = new RectOffset(16, 16, 16, 16)
|
||||||
modalOutline.effectColor = Color.white;
|
});
|
||||||
modalOutline.effectDistance = new Vector2(3.0f, -3.0f); // Consistent with existing UI outline style
|
|
||||||
|
// 3. Build content inside window.Content
|
||||||
var modalRect = modalContainerObj.GetComponent<RectTransform>();
|
var content = _window.Content;
|
||||||
modalRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
||||||
modalRect.anchorMax = new Vector2(0.5f, 0.5f);
|
var vLayout = content.gameObject.AddComponent<VerticalLayoutGroup>();
|
||||||
modalRect.pivot = new Vector2(0.5f, 0.5f);
|
vLayout.spacing = 16f;
|
||||||
modalRect.sizeDelta = new Vector2(650, 360);
|
vLayout.padding = new RectOffset(16, 16, 12, 12);
|
||||||
|
vLayout.childControlWidth = true;
|
||||||
// 3. Create title text
|
vLayout.childControlHeight = true;
|
||||||
var titleObj = new GameObject("TitleText");
|
vLayout.childForceExpandWidth = true;
|
||||||
titleObj.transform.SetParent(modalContainerObj.transform, false);
|
vLayout.childForceExpandHeight = false;
|
||||||
titleObj.layer = 5;
|
|
||||||
|
// Description text
|
||||||
var titleText = titleObj.AddComponent<TextMeshProUGUI>();
|
var descText = O5Factory.ControlText(ctx, content, 18f, noPad: true);
|
||||||
titleText.text = title;
|
|
||||||
titleText.fontSize = 24;
|
|
||||||
titleText.font = font;
|
|
||||||
titleText.color = new Color(1.0f, 0.8f, 0.2f, 1.0f); // Orange/yellow tone matching warning theme
|
|
||||||
titleText.alignment = TextAlignmentOptions.Center;
|
|
||||||
|
|
||||||
var titleRect = titleObj.GetComponent<RectTransform>();
|
|
||||||
titleRect.anchorMin = new Vector2(0, 1);
|
|
||||||
titleRect.anchorMax = new Vector2(1, 1);
|
|
||||||
titleRect.pivot = new Vector2(0.5f, 1);
|
|
||||||
titleRect.anchoredPosition = new Vector2(0, -35);
|
|
||||||
titleRect.sizeDelta = new Vector2(0, 40);
|
|
||||||
|
|
||||||
// 4. Create description text
|
|
||||||
var descObj = new GameObject("DescriptionText");
|
|
||||||
descObj.transform.SetParent(modalContainerObj.transform, false);
|
|
||||||
descObj.layer = 5;
|
|
||||||
|
|
||||||
var descText = descObj.AddComponent<TextMeshProUGUI>();
|
|
||||||
descText.text = description;
|
descText.text = description;
|
||||||
descText.fontSize = 20;
|
|
||||||
descText.font = font;
|
|
||||||
descText.color = new Color(0.85f, 0.85f, 0.85f, 1f);
|
|
||||||
descText.alignment = TextAlignmentOptions.Center;
|
descText.alignment = TextAlignmentOptions.Center;
|
||||||
descText.lineSpacing = 8;
|
descText.textWrappingMode = TextWrappingModes.Normal;
|
||||||
|
descText.lineSpacing = 6;
|
||||||
var descRect = descObj.GetComponent<RectTransform>();
|
descText.color = new Color(0.88f, 0.88f, 0.88f, 1f);
|
||||||
descRect.anchorMin = new Vector2(0, 0.5f);
|
|
||||||
descRect.anchorMax = new Vector2(1, 1);
|
|
||||||
descRect.pivot = new Vector2(0.5f, 0.5f);
|
|
||||||
descRect.anchoredPosition = new Vector2(0, -65);
|
|
||||||
descRect.sizeDelta = new Vector2(-40, 120);
|
|
||||||
|
|
||||||
// 5. Create button container
|
|
||||||
var buttonContainerObj = new GameObject("ButtonContainer", typeof(RectTransform));
|
|
||||||
buttonContainerObj.transform.SetParent(modalContainerObj.transform, false);
|
|
||||||
buttonContainerObj.layer = 5;
|
|
||||||
|
|
||||||
var btnContainerRect = buttonContainerObj.GetComponent<RectTransform>();
|
|
||||||
btnContainerRect.anchorMin = new Vector2(0, 0);
|
|
||||||
btnContainerRect.anchorMax = new Vector2(1, 0);
|
|
||||||
btnContainerRect.pivot = new Vector2(0.5f, 0);
|
|
||||||
btnContainerRect.anchoredPosition = new Vector2(0, 35);
|
|
||||||
btnContainerRect.sizeDelta = new Vector2(0, 50);
|
|
||||||
|
|
||||||
// 6. Dynamic button layout and styling
|
// ReSharper disable once InconsistentNaming
|
||||||
float totalWidth = 560f;
|
var descLE = descText.gameObject.AddComponent<LayoutElement>();
|
||||||
float spacing = 15f;
|
descLE.flexibleWidth = 1f;
|
||||||
float buttonHeight = 45f;
|
descLE.flexibleHeight = 1f;
|
||||||
int numButtons = buttons.Length;
|
|
||||||
|
|
||||||
float buttonWidth = numButtons == 1
|
// Button action row
|
||||||
? 200f
|
var btnRowObj = new GameObject("ButtonRow");
|
||||||
: (totalWidth - (spacing * (numButtons - 1))) / numButtons;
|
btnRowObj.transform.SetParent(content, false);
|
||||||
|
var btnRowRect = btnRowObj.AddComponent<RectTransform>();
|
||||||
|
var btnRowLE = btnRowObj.AddComponent<LayoutElement>();
|
||||||
|
btnRowLE.preferredHeight = 40f;
|
||||||
|
btnRowLE.flexibleWidth = 1f;
|
||||||
|
|
||||||
float startX = numButtons == 1
|
var hLayout = btnRowObj.AddComponent<HorizontalLayoutGroup>();
|
||||||
? 0
|
hLayout.spacing = 10f;
|
||||||
: (-totalWidth / 2f) + (buttonWidth / 2f);
|
hLayout.childAlignment = TextAnchor.MiddleCenter;
|
||||||
|
hLayout.childControlWidth = true;
|
||||||
|
hLayout.childControlHeight = true;
|
||||||
|
hLayout.childForceExpandWidth = true;
|
||||||
|
hLayout.childForceExpandHeight = true;
|
||||||
|
|
||||||
for (int i = 0; i < numButtons; i++)
|
for (var i = 0; i < buttons.Length; i++)
|
||||||
{
|
{
|
||||||
var btnData = buttons[i];
|
var btnData = buttons[i];
|
||||||
var btnObj = new GameObject($"Button_{i}");
|
var btn = O5Factory.Button(
|
||||||
btnObj.transform.SetParent(buttonContainerObj.transform, false);
|
ctx: ctx,
|
||||||
btnObj.layer = 5;
|
parent: btnRowRect,
|
||||||
|
onClick: () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
btnData.OnClick();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Melon<RenderMod>.Logger.Error($"Dialog Button Click Event Error: {ex}");
|
||||||
|
}
|
||||||
|
Destroy(gameObject);
|
||||||
|
},
|
||||||
|
text: btnData.Text,
|
||||||
|
id: $"btn_dialog_{i}",
|
||||||
|
height: 40f
|
||||||
|
);
|
||||||
|
|
||||||
// Define default colors
|
if (btnData.BackgroundColor.HasValue)
|
||||||
Color baseColor = btnData.BackgroundColor ?? new Color(0.2f, 0.2f, 0.23f, 1f); // Custom color or gray default
|
|
||||||
Color hoverColor = ApplyColorBrightness(baseColor, 1.2f);
|
|
||||||
Color pressedColor = ApplyColorBrightness(baseColor, 0.8f);
|
|
||||||
|
|
||||||
var btnImage = btnObj.AddComponent<Image>();
|
|
||||||
btnImage.color = baseColor;
|
|
||||||
btnImage.raycastTarget = true;
|
|
||||||
|
|
||||||
var btn = btnObj.AddComponent<Button>();
|
|
||||||
SetupButtonStyle(btn, baseColor, hoverColor, pressedColor);
|
|
||||||
|
|
||||||
// Register click callback
|
|
||||||
btn.onClick.AddListener(() =>
|
|
||||||
{
|
{
|
||||||
try
|
btn.NormalColor = btnData.BackgroundColor.Value;
|
||||||
{
|
btn.UpdateVisual();
|
||||||
btnData.OnClick();
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MelonLoader.Melon<RenderMod>.Logger.Error($"Dialog Button Click Event Error: {ex}");
|
|
||||||
}
|
|
||||||
Destroy(gameObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
var btnRect = btnObj.GetComponent<RectTransform>();
|
|
||||||
btnRect.anchorMin = new Vector2(0.5f, 0.5f);
|
|
||||||
btnRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
||||||
btnRect.pivot = new Vector2(0.5f, 0.5f);
|
|
||||||
|
|
||||||
float posX = numButtons == 1
|
|
||||||
? 0
|
|
||||||
: startX + i * (buttonWidth + spacing);
|
|
||||||
|
|
||||||
btnRect.anchoredPosition = new Vector2(posX, 0);
|
|
||||||
btnRect.sizeDelta = new Vector2(buttonWidth, buttonHeight);
|
|
||||||
|
|
||||||
// Add text label
|
var le = btn.Rect.gameObject.AddComponent<LayoutElement>();
|
||||||
var txtObj = new GameObject("Text");
|
le.flexibleWidth = 1f;
|
||||||
txtObj.transform.SetParent(btnObj.transform, false);
|
le.preferredHeight = 40f;
|
||||||
txtObj.layer = 5;
|
|
||||||
|
|
||||||
var text = txtObj.AddComponent<TextMeshProUGUI>();
|
|
||||||
text.text = btnData.Text;
|
|
||||||
text.fontSize = 20;
|
|
||||||
text.font = font;
|
|
||||||
text.color = Color.white;
|
|
||||||
text.alignment = TextAlignmentOptions.Center;
|
|
||||||
|
|
||||||
var txtRect = txtObj.GetComponent<RectTransform>();
|
|
||||||
txtRect.anchorMin = Vector2.zero;
|
|
||||||
txtRect.anchorMax = Vector2.one;
|
|
||||||
txtRect.offsetMin = Vector2.zero;
|
|
||||||
txtRect.offsetMax = Vector2.zero;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupButtonStyle(Button button, Color normalColor, Color hoverColor, Color pressedColor)
|
|
||||||
{
|
|
||||||
button.transition = Selectable.Transition.ColorTint;
|
|
||||||
var colors = button.colors;
|
|
||||||
colors.normalColor = normalColor;
|
|
||||||
colors.highlightedColor = hoverColor;
|
|
||||||
colors.pressedColor = pressedColor;
|
|
||||||
colors.disabledColor = new Color(0.3f, 0.3f, 0.3f, 1f);
|
|
||||||
button.colors = colors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Color ApplyColorBrightness(Color color, float factor)
|
|
||||||
{
|
|
||||||
float r = Mathf.Clamp01(color.r * factor);
|
|
||||||
float g = Mathf.Clamp01(color.g * factor);
|
|
||||||
float b = Mathf.Clamp01(color.b * factor);
|
|
||||||
return new Color(r, g, b, color.a);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+149
-207
@@ -4,11 +4,13 @@ using System.IO.Compression;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MelonLoader;
|
||||||
|
using MelonLoader.Utils;
|
||||||
|
using O5Kit.Core;
|
||||||
|
using O5Kit.Factory;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
using MelonLoader;
|
|
||||||
using MelonLoader.Utils;
|
|
||||||
|
|
||||||
namespace ADOFAIRenderer.UI;
|
namespace ADOFAIRenderer.UI;
|
||||||
|
|
||||||
@@ -22,6 +24,7 @@ internal class FFmpegDownloadUI : MonoBehaviour
|
|||||||
private GameObject _statusTextObj = null!;
|
private GameObject _statusTextObj = null!;
|
||||||
private TextMeshProUGUI _statusText = null!;
|
private TextMeshProUGUI _statusText = null!;
|
||||||
|
|
||||||
|
private O5Window? _window;
|
||||||
private bool _isDownloading;
|
private bool _isDownloading;
|
||||||
private string DownloadUrl => Application.platform switch
|
private string DownloadUrl => Application.platform switch
|
||||||
{
|
{
|
||||||
@@ -103,14 +106,16 @@ internal class FFmpegDownloadUI : MonoBehaviour
|
|||||||
scaler.matchWidthOrHeight = 0.5f;
|
scaler.matchWidthOrHeight = 0.5f;
|
||||||
|
|
||||||
gameObject.AddComponent<GraphicRaycaster>();
|
gameObject.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
// 1. Create full screen overlay background
|
var ctx = RendererUIManager.Context;
|
||||||
var bgPanelObj = new GameObject("BackgroundPanel");
|
|
||||||
|
// 1. Create full screen backdrop
|
||||||
|
var bgPanelObj = new GameObject("Backdrop");
|
||||||
bgPanelObj.transform.SetParent(transform, false);
|
bgPanelObj.transform.SetParent(transform, false);
|
||||||
bgPanelObj.layer = 5;
|
bgPanelObj.layer = 5;
|
||||||
|
|
||||||
var bgImage = bgPanelObj.AddComponent<Image>();
|
var bgImage = bgPanelObj.AddComponent<Image>();
|
||||||
bgImage.color = new Color(0f, 0f, 0f, 0.65f); // Dark transparent overlay
|
bgImage.color = new Color(0f, 0f, 0f, 0.65f);
|
||||||
bgImage.raycastTarget = true;
|
bgImage.raycastTarget = true;
|
||||||
|
|
||||||
var bgRect = bgPanelObj.GetComponent<RectTransform>();
|
var bgRect = bgPanelObj.GetComponent<RectTransform>();
|
||||||
@@ -119,51 +124,31 @@ internal class FFmpegDownloadUI : MonoBehaviour
|
|||||||
bgRect.offsetMin = Vector2.zero;
|
bgRect.offsetMin = Vector2.zero;
|
||||||
bgRect.offsetMax = Vector2.zero;
|
bgRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
var font = ModAssets.NanumSquareNeoNormal;
|
// 2. Create actual native O5Window
|
||||||
|
_window = O5Window.Create(ctx, bgPanelObj.transform, new O5WindowOptions
|
||||||
// 2. Create modal container
|
{
|
||||||
var modalContainerObj = new GameObject("ModalContainer");
|
Id = "RendererMod_FFmpegDownloadDialog",
|
||||||
modalContainerObj.transform.SetParent(bgPanelObj.transform, false);
|
Title = "FFmpeg Library Installation Required",
|
||||||
modalContainerObj.layer = 5;
|
Size = new Vector2(580, 270),
|
||||||
|
Draggable = true,
|
||||||
var modalImage = modalContainerObj.AddComponent<Image>();
|
Resizable = false,
|
||||||
modalImage.color = new Color(0.08f, 0.08f, 0.1f, 0.88f);
|
ShowCloseButton = false,
|
||||||
|
ShowOutline = true,
|
||||||
var modalOutline = modalContainerObj.AddComponent<Outline>();
|
Padding = new RectOffset(16, 16, 16, 16)
|
||||||
modalOutline.effectColor = Color.white;
|
});
|
||||||
modalOutline.effectDistance = new Vector2(3.0f, -3.0f);
|
|
||||||
|
var content = _window.Content;
|
||||||
var modalRect = modalContainerObj.GetComponent<RectTransform>();
|
|
||||||
modalRect.anchorMin = new Vector2(0.5f, 0.5f);
|
var vLayout = content.gameObject.AddComponent<VerticalLayoutGroup>();
|
||||||
modalRect.anchorMax = new Vector2(0.5f, 0.5f);
|
vLayout.spacing = 14f;
|
||||||
modalRect.pivot = new Vector2(0.5f, 0.5f);
|
vLayout.padding = new RectOffset(16, 16, 10, 10);
|
||||||
modalRect.sizeDelta = new Vector2(600, 320);
|
vLayout.childControlWidth = true;
|
||||||
|
vLayout.childControlHeight = true;
|
||||||
// 4. Create title text
|
vLayout.childForceExpandWidth = true;
|
||||||
var titleObj = new GameObject("TitleText");
|
vLayout.childForceExpandHeight = false;
|
||||||
titleObj.transform.SetParent(modalContainerObj.transform, false);
|
|
||||||
titleObj.layer = 5;
|
// 3. Description text
|
||||||
|
var descText = O5Factory.ControlText(ctx, content, 18f, noPad: true);
|
||||||
var titleText = titleObj.AddComponent<TextMeshProUGUI>();
|
|
||||||
titleText.text = "FFmpeg Library Installation Required";
|
|
||||||
titleText.fontSize = 26;
|
|
||||||
titleText.font = font;
|
|
||||||
titleText.color = Color.white;
|
|
||||||
titleText.alignment = TextAlignmentOptions.Center;
|
|
||||||
|
|
||||||
var titleRect = titleObj.GetComponent<RectTransform>();
|
|
||||||
titleRect.anchorMin = new Vector2(0, 1);
|
|
||||||
titleRect.anchorMax = new Vector2(1, 1);
|
|
||||||
titleRect.pivot = new Vector2(0.5f, 1);
|
|
||||||
titleRect.anchoredPosition = new Vector2(0, -35);
|
|
||||||
titleRect.sizeDelta = new Vector2(0, 40);
|
|
||||||
|
|
||||||
// 5. Create description text
|
|
||||||
var descObj = new GameObject("DescriptionText");
|
|
||||||
descObj.transform.SetParent(modalContainerObj.transform, false);
|
|
||||||
descObj.layer = 5;
|
|
||||||
|
|
||||||
var descText = descObj.AddComponent<TextMeshProUGUI>();
|
|
||||||
var descStrBuilder = new StringBuilder();
|
var descStrBuilder = new StringBuilder();
|
||||||
descStrBuilder.AppendLine("FFmpeg shared libraries are required to render video.");
|
descStrBuilder.AppendLine("FFmpeg shared libraries are required to render video.");
|
||||||
if (Application.platform == RuntimePlatform.OSXPlayer)
|
if (Application.platform == RuntimePlatform.OSXPlayer)
|
||||||
@@ -176,197 +161,152 @@ internal class FFmpegDownloadUI : MonoBehaviour
|
|||||||
descStrBuilder.AppendLine("Click the button below to automatically download and install from the internet.");
|
descStrBuilder.AppendLine("Click the button below to automatically download and install from the internet.");
|
||||||
descStrBuilder.AppendLine("<color=#aaaaaa><size=13>(Download size: ~70MB, extracted to UserLibs folder)</size></color>");
|
descStrBuilder.AppendLine("<color=#aaaaaa><size=13>(Download size: ~70MB, extracted to UserLibs folder)</size></color>");
|
||||||
}
|
}
|
||||||
|
|
||||||
descText.text = descStrBuilder.ToString();
|
descText.text = descStrBuilder.ToString();
|
||||||
descText.fontSize = 16;
|
|
||||||
descText.font = font;
|
|
||||||
descText.color = new Color(0.85f, 0.85f, 0.85f, 1f);
|
|
||||||
descText.alignment = TextAlignmentOptions.Center;
|
descText.alignment = TextAlignmentOptions.Center;
|
||||||
descText.lineSpacing = 10;
|
descText.textWrappingMode = TextWrappingModes.Normal;
|
||||||
|
descText.lineSpacing = 5;
|
||||||
var descRect = descObj.GetComponent<RectTransform>();
|
descText.color = new Color(0.85f, 0.85f, 0.85f, 1f);
|
||||||
descRect.anchorMin = new Vector2(0, 0.5f);
|
|
||||||
descRect.anchorMax = new Vector2(1, 1);
|
|
||||||
descRect.pivot = new Vector2(0.5f, 0.5f);
|
|
||||||
descRect.anchoredPosition = new Vector2(0, -60);
|
|
||||||
descRect.sizeDelta = new Vector2(-40, 100);
|
|
||||||
|
|
||||||
// 6. Create button container
|
|
||||||
_buttonContainerObj = new GameObject("ButtonContainer", typeof(RectTransform));
|
|
||||||
_buttonContainerObj.transform.SetParent(modalContainerObj.transform, false);
|
|
||||||
_buttonContainerObj.layer = 5;
|
|
||||||
|
|
||||||
var btnContainerRect = _buttonContainerObj.GetComponent<RectTransform>();
|
|
||||||
btnContainerRect.anchorMin = new Vector2(0, 0);
|
|
||||||
btnContainerRect.anchorMax = new Vector2(1, 0);
|
|
||||||
btnContainerRect.pivot = new Vector2(0.5f, 0);
|
|
||||||
btnContainerRect.anchoredPosition = new Vector2(0, 35);
|
|
||||||
btnContainerRect.sizeDelta = new Vector2(0, 50);
|
|
||||||
|
|
||||||
// 7. Create download button
|
|
||||||
var downloadBtnObj = new GameObject("DownloadButton");
|
|
||||||
downloadBtnObj.transform.SetParent(_buttonContainerObj.transform, false);
|
|
||||||
downloadBtnObj.layer = 5;
|
|
||||||
|
|
||||||
var downloadImg = downloadBtnObj.AddComponent<Image>();
|
|
||||||
downloadImg.color = new Color(0.0f, 0.8f, 1.0f, 1.0f); // Sleek cyan/blue
|
|
||||||
downloadImg.raycastTarget = true;
|
|
||||||
|
|
||||||
var downloadBtn = downloadBtnObj.AddComponent<Button>();
|
|
||||||
SetupButtonStyle(downloadBtn, new Color(0.0f, 0.8f, 1.0f, 1.0f), new Color(0.2f, 0.9f, 1.0f, 1.0f), new Color(0.0f, 0.6f, 0.8f, 1.0f));
|
|
||||||
if (Application.platform != RuntimePlatform.OSXPlayer) downloadBtn.onClick.AddListener(StartDownloadProcess);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
downloadBtn.onClick.AddListener(OpenFFmpegWebsite);
|
|
||||||
void OpenFFmpegWebsite() { Application.OpenURL("https://ffmpeg.org"); Destroy(gameObject); }
|
|
||||||
}
|
|
||||||
|
|
||||||
var downloadBtnRect = downloadBtnObj.GetComponent<RectTransform>();
|
var descLE = descText.gameObject.AddComponent<LayoutElement>();
|
||||||
downloadBtnRect.anchorMin = new Vector2(0.5f, 0.5f);
|
descLE.flexibleWidth = 1f;
|
||||||
downloadBtnRect.anchorMax = new Vector2(0.5f, 0.5f);
|
descLE.flexibleHeight = 1f;
|
||||||
downloadBtnRect.pivot = new Vector2(1f, 0.5f);
|
|
||||||
downloadBtnRect.anchoredPosition = new Vector2(-15, 0);
|
// 4. Button container
|
||||||
downloadBtnRect.sizeDelta = new Vector2(180, 45);
|
_buttonContainerObj = new GameObject("ButtonContainer");
|
||||||
|
_buttonContainerObj.transform.SetParent(content, false);
|
||||||
var downloadTextObj = new GameObject("DownloadText");
|
_buttonContainerObj.layer = 5;
|
||||||
downloadTextObj.transform.SetParent(downloadBtnObj.transform, false);
|
|
||||||
downloadTextObj.layer = 5;
|
var btnContainerLE = _buttonContainerObj.AddComponent<LayoutElement>();
|
||||||
|
btnContainerLE.preferredHeight = 40f;
|
||||||
var downloadText = downloadTextObj.AddComponent<TextMeshProUGUI>();
|
btnContainerLE.flexibleWidth = 1f;
|
||||||
downloadText.text = Application.platform != RuntimePlatform.OSXPlayer ? "Download & Install" : "Open Website";
|
|
||||||
downloadText.fontSize = 20;
|
var btnLayout = _buttonContainerObj.AddComponent<HorizontalLayoutGroup>();
|
||||||
downloadText.font = font;
|
btnLayout.spacing = 10f;
|
||||||
downloadText.color = Color.white;
|
btnLayout.childAlignment = TextAnchor.MiddleCenter;
|
||||||
downloadText.alignment = TextAlignmentOptions.Center;
|
btnLayout.childControlWidth = true;
|
||||||
|
btnLayout.childControlHeight = true;
|
||||||
var downloadTextRect = downloadTextObj.GetComponent<RectTransform>();
|
btnLayout.childForceExpandWidth = true;
|
||||||
downloadTextRect.anchorMin = Vector2.zero;
|
btnLayout.childForceExpandHeight = true;
|
||||||
downloadTextRect.anchorMax = Vector2.one;
|
|
||||||
downloadTextRect.offsetMin = Vector2.zero;
|
Action onDownloadClick = Application.platform != RuntimePlatform.OSXPlayer
|
||||||
downloadTextRect.offsetMax = Vector2.zero;
|
? StartDownloadProcess
|
||||||
|
: () => { Application.OpenURL("https://ffmpeg.org"); Destroy(gameObject); };
|
||||||
// 8. Create cancel button
|
|
||||||
var cancelBtnObj = new GameObject("CancelButton");
|
var downloadBtn = O5Factory.Button(
|
||||||
cancelBtnObj.transform.SetParent(_buttonContainerObj.transform, false);
|
ctx: ctx,
|
||||||
cancelBtnObj.layer = 5;
|
parent: _buttonContainerObj.transform,
|
||||||
|
onClick: onDownloadClick,
|
||||||
var cancelImg = cancelBtnObj.AddComponent<Image>();
|
text: Application.platform != RuntimePlatform.OSXPlayer ? "Download & Install" : "Open Website",
|
||||||
cancelImg.color = new Color(0.2f, 0.2f, 0.23f, 1f);
|
id: "btn_ffmpeg_download",
|
||||||
cancelImg.raycastTarget = true;
|
height: 40f
|
||||||
|
);
|
||||||
var cancelBtn = cancelBtnObj.AddComponent<Button>();
|
downloadBtn.NormalColor = ctx.Theme.ObjectActiveBright;
|
||||||
SetupButtonStyle(cancelBtn, new Color(0.2f, 0.2f, 0.23f, 1f), new Color(0.25f, 0.25f, 0.28f, 1f), new Color(0.15f, 0.15f, 0.18f, 1f));
|
downloadBtn.UpdateVisual();
|
||||||
cancelBtn.onClick.AddListener(CancelProcess);
|
|
||||||
|
var downloadBtnLE = downloadBtn.Rect.gameObject.AddComponent<LayoutElement>();
|
||||||
var cancelBtnRect = cancelBtnObj.GetComponent<RectTransform>();
|
downloadBtnLE.flexibleWidth = 1f;
|
||||||
cancelBtnRect.anchorMin = new Vector2(0.5f, 0.5f);
|
downloadBtnLE.preferredHeight = 40f;
|
||||||
cancelBtnRect.anchorMax = new Vector2(0.5f, 0.5f);
|
|
||||||
cancelBtnRect.pivot = new Vector2(0f, 0.5f);
|
var cancelBtn = O5Factory.Button(
|
||||||
cancelBtnRect.anchoredPosition = new Vector2(15, 0);
|
ctx: ctx,
|
||||||
cancelBtnRect.sizeDelta = new Vector2(180, 45);
|
parent: _buttonContainerObj.transform,
|
||||||
|
onClick: CancelProcess,
|
||||||
var cancelTextObj = new GameObject("CancelText");
|
text: "Cancel",
|
||||||
cancelTextObj.transform.SetParent(cancelBtnObj.transform, false);
|
id: "btn_ffmpeg_cancel",
|
||||||
cancelTextObj.layer = 5;
|
height: 40f
|
||||||
|
);
|
||||||
var cancelText = cancelTextObj.AddComponent<TextMeshProUGUI>();
|
var cancelBtnLE = cancelBtn.Rect.gameObject.AddComponent<LayoutElement>();
|
||||||
cancelText.text = "Cancel";
|
cancelBtnLE.flexibleWidth = 1f;
|
||||||
cancelText.fontSize = 20;
|
cancelBtnLE.preferredHeight = 40f;
|
||||||
cancelText.font = font;
|
|
||||||
cancelText.color = new Color(0.9f, 0.9f, 0.9f, 1f);
|
// 5. Progress bar container
|
||||||
cancelText.alignment = TextAlignmentOptions.Center;
|
|
||||||
|
|
||||||
var cancelTextRect = cancelTextObj.GetComponent<RectTransform>();
|
|
||||||
cancelTextRect.anchorMin = Vector2.zero;
|
|
||||||
cancelTextRect.anchorMax = Vector2.one;
|
|
||||||
cancelTextRect.offsetMin = Vector2.zero;
|
|
||||||
cancelTextRect.offsetMax = Vector2.zero;
|
|
||||||
|
|
||||||
// 9. Create progress bar container
|
|
||||||
_progressBarObj = new GameObject("ProgressBarContainer");
|
_progressBarObj = new GameObject("ProgressBarContainer");
|
||||||
_progressBarObj.transform.SetParent(modalContainerObj.transform, false);
|
_progressBarObj.transform.SetParent(content, false);
|
||||||
_progressBarObj.layer = 5;
|
_progressBarObj.layer = 5;
|
||||||
_progressBarObj.SetActive(false);
|
_progressBarObj.SetActive(false);
|
||||||
|
|
||||||
|
var pbLE = _progressBarObj.AddComponent<LayoutElement>();
|
||||||
|
pbLE.preferredHeight = 24f;
|
||||||
|
pbLE.flexibleWidth = 1f;
|
||||||
|
|
||||||
var barBgImg = _progressBarObj.AddComponent<Image>();
|
var barBgImg = _progressBarObj.AddComponent<Image>();
|
||||||
barBgImg.color = new Color(0.08f, 0.08f, 0.1f, 1.0f);
|
barBgImg.sprite = ctx.Sprites.RoundedControl;
|
||||||
|
barBgImg.type = Image.Type.Sliced;
|
||||||
var barBgOutline = _progressBarObj.AddComponent<Outline>();
|
barBgImg.color = ctx.Theme.ObjectBG;
|
||||||
barBgOutline.effectColor = Color.white;
|
|
||||||
barBgOutline.effectDistance = new Vector2(3.0f, -3.0f);
|
var barOutlineObj = new GameObject("BarOutline");
|
||||||
|
barOutlineObj.transform.SetParent(_progressBarObj.transform, false);
|
||||||
var barRect = _progressBarObj.GetComponent<RectTransform>();
|
barOutlineObj.layer = 5;
|
||||||
barRect.anchorMin = new Vector2(0.5f, 0);
|
|
||||||
barRect.anchorMax = new Vector2(0.5f, 0);
|
var barOutlineImg = barOutlineObj.AddComponent<Image>();
|
||||||
barRect.pivot = new Vector2(0.5f, 0);
|
barOutlineImg.sprite = ctx.Sprites.RoundedOutline;
|
||||||
barRect.anchoredPosition = new Vector2(0, 75);
|
barOutlineImg.type = Image.Type.Sliced;
|
||||||
barRect.sizeDelta = new Vector2(480, 24);
|
barOutlineImg.color = ctx.Theme.ControlOutlineIdle;
|
||||||
|
barOutlineImg.raycastTarget = false;
|
||||||
// 10. Create progress bar fill image
|
|
||||||
|
var barOutlineRect = barOutlineObj.GetComponent<RectTransform>();
|
||||||
|
barOutlineRect.anchorMin = Vector2.zero;
|
||||||
|
barOutlineRect.anchorMax = Vector2.one;
|
||||||
|
barOutlineRect.offsetMin = Vector2.zero;
|
||||||
|
barOutlineRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
|
// Progress bar fill image
|
||||||
_progressBarFillObj = new GameObject("ProgressBarFill");
|
_progressBarFillObj = new GameObject("ProgressBarFill");
|
||||||
_progressBarFillObj.transform.SetParent(_progressBarObj.transform, false);
|
_progressBarFillObj.transform.SetParent(_progressBarObj.transform, false);
|
||||||
_progressBarFillObj.layer = 5;
|
_progressBarFillObj.layer = 5;
|
||||||
|
|
||||||
var fillImg = _progressBarFillObj.AddComponent<Image>();
|
var fillImg = _progressBarFillObj.AddComponent<Image>();
|
||||||
fillImg.color = new Color(0.0f, 0.8f, 1.0f, 1.0f);
|
fillImg.sprite = ctx.Sprites.RoundedControl;
|
||||||
|
fillImg.type = Image.Type.Sliced;
|
||||||
|
fillImg.color = ctx.Theme.ObjectActiveBright;
|
||||||
|
|
||||||
_fillRect = _progressBarFillObj.GetComponent<RectTransform>();
|
_fillRect = _progressBarFillObj.GetComponent<RectTransform>();
|
||||||
_fillRect.anchorMin = new Vector2(0, 0);
|
_fillRect.anchorMin = new Vector2(0, 0);
|
||||||
_fillRect.anchorMax = new Vector2(0, 1);
|
_fillRect.anchorMax = new Vector2(0, 1);
|
||||||
_fillRect.pivot = new Vector2(0, 0.5f);
|
_fillRect.pivot = new Vector2(0, 0.5f);
|
||||||
_fillRect.anchoredPosition = Vector2.zero;
|
_fillRect.anchoredPosition = Vector2.zero;
|
||||||
_fillRect.sizeDelta = Vector2.zero;
|
_fillRect.sizeDelta = Vector2.zero;
|
||||||
|
|
||||||
// 11. Create progress text
|
// Progress text
|
||||||
var progressTextObj = new GameObject("ProgressBarText");
|
var progressTextObj = new GameObject("ProgressBarText");
|
||||||
progressTextObj.transform.SetParent(_progressBarObj.transform, false);
|
progressTextObj.transform.SetParent(_progressBarObj.transform, false);
|
||||||
progressTextObj.layer = 5;
|
progressTextObj.layer = 5;
|
||||||
|
|
||||||
_progressText = progressTextObj.AddComponent<TextMeshProUGUI>();
|
_progressText = progressTextObj.AddComponent<TextMeshProUGUI>();
|
||||||
_progressText.fontSize = 16;
|
_progressText.fontSize = 13;
|
||||||
_progressText.font = font;
|
_progressText.font = ctx.Fonts.Regular;
|
||||||
_progressText.color = Color.white;
|
_progressText.color = Color.white;
|
||||||
_progressText.alignment = TextAlignmentOptions.Center;
|
_progressText.alignment = TextAlignmentOptions.Center;
|
||||||
|
_progressText.raycastTarget = false;
|
||||||
var progressTextOutline = progressTextObj.AddComponent<Outline>();
|
|
||||||
progressTextOutline.effectColor = new Color(0, 0, 0, 0.8f);
|
|
||||||
progressTextOutline.effectDistance = new Vector2(1, -1);
|
|
||||||
|
|
||||||
var progressTextRect = progressTextObj.GetComponent<RectTransform>();
|
var progressTextRect = progressTextObj.GetComponent<RectTransform>();
|
||||||
progressTextRect.anchorMin = Vector2.zero;
|
progressTextRect.anchorMin = Vector2.zero;
|
||||||
progressTextRect.anchorMax = Vector2.one;
|
progressTextRect.anchorMax = Vector2.one;
|
||||||
progressTextRect.offsetMin = Vector2.zero;
|
progressTextRect.offsetMin = Vector2.zero;
|
||||||
progressTextRect.offsetMax = Vector2.zero;
|
progressTextRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
// 12. Create status text
|
// 6. Status text
|
||||||
_statusTextObj = new GameObject("StatusText");
|
_statusTextObj = new GameObject("StatusText");
|
||||||
_statusTextObj.transform.SetParent(modalContainerObj.transform, false);
|
_statusTextObj.transform.SetParent(content, false);
|
||||||
_statusTextObj.layer = 5;
|
_statusTextObj.layer = 5;
|
||||||
_statusTextObj.SetActive(false);
|
_statusTextObj.SetActive(false);
|
||||||
|
|
||||||
|
var statusLE = _statusTextObj.AddComponent<LayoutElement>();
|
||||||
|
statusLE.preferredHeight = 22f;
|
||||||
|
statusLE.flexibleWidth = 1f;
|
||||||
|
|
||||||
_statusText = _statusTextObj.AddComponent<TextMeshProUGUI>();
|
_statusText = _statusTextObj.AddComponent<TextMeshProUGUI>();
|
||||||
_statusText.fontSize = 16;
|
_statusText.fontSize = 14;
|
||||||
_statusText.font = font;
|
_statusText.font = ctx.Fonts.Regular;
|
||||||
_statusText.color = new Color(0.8f, 0.8f, 0.8f, 1f);
|
_statusText.color = new Color(0.8f, 0.8f, 0.8f, 1f);
|
||||||
_statusText.alignment = TextAlignmentOptions.Center;
|
_statusText.alignment = TextAlignmentOptions.Center;
|
||||||
|
_statusText.raycastTarget = false;
|
||||||
var statusRect = _statusTextObj.GetComponent<RectTransform>();
|
|
||||||
statusRect.anchorMin = new Vector2(0, 0);
|
|
||||||
statusRect.anchorMax = new Vector2(1, 0);
|
|
||||||
statusRect.pivot = new Vector2(0.5f, 0);
|
|
||||||
statusRect.anchoredPosition = new Vector2(0, 35);
|
|
||||||
statusRect.sizeDelta = new Vector2(0, 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupButtonStyle(Button button, Color normalColor, Color hoverColor, Color pressedColor)
|
var statusRect = _statusTextObj.GetComponent<RectTransform>();
|
||||||
{
|
statusRect.anchorMin = Vector2.zero;
|
||||||
button.transition = Selectable.Transition.ColorTint;
|
statusRect.anchorMax = Vector2.one;
|
||||||
var colors = button.colors;
|
statusRect.offsetMin = Vector2.zero;
|
||||||
colors.normalColor = normalColor;
|
statusRect.offsetMax = Vector2.zero;
|
||||||
colors.highlightedColor = hoverColor;
|
|
||||||
colors.pressedColor = pressedColor;
|
|
||||||
colors.disabledColor = new Color(0.3f, 0.3f, 0.3f, 1f);
|
|
||||||
button.colors = colors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
@@ -643,6 +583,8 @@ internal class FFmpegDownloadUI : MonoBehaviour
|
|||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
|
_window?.Dispose();
|
||||||
|
_window = null;
|
||||||
_cts?.Dispose();
|
_cts?.Dispose();
|
||||||
if (Instance == this)
|
if (Instance == this)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user