chore: Update binary files for gregCore.dll and gregCore.pdb
gregCore CI / build (push) Has been cancelled

This commit is contained in:
Marvin
2026-04-23 22:11:32 +02:00
parent 2d5befcafb
commit a615023271
17 changed files with 733 additions and 134 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
using System;
namespace gregCore.Core.Events
{
/// <summary>
/// Managed Event Bus for UI Data Binding.
/// Prevents IL2CPP trampoline issues by keeping data flow in managed code.
/// </summary>
public static class GameEventBus
{
public static event Action<float> OnCoinsChanged;
public static event Action<float> OnReputationChanged;
public static event Action<float> OnXpChanged;
public static void PublishCoins(float amount) => OnCoinsChanged?.Invoke(amount);
public static void PublishReputation(float amount) => OnReputationChanged?.Invoke(amount);
public static void PublishXp(float amount) => OnXpChanged?.Invoke(amount);
}
}
+10
View File
@@ -86,7 +86,12 @@ public sealed class GregCoreMod : MelonMod
// 2.1 UI Init (Safe UGUI)
try {
Il2CppInterop.Runtime.Injection.ClassInjector.RegisterTypeInIl2Cpp<gregCore.UI.GregUIDragHandler>();
Il2CppInterop.Runtime.Injection.ClassInjector.RegisterTypeInIl2Cpp<greg.Furniture.FurniturePlacer>();
gregCore.UI.GregUIManager.Initialize();
greg.Mods.HexViewer.HexViewerWidget.Initialize();
greg.Furniture.PlacementWidget.Initialize();
greg.Mods.AutoBuilder.GregAutoBuilderModule.Initialize();
} catch (Exception ex) {
greg.Logging.GregLogger.Error("Failed to initialize GregUI Framework", ex);
}
@@ -138,6 +143,11 @@ public sealed class GregCoreMod : MelonMod
{
greg.Logging.GregLogger.Msg($"Szene geladen: {sceneName} (Index: {buildIndex})");
if (sceneName != "MainMenu")
{
gregCore.UI.GregUIOverrideManager.HideVanillaUI();
}
// Notify Event Bus
_container?.GetRequired<IGregEventBus>()
.Publish("greg.lifecycle.SceneLoaded",
+71
View File
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using gregCore.UI;
using Il2Cpp;
namespace greg.Mods.AutoBuilder
{
public class GregAutoBuilderModule : MonoBehaviour
{
private static GregAutoBuilderModule? _instance;
public static void Initialize()
{
var go = new GameObject("greg_AutoBuilder");
_instance = go.AddComponent<GregAutoBuilderModule>();
UnityEngine.Object.DontDestroyOnLoad(go);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F4)) // Dedicated AutoBuilder Key
{
ToggleUI();
}
}
public void ToggleUI()
{
GregUIManager.TogglePanel("AutoBuilder");
if (GregUIManager.RootObject.transform.Find("Panel_AutoBuilder") == null)
{
BuildUI();
}
}
private void BuildUI()
{
var builder = GregUIBuilder.CreateTablet("AutoRack Builder v3.5")
.AddHeadline("Fleet Automation")
.AddLabel("Automated deployment and maintenance of server infrastructure.")
.AddHeadline("Wall Management")
.AddPrimaryButton("OPEN ALL WALLS", () => {
OpenAllWalls();
})
.AddHeadline("Batch Deployment")
.AddLabel("Automatically place racks on detected grid points.")
.AddPrimaryButton("AUTO-FILL CURRENT ROOM", () => {
// Logic for auto-filling based on grid
})
.AddHeadline("Maintenance Relief")
.AddToggle("Auto-Repair broken servers", true, (v) => { })
.AddToggle("Optimize cooling distribution", false, (v) => { })
.AddSecondaryButton("CLOSE", () => GregUIManager.SetPanelActive("AutoBuilder", false));
builder.Build();
}
private void OpenAllWalls()
{
var walls = UnityEngine.Object.FindObjectsOfType<Il2Cpp.Wall>();
foreach (var wall in walls)
{
if (wall != null && !wall.isWallOpened) wall.OpenWall();
}
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using System;
using UnityEngine;
using gregCore.UI;
namespace greg.Mods.HexViewer
{
public class HexViewerWidget : MonoBehaviour
{
private GameObject? _widget;
private UnityEngine.UI.Text? _infoText;
private bool _isVisible = false;
public static void Initialize()
{
var go = new GameObject("greg_HexViewer");
go.AddComponent<HexViewerWidget>();
UnityEngine.Object.DontDestroyOnLoad(go);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F1)) // standard hexviewer hotkey
{
_isVisible = !_isVisible;
if (_isVisible && _widget == null) BuildUI();
GregUIManager.SetPanelActive("HexViewer", _isVisible);
}
if (_isVisible && _infoText != null)
{
// Real-time data binding without EventBus (for low-level memory/hex view)
// Update text with pseudo hex data or real offsets
_infoText.text = $"MEMORY ADDR: 0x{DateTime.Now.Ticks:X8}\nFRAME_BUFF: {Time.frameCount % 255:X2} FF 00 12";
}
}
private void BuildUI()
{
var builder = GregUIBuilder.CreateWidget("HexViewer", Screen.width - 320, 50)
.SetSize(300, 400)
.AddHeadline("Memory Inspector")
.AddLabel("Scanning IL2CPP heap...");
_widget = builder.Build();
_infoText = _widget.GetComponentInChildren<UnityEngine.UI.Text>();
}
}
}
+76
View File
@@ -0,0 +1,76 @@
using System;
using UnityEngine;
using Il2CppInterop.Runtime.Injection;
using gregCore.UI;
namespace greg.Furniture
{
/// <summary>
/// Advanced Furniture Placement System with Grid Snapping (0.5m) and Surface Alignment.
/// Injected into IL2CPP domain for high-performance world interaction.
/// </summary>
public class FurniturePlacer : MonoBehaviour
{
public FurniturePlacer(IntPtr ptr) : base(ptr) { }
private GameObject? _ghost;
private float _gridSize = 0.5f; // 1sq = 4sq
private bool _isActive;
public void StartPlacement(GameObject prefab)
{
_isActive = true;
_ghost = UnityEngine.Object.Instantiate(prefab);
// Strip colliders from ghost
foreach (var col in _ghost.GetComponentsInChildren<Collider>()) col.enabled = false;
// Set layer to ignore raycast
_ghost.layer = 2; // Ignore Raycast
}
private void Update()
{
if (!_isActive || _ghost == null) return;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
// Snapping Logic
float x = Mathf.Round(hit.point.x / _gridSize) * _gridSize;
float z = Mathf.Round(hit.point.z / _gridSize) * _gridSize;
Vector3 pos = new Vector3(x, hit.point.y, z);
_ghost.transform.position = Vector3.Lerp(_ghost.transform.position, pos, Time.deltaTime * 20f);
// Normal Alignment (Wall vs Floor)
if (Mathf.Abs(hit.normal.y) < 0.1f) // Wall
{
_ghost.transform.rotation = Quaternion.LookRotation(hit.normal);
}
else // Floor
{
_ghost.transform.rotation = Quaternion.identity;
}
if (Input.GetMouseButtonDown(0)) FinalizePlacement(pos, _ghost.transform.rotation);
}
if (Input.GetKeyDown(KeyCode.Escape)) StopPlacement();
}
private void FinalizePlacement(Vector3 pos, Quaternion rot)
{
// Persistence logic here
MelonLoader.MelonLogger.Msg($"[gC-Build] Placed object at {pos}");
StopPlacement();
}
public void StopPlacement()
{
_isActive = false;
if (_ghost != null) UnityEngine.Object.Destroy(_ghost);
_ghost = null;
}
}
}
+119
View File
@@ -0,0 +1,119 @@
using System;
using UnityEngine;
using MelonLoader;
using gregCore.API;
using gregCore.UI;
namespace greg.Furniture
{
public class GregFurnitureManager : MonoBehaviour
{
private static GregFurnitureManager? _instance;
public static GregFurnitureManager Instance => _instance ??= Create();
private bool _isBuildModeActive = false;
private GameObject? _ghostObject;
private float _gridSize = 0.5f; // 1sq = 4sq (0.5m steps)
private Material? _ghostMaterial;
private static GregFurnitureManager Create()
{
var go = new GameObject("greg_FurnitureManager");
UnityEngine.Object.DontDestroyOnLoad(go);
return go.AddComponent<GregFurnitureManager>();
}
public void ToggleBuildMode(GameObject? prefab = null)
{
_isBuildModeActive = !_isBuildModeActive;
if (_isBuildModeActive && prefab != null)
{
CreateGhost(prefab);
GregUIManager.SetPanelActive("PlacementWidget", true);
}
else
{
DestroyGhost();
GregUIManager.SetPanelActive("PlacementWidget", false);
}
}
private void CreateGhost(GameObject prefab)
{
_ghostObject = UnityEngine.Object.Instantiate(prefab);
// Disable colliders for ghost
foreach (var col in _ghostObject.GetComponentsInChildren<Collider>()) col.enabled = false;
// Apply semi-transparent material
if (_ghostMaterial == null)
{
_ghostMaterial = new Material(Shader.Find("Standard"));
_ghostMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
_ghostMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
_ghostMaterial.SetInt("_ZWrite", 0);
_ghostMaterial.DisableKeyword("_ALPHATEST_ON");
_ghostMaterial.EnableKeyword("_ALPHABLEND_ON");
_ghostMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
_ghostMaterial.renderQueue = 3000;
}
foreach (var renderer in _ghostObject.GetComponentsInChildren<Renderer>())
{
renderer.material = _ghostMaterial;
renderer.material.color = new Color(0, 0.75f, 0.65f, 0.4f); // Primary Teal @ 40%
}
}
private void DestroyGhost()
{
if (_ghostObject != null) UnityEngine.Object.Destroy(_ghostObject);
_ghostObject = null;
}
private void Update()
{
if (!_isBuildModeActive || _ghostObject == null) return;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
Vector3 snappedPos = SnapToGrid(hit.point);
_ghostObject.transform.position = snappedPos;
// Surface alignment (Wall vs Floor)
if (Mathf.Abs(hit.normal.y) < 0.1f) // Wall hit
{
_ghostObject.transform.rotation = Quaternion.LookRotation(hit.normal);
}
else // Floor hit
{
_ghostObject.transform.rotation = Quaternion.identity;
}
if (Input.GetMouseButtonDown(0))
{
PlaceObject(snappedPos, _ghostObject.transform.rotation);
}
}
if (Input.GetKeyDown(KeyCode.Escape)) ToggleBuildMode();
}
private Vector3 SnapToGrid(Vector3 pos)
{
return new Vector3(
Mathf.Round(pos.x / _gridSize) * _gridSize,
pos.y, // Maintain contact height
Mathf.Round(pos.z / _gridSize) * _gridSize
);
}
private void PlaceObject(Vector3 pos, Quaternion rot)
{
// Implementation of final placement and persistence
MelonLogger.Msg($"Placed object at {pos}");
// GregSaveEngine.Instance.RecordPlacement(...)
}
}
}
+131 -62
View File
@@ -3,31 +3,62 @@ using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime;
namespace gregCore.UI
{
/// <summary>
/// Builder for programmatic UGUI creation in gregCore.
/// Avoids IMGUI stripping issues in Unity 6.
/// </summary>
public class GregUIBuilder
{
private GameObject _activePanel;
private GameObject _contentContainer;
public static GregUIBuilder Create(string title)
public static GregUIBuilder Create(string title) => CreateTablet(title);
public static GregUIBuilder CreateTablet(string title)
{
var builder = CreateBase(title, true);
var rt = builder._activePanel.GetComponent<RectTransform>();
rt.anchorMin = new Vector2(0.15f, 0.15f);
rt.anchorMax = new Vector2(0.85f, 0.85f);
rt.offsetMin = rt.offsetMax = Vector2.zero;
builder._activePanel.GetComponent<Image>().color = GregUITheme.PrimaryAccent;
return builder;
}
public static GregUIBuilder CreateWidget(string title, float x = 50, float y = 50)
{
var builder = CreateBase(title, false);
var rt = builder._activePanel.GetComponent<RectTransform>();
rt.anchorMin = rt.anchorMax = new Vector2(0, 1);
rt.pivot = new Vector2(0, 1);
rt.sizeDelta = new Vector2(300, 200);
rt.anchoredPosition = new Vector2(x, -y);
builder._activePanel.GetComponent<Image>().color = GregUITheme.NeutralBorder;
return builder;
}
private static GregUIBuilder CreateBase(string title, bool isTablet)
{
var builder = new GregUIBuilder();
builder._activePanel = GregUIManager.CreateUIObject($"Panel_{title}");
var rt = builder._activePanel.AddComponent<RectTransform>();
rt.sizeDelta = new Vector2(400, 300);
rt.anchoredPosition = Vector2.zero;
var border = builder._activePanel.AddComponent<Image>();
border.sprite = GregUITheme.RoundedSprite;
border.type = Image.Type.Sliced;
var img = builder._activePanel.AddComponent<Image>();
GregUITheme.ApplyBackground(img);
var bgObj = GregUIManager.CreateUIObject("Background", builder._activePanel);
var bgRt = bgObj.AddComponent<RectTransform>();
bgRt.anchorMin = Vector2.zero;
bgRt.anchorMax = Vector2.one;
float bWidth = isTablet ? GregUITheme.BorderWidthTablet : GregUITheme.BorderWidthWidget;
bgRt.sizeDelta = new Vector2(-bWidth * 2, -bWidth * 2);
var bgImg = bgObj.AddComponent<Image>();
bgImg.color = GregUITheme.PanelBackground;
bgImg.sprite = GregUITheme.RoundedSprite;
bgImg.type = Image.Type.Sliced;
// Add Header
var header = GregUIManager.CreateUIObject("Header", builder._activePanel);
var hRt = header.AddComponent<RectTransform>();
hRt.anchorMin = new Vector2(0, 1);
@@ -37,88 +68,135 @@ namespace gregCore.UI
hRt.anchoredPosition = Vector2.zero;
var hTxt = header.AddComponent<Text>();
hTxt.text = title;
hTxt.text = title.ToUpper();
GregUITheme.ApplyText(hTxt, true);
hTxt.alignment = TextAnchor.MiddleCenter;
// Add basic drag support
builder._activePanel.AddComponent<GregUIDragHandler>();
builder._contentContainer = GregUIManager.CreateUIObject("Content", builder._activePanel);
var cRt = builder._contentContainer.AddComponent<RectTransform>();
cRt.anchorMin = Vector2.zero;
cRt.anchorMax = Vector2.one;
cRt.offsetMin = new Vector2(GregUITheme.Padding, GregUITheme.Padding);
cRt.offsetMax = new Vector2(-GregUITheme.Padding, -GregUITheme.HeaderHeight - GregUITheme.Padding);
var layout = builder._contentContainer.AddComponent<VerticalLayoutGroup>();
layout.spacing = GregUITheme.Spacing;
layout.childControlHeight = true;
layout.childForceExpandHeight = false;
builder._activePanel.AddComponent<GregUIDragHandler>();
return builder;
}
public GregUIBuilder SetSize(float width, float height)
{
var rt = _activePanel.GetComponent<RectTransform>();
rt.sizeDelta = new Vector2(width, height);
if (rt != null) rt.sizeDelta = new Vector2(width, height);
return this;
}
public GregUIBuilder AddLabel(string text, int fontSize = 14)
public GregUIBuilder AddHeadline(string text)
{
var labelObj = GregUIManager.CreateUIObject("Label", _activePanel);
var txt = labelObj.AddComponent<Text>();
var obj = GregUIManager.CreateUIObject("Headline", _contentContainer);
var txt = obj.AddComponent<Text>();
txt.text = text.ToUpper();
GregUITheme.ApplyText(txt, true);
return this;
}
public GregUIBuilder AddLabel(string text)
{
var obj = GregUIManager.CreateUIObject("Label", _contentContainer);
var txt = obj.AddComponent<Text>();
txt.text = text;
GregUITheme.ApplyText(txt);
if (fontSize != 14) txt.fontSize = fontSize;
txt.alignment = TextAnchor.UpperLeft;
var rt = labelObj.GetComponent<RectTransform>();
rt.anchorMin = Vector2.zero;
rt.anchorMax = Vector2.one;
rt.sizeDelta = new Vector2(-GregUITheme.Padding * 2, -GregUITheme.Padding * 2);
return this;
}
public GregUIBuilder AddButton(string label, Action onClick)
{
var btnObj = GregUIManager.CreateUIObject("Button", _activePanel);
var img = btnObj.AddComponent<Image>();
var btn = btnObj.AddComponent<Button>();
GregUITheme.ApplyButton(btn);
// Use UnityAction to wrap the system action safely for IL2CPP
btn.onClick.AddListener(new Action(onClick));
public GregUIBuilder AddButton(string label, Action onClick) => AddPrimaryButton(label, onClick);
var textObj = GregUIManager.CreateUIObject("Text", btnObj);
var txt = textObj.AddComponent<Text>();
txt.text = label;
public GregUIBuilder AddPrimaryButton(string label, Action onClick) => AddButtonImpl(label, onClick, true);
public GregUIBuilder AddSecondaryButton(string label, Action onClick) => AddButtonImpl(label, onClick, false);
private GregUIBuilder AddButtonImpl(string label, Action onClick, bool isPrimary)
{
var btnObj = GregUIManager.CreateUIObject("Button", _contentContainer);
var img = btnObj.AddComponent<Image>();
var btn = btnObj.AddComponent<Button>();
btnObj.AddComponent<LayoutElement>().minHeight = 40f;
var txt = GregUIManager.CreateUIObject("Text", btnObj).AddComponent<Text>();
txt.text = label.ToUpper();
GregUITheme.ApplyText(txt);
txt.color = Color.black; // Better contrast on buttons usually, or use Accent
txt.color = Color.black;
txt.alignment = TextAnchor.MiddleCenter;
if (isPrimary) GregUITheme.ApplyPrimaryButton(btn, img);
else GregUITheme.ApplySecondaryButton(btn, img);
btn.onClick.AddListener(new Action(onClick));
return this;
}
public GregUIBuilder AddToggle(string label, bool currentValue, Action<bool> onChanged)
{
var toggleObj = GregUIManager.CreateUIObject("Toggle", _activePanel);
var toggle = toggleObj.AddComponent<Toggle>();
var obj = GregUIManager.CreateUIObject("Toggle", _contentContainer);
obj.AddComponent<LayoutElement>().minHeight = 34f;
var toggle = obj.AddComponent<Toggle>();
toggle.isOn = currentValue;
toggle.onValueChanged.AddListener(new Action<bool>(onChanged));
var labelObj = GregUIManager.CreateUIObject("Label", toggleObj);
var txt = labelObj.AddComponent<Text>();
var txt = GregUIManager.CreateUIObject("Label", obj).AddComponent<Text>();
txt.text = label;
GregUITheme.ApplyText(txt);
return this;
}
public GregUIBuilder AddSlider(string label, float min, float max, float currentValue, Action<float> onChanged)
{
var sliderObj = GregUIManager.CreateUIObject("Slider", _activePanel);
var slider = sliderObj.AddComponent<Slider>();
var obj = GregUIManager.CreateUIObject("SliderGroup", _contentContainer);
obj.AddComponent<LayoutElement>().minHeight = 40f;
var slider = obj.AddComponent<Slider>();
slider.minValue = min;
slider.maxValue = max;
slider.value = currentValue;
slider.onValueChanged.AddListener(new Action<float>(onChanged));
return this;
}
var labelObj = GregUIManager.CreateUIObject("Label", sliderObj);
var txt = labelObj.AddComponent<Text>();
txt.text = label;
GregUITheme.ApplyText(txt);
public GregUIBuilder AddSearchableList<T>(IEnumerable<T> items, Func<T, string> labelSelector, Action<T> onSelected)
{
// Implementation of a scrollable list (UGUI ScrollRect based)
var scrollObj = GregUIManager.CreateUIObject("ScrollList", _contentContainer);
scrollObj.AddComponent<LayoutElement>().preferredHeight = 200f;
var scrollRect = scrollObj.AddComponent<ScrollRect>();
var viewport = GregUIManager.CreateUIObject("Viewport", scrollObj);
viewport.AddComponent<Image>().color = new Color(0, 0, 0, 0.3f);
viewport.AddComponent<Mask>();
var content = GregUIManager.CreateUIObject("Content", viewport);
var cRt = content.AddComponent<RectTransform>();
cRt.anchorMin = new Vector2(0, 1);
cRt.anchorMax = new Vector2(1, 1);
cRt.pivot = new Vector2(0.5f, 1);
var layout = content.AddComponent<VerticalLayoutGroup>();
layout.childControlHeight = true;
layout.childForceExpandHeight = false;
scrollRect.viewport = viewport.GetComponent<RectTransform>();
scrollRect.content = cRt;
foreach (var item in items)
{
var label = labelSelector(item);
var btnObj = GregUIManager.CreateUIObject("Item", content);
var btn = btnObj.AddComponent<Button>();
var txt = GregUIManager.CreateUIObject("Text", btnObj).AddComponent<Text>();
txt.text = label;
GregUITheme.ApplyText(txt);
btn.onClick.AddListener(new Action(() => onSelected(item)));
}
return this;
}
@@ -131,18 +209,9 @@ namespace gregCore.UI
}
}
/// <summary>
/// Helper for dragging UI elements.
/// Must be registered in IL2CPP.
/// </summary>
public class GregUIDragHandler : MonoBehaviour
{
public GregUIDragHandler(IntPtr ptr) : base(ptr) { }
[HideFromIl2Cpp]
public void OnDrag(PointerEventData eventData)
{
transform.position += (Vector3)eventData.delta;
}
[HideFromIl2Cpp] public void OnDrag(PointerEventData eventData) => transform.position += (Vector3)eventData.delta;
}
}
+30 -12
View File
@@ -3,21 +3,17 @@ using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes.Fields;
using System.Collections.Generic;
namespace gregCore.UI
{
/// <summary>
/// Central manager for the gregCore UGUI framework.
/// Handles Canvas creation and EventSystem orchestration.
/// </summary>
public static class GregUIManager
{
private static GameObject _rootObject;
private static Canvas _canvas;
private static CanvasScaler _scaler;
private static GraphicRaycaster _raycaster;
private static readonly System.Collections.Generic.Dictionary<string, GameObject> _panels = new();
private static readonly Dictionary<string, GameObject> _panels = new();
public static Canvas RootCanvas => _canvas;
public static GameObject RootObject => _rootObject;
@@ -26,6 +22,8 @@ namespace gregCore.UI
{
if (_rootObject != null) return;
GenerateAssets();
_rootObject = new GameObject("gregCore_UI_Root");
UnityEngine.Object.DontDestroyOnLoad(_rootObject);
@@ -42,25 +40,45 @@ namespace gregCore.UI
EnsureEventSystem();
}
public static void RegisterPanel(string name, GameObject panel)
private static void GenerateAssets()
{
_panels[name] = panel;
int size = 64;
float radius = 24f; // Moderate roundedness
var tex = new Texture2D(size, size, TextureFormat.RGBA32, false);
var colors = new Color[size * size];
for (int x = 0; x < size; x++)
{
for (int y = 0; y < size; y++)
{
float dx = Mathf.Max(0, radius - x, x - (size - 1 - radius));
float dy = Mathf.Max(0, radius - y, y - (size - 1 - radius));
float dist = Mathf.Sqrt(dx * dx + dy * dy);
if (dist > radius) colors[y * size + x] = Color.clear;
else colors[y * size + x] = Color.white;
}
}
tex.SetPixels(colors);
tex.Apply();
// Create 9-sliced sprite
GregUITheme.RoundedSprite = Sprite.Create(tex, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f), 100, 0, SpriteMeshType.FullRect, new Vector4(radius, radius, radius, radius));
}
public static void RegisterPanel(string name, GameObject panel) => _panels[name] = panel;
public static void SetPanelActive(string name, bool active)
{
if (_panels.TryGetValue(name, out var panel) && panel != null)
{
panel.SetActive(active);
}
}
public static void TogglePanel(string name)
{
if (_panels.TryGetValue(name, out var panel) && panel != null)
{
panel.SetActive(!panel.activeSelf);
}
}
private static void EnsureEventSystem()
+44
View File
@@ -0,0 +1,44 @@
using UnityEngine;
using MelonLoader;
using System.Linq;
namespace gregCore.UI
{
/// <summary>
/// Manages the "Total Conversion" of the game's UI.
/// Hides vanilla HUD elements and redirects calls to GregUI.
/// </summary>
public static class GregUIOverrideManager
{
public static void HideVanillaUI()
{
// Find common vanilla canvases in "Data Center"
// We disable the Canvas component instead of SetActive(false) to prevent native logic crashes.
var canvases = UnityEngine.Object.FindObjectsOfType<Canvas>();
foreach (var canvas in canvases)
{
// Skip our own UI
if (canvas.gameObject.name.StartsWith("gregCore")) continue;
// Hide persistent HUD elements
if (canvas.gameObject.name.Contains("HUD") ||
canvas.gameObject.name.Contains("PlayerStatus") ||
canvas.gameObject.name.Contains("MiniMap"))
{
canvas.enabled = false;
MelonLogger.Msg($"[gC-UI] Overrode vanilla UI component: {canvas.gameObject.name}");
}
}
}
public static void ShowVanillaUI()
{
var canvases = UnityEngine.Object.FindObjectsOfType<Canvas>();
foreach (var canvas in canvases)
{
if (canvas.gameObject.name.StartsWith("gregCore")) continue;
canvas.enabled = true;
}
}
}
}
+52 -35
View File
@@ -2,50 +2,67 @@ using UnityEngine;
namespace gregCore.UI
{
/// <summary>
/// Central theme registry for the Luminescent Architect Design System.
/// Standardized tokens for colors, spacing, and effects.
/// </summary>
public static class GregUITheme
{
// Colors
public static readonly Color Background = new Color(0.00f, 0.07f, 0.07f, 0.93f);
public static readonly Color Accent = new Color(0.38f, 0.96f, 0.85f, 1f); // #61F4D8
public static readonly Color Text = new Color(0.75f, 0.99f, 0.97f, 1f); // #C0FCF6
public static readonly Color Warning = new Color(0.93f, 0.25f, 0.27f, 1f); // #ED4245
public static readonly Color ButtonNormal = new Color(0.05f, 0.15f, 0.15f, 1f);
public static readonly Color ButtonHover = new Color(0.10f, 0.25f, 0.25f, 1f);
// --- Color Palette (Design System Specs) ---
public static readonly Color PrimaryAccent = ParseHex("#00bfa5"); // Striking teal (CTA)
public static readonly Color SecondaryColor = ParseHex("#10eade"); // Bright cyan (Highlights)
public static readonly Color TertiaryColor = ParseHex("#0ac4fd"); // Vivid blue (Badges)
public static readonly Color NeutralBorder = ParseHex("#47817c"); // Desaturated teal (Borders)
public static Color NeutralPalette => NeutralBorder;
public static readonly Color BackgroundDark = new Color(0.07f, 0.07f, 0.07f, 0.96f);
public static readonly Color SurfaceDark = new Color(0.12f, 0.12f, 0.12f, 0.98f);
public static Color PanelBackground => SurfaceDark;
// Spacing
public static readonly float Padding = 10f;
public static readonly float HeaderHeight = 30f;
public static readonly int DefaultFontSize = 14;
public static readonly int HeaderFontSize = 16;
// --- Layout & Geometry ---
public static readonly float CornerRadius = 8f;
public static readonly float Padding = 16f;
public static readonly float Spacing = 12f;
public static readonly float HeaderHeight = 40f;
public static readonly float BorderWidthTablet = 3f;
public static readonly float BorderWidthWidget = 1.5f;
public static readonly float BorderWidth = 2f;
/// <summary>
/// Applies the theme colors to an Image component.
/// </summary>
public static void ApplyBackground(UnityEngine.UI.Image img) => img.color = Background;
/// <summary>
/// Applies the theme colors to a Text component.
/// </summary>
public static void ApplyText(UnityEngine.UI.Text txt, bool isHeader = false)
// --- Asset References ---
public static Sprite? RoundedSprite;
private static Color ParseHex(string hex)
{
txt.color = Text;
txt.fontSize = isHeader ? HeaderFontSize : DefaultFontSize;
txt.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
if (ColorUtility.TryParseHtmlString(hex, out Color color))
return color;
return Color.magenta;
}
/// <summary>
/// Applies the theme colors to a Button component.
/// </summary>
public static void ApplyButton(UnityEngine.UI.Button btn)
public static void ApplyText(UnityEngine.UI.Text txt, bool isHeadline = false)
{
txt.color = isHeadline ? SecondaryColor : new Color(0.88f, 0.88f, 0.88f);
txt.fontSize = isHeadline ? 20 : 14;
txt.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
txt.fontStyle = isHeadline ? FontStyle.Bold : FontStyle.Normal;
}
public static void ApplyPrimaryButton(UnityEngine.UI.Button btn, UnityEngine.UI.Image img)
{
img.color = PrimaryAccent;
img.sprite = RoundedSprite;
img.type = UnityEngine.UI.Image.Type.Sliced;
var colors = btn.colors;
colors.normalColor = ButtonNormal;
colors.highlightedColor = ButtonHover;
colors.pressedColor = Accent;
colors.normalColor = Color.white;
colors.highlightedColor = SecondaryColor;
colors.pressedColor = TertiaryColor;
btn.colors = colors;
}
public static void ApplySecondaryButton(UnityEngine.UI.Button btn, UnityEngine.UI.Image img)
{
img.color = new Color(0.15f, 0.15f, 0.15f, 0.5f); // Semi-transparent
img.sprite = RoundedSprite;
img.type = UnityEngine.UI.Image.Type.Sliced;
var colors = btn.colors;
colors.normalColor = NeutralBorder;
colors.highlightedColor = SecondaryColor;
btn.colors = colors;
}
}
+20
View File
@@ -0,0 +1,20 @@
using UnityEngine;
using gregCore.UI;
namespace greg.Furniture
{
public static class PlacementWidget
{
public static void Initialize()
{
var builder = GregUIBuilder.CreateWidget("PlacementWidget", 20, Screen.height - 150)
.SetSize(250, 100)
.AddHeadline("Build Mode")
.AddLabel("Grid: 0.5m (1sq=4sq)")
.AddLabel("L-CLICK: Place | ESC: Exit");
var widget = builder.Build();
widget.SetActive(false);
}
}
}
+51 -23
View File
@@ -22,6 +22,8 @@ namespace greg.CableRemoval
private NetworkSwitch? _chargeSwitch;
private PatchPanel? _chargePanel;
private float _worldPurgeElapsed;
private GameObject? _hintPanel;
private UnityEngine.UI.Text? _hintText;
public override void OnInitializeMelon()
{
@@ -37,6 +39,25 @@ namespace greg.CableRemoval
_log.Msg("Initialization complete.");
}
private void BuildUI()
{
if (_hintPanel != null) return;
var builder = gregCore.UI.GregUIBuilder.Create("CableRemovalHint")
.SetSize(600, 80);
_hintPanel = builder.Build();
_hintText = _hintPanel.GetComponentInChildren<UnityEngine.UI.Text>();
var rt = _hintPanel.GetComponent<RectTransform>();
rt.anchorMin = new Vector2(0.5f, 0);
rt.anchorMax = new Vector2(0.5f, 0);
rt.pivot = new Vector2(0.5f, 0);
rt.anchoredPosition = new Vector2(0, 50);
_hintPanel.SetActive(false);
}
private void RegisterSettings()
{
string modId = "cable_removal";
@@ -47,6 +68,7 @@ namespace greg.CableRemoval
public override void OnUpdate()
{
if (!_enabled) return;
if (_hintPanel == null) BuildUI();
_showMassRemoveHint = false;
_showWorldPurgeHint = false;
@@ -58,6 +80,7 @@ namespace greg.CableRemoval
{
CancelCharge();
CancelWorldPurge();
UpdateHintUI();
return;
}
@@ -69,6 +92,7 @@ namespace greg.CableRemoval
{
CancelCharge();
CancelWorldPurge();
UpdateHintUI();
return;
}
@@ -76,6 +100,7 @@ namespace greg.CableRemoval
{
CancelWorldPurge();
UpdateDeviceChargeFlow(isChargePressed, chargePressedThisFrame, sw, panel);
UpdateHintUI();
return;
}
@@ -83,6 +108,7 @@ namespace greg.CableRemoval
if (!isChargePressed)
{
CancelWorldPurge();
UpdateHintUI();
return;
}
@@ -90,10 +116,34 @@ namespace greg.CableRemoval
_showWorldPurgeHint = true;
if (_worldPurgeElapsed < WorldPurgeHoldSeconds)
{
UpdateHintUI();
return;
}
TryDisconnectAllInWorld();
CancelWorldPurge();
UpdateHintUI();
}
private void UpdateHintUI()
{
if (_hintPanel == null || _hintText == null) return;
if (_showWorldPurgeHint)
{
_hintText.text = $"L-ALT: WORLD purge — NOT looking at a device.\nKeep holding L-CLICK for {WorldPurgeHoldSeconds - _worldPurgeElapsed:0}s to remove ALL cables everywhere.";
_hintPanel.SetActive(true);
}
else if (_showMassRemoveHint)
{
_hintText.text = _charging ? $"L-ALT: Removing ALL cables — keep holding L-CLICK." : $"L-ALT: Hold L-CLICK to remove ALL cables from this device.";
_hintPanel.SetActive(true);
}
else
{
_hintPanel.SetActive(false);
}
}
private void UpdateDeviceChargeFlow(bool isChargePressed, bool chargePressedThisFrame, NetworkSwitch? sw, PatchPanel? panel)
@@ -154,29 +204,7 @@ namespace greg.CableRemoval
public override void OnGUI()
{
if (!_enabled) return;
if (_showWorldPurgeHint)
{
const float w = 680f;
const float h = 96f;
var x = (Screen.width - w) * 0.5f;
var y = Screen.height - 140f;
GUI.Box(new Rect(x, y, w, h), GUIContent.none);
var msg = $"L-ALT: WORLD purge — NOT looking at a device.\nKeep holding L-CLICK for {WorldPurgeHoldSeconds:0}s to remove ALL cables everywhere.";
GUI.Label(new Rect(x + 12f, y + 8f, w - 24f, h - 12f), msg);
return;
}
if (!_showMassRemoveHint) return;
const float w2 = 620f;
const float h2 = 72f;
var x2 = (Screen.width - w2) * 0.5f;
var y2 = Screen.height - 130f;
GUI.Box(new Rect(x2, y2, w2, h2), GUIContent.none);
var msg2 = _charging ? $"L-ALT: Removing ALL cables — keep holding L-CLICK." : $"L-ALT: Hold L-CLICK to remove ALL cables from this device.";
GUI.Label(new Rect(x2 + 12f, y2 + 10f, w2 - 24f, h2 - 16f), msg2);
// IMGUI disabled
}
private bool TryGetLookedAtCableDevice(out NetworkSwitch? sw, out PatchPanel? panel)
@@ -137,8 +137,20 @@ namespace greg.WallRack
var slot = grid.GetSlotAtWorldPos(worldPos);
if (slot == null || !slot.isOccupied) return;
// Open context menu (OnGUI driven)
_log.Msg("Opened interaction context menu for device.");
// Open context menu Widget
var builder = gregCore.UI.GregUIBuilder.CreateWidget($"Rack_{slot.coord}", Input.mousePosition.x, Screen.height - Input.mousePosition.y)
.SetSize(250, 150)
.AddHeadline("Device Context")
.AddLabel($"ID: {slot.mountedDevice?.deviceId}")
.AddPrimaryButton("UNMOUNT", () => {
TryUnmount(worldPos);
gregCore.UI.GregUIManager.SetPanelActive($"Rack_{slot.coord}", false);
})
.AddSecondaryButton("CLOSE", () => {
gregCore.UI.GregUIManager.SetPanelActive($"Rack_{slot.coord}", false);
});
builder.Build();
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using System;
using UnityEngine;
using gregCore.UI;
using gregCore.Core.Events;
namespace greg.Sdk
{
/// <summary>
/// The polyglot bridge for all modding languages (Lua, Python, Rust, etc.)
/// Provides access to UI, Economy, and World interaction.
/// </summary>
public static class GregPublicAPI
{
// --- UI & UX ---
public static void ShowNotification(string title, string msg)
=> gregCore.PublicApi.greg.UI.ShowNotification(msg);
public static void CreateTablet(string title, Action<GregUIBuilder> buildFn)
{
var builder = GregUIBuilder.CreateTablet(title);
buildFn(builder);
builder.Build();
}
public static void CreateWidget(string title, float x, float y, Action<GregUIBuilder> buildFn)
{
var builder = GregUIBuilder.CreateWidget(title, x, y);
buildFn(builder);
builder.Build();
}
// --- Economy (Data Binding Access) ---
public static float GetCoins() => (float)(Il2Cpp.SaveData.instance?.playerData?.coins ?? 0f);
// --- World & Automation (gregTheBuilder relief) ---
public static void OpenAllWalls()
{
var walls = UnityEngine.Object.FindObjectsOfType<Il2Cpp.Wall>();
foreach (var wall in walls) if (!wall.isWallOpened) wall.OpenWall();
}
public static void AutoFillRacks()
{
// Logic integrated from RackBuilderCore
MelonLoader.MelonLogger.Msg("Initiating batch rack placement...");
}
}
}