OSGD面渲染+窗口逻辑增强

This commit is contained in:
2026-04-04 13:38:51 +08:00
parent 636f3f146d
commit 2f9df41666
7 changed files with 203 additions and 10 deletions

View File

@@ -1 +1 @@
2026-04-04 12:15:03 2026-04-04 13:32:14

View File

@@ -1 +1 @@
836f199 636f3f1

View File

@@ -40,6 +40,14 @@ namespace CMLeonOS.Gui.Apps.Demos
Renderer3D.DrawLine3D(window, a, b, color, FovScale, CameraDistance); Renderer3D.DrawLine3D(window, a, b, color, FovScale, CameraDistance);
} }
private void Draw3DTriangle(Vec3 a, Vec3 b, Vec3 c, Color color)
{
a = TransformPoint(a);
b = TransformPoint(b);
c = TransformPoint(c);
Renderer3D.DrawTriangle3D(window, a, b, c, color, FovScale, CameraDistance);
}
private void DrawGear(Vec3 center, double outerRadius, double innerRadius, double depth, int teeth, double angle, Color color) private void DrawGear(Vec3 center, double outerRadius, double innerRadius, double depth, int teeth, double angle, Color color)
{ {
int ringCount = teeth * 2; int ringCount = teeth * 2;
@@ -70,6 +78,35 @@ namespace CMLeonOS.Gui.Apps.Demos
{ {
int n = (i + 1) % ringCount; int n = (i + 1) % ringCount;
Color frontFace = Color.FromArgb(
color.R,
color.G,
color.B);
Color backFace = Color.FromArgb(
Math.Max(0, color.R - 32),
Math.Max(0, color.G - 32),
Math.Max(0, color.B - 32));
Color sideFace = Color.FromArgb(
Math.Max(0, color.R - 18),
Math.Max(0, color.G - 18),
Math.Max(0, color.B - 18));
// Front ring face (quad -> 2 triangles)
Draw3DTriangle(frontOuter[i], frontOuter[n], frontInner[n], frontFace);
Draw3DTriangle(frontOuter[i], frontInner[n], frontInner[i], frontFace);
// Back ring face
Draw3DTriangle(backOuter[i], backInner[n], backOuter[n], backFace);
Draw3DTriangle(backOuter[i], backInner[i], backInner[n], backFace);
// Outer wall
Draw3DTriangle(frontOuter[i], backOuter[n], frontOuter[n], sideFace);
Draw3DTriangle(frontOuter[i], backOuter[i], backOuter[n], sideFace);
// Inner wall
Draw3DTriangle(frontInner[i], frontInner[n], backInner[n], sideFace);
Draw3DTriangle(frontInner[i], backInner[n], backInner[i], sideFace);
Draw3DLine(frontOuter[i], frontOuter[n], color); Draw3DLine(frontOuter[i], frontOuter[n], color);
Draw3DLine(backOuter[i], backOuter[n], color); Draw3DLine(backOuter[i], backOuter[n], color);
Draw3DLine(frontOuter[i], backOuter[i], color); Draw3DLine(frontOuter[i], backOuter[i], color);

View File

@@ -32,7 +32,7 @@ namespace CMLeonOS.Gui.ShellComponents.Dock
internal override void Clicked() internal override void Clicked()
{ {
ProcessManager.GetProcess<WindowManager>().Focus = AppWindow; ProcessManager.GetProcess<WindowManager>().BringToFrontAndFocus(AppWindow);
} }
} }
} }

View File

@@ -49,6 +49,9 @@ namespace CMLeonOS.Gui.ShellComponents.Dock
internal static readonly int IconSize = 64; internal static readonly int IconSize = 64;
internal static readonly int IconImageMaxSize = 48; internal static readonly int IconImageMaxSize = 48;
private static readonly Color DockBackground = Color.FromArgb(211, 211, 211);
private static readonly Color ActiveIconBackground = Color.FromArgb(160, 190, 255);
private static readonly Color ActiveIndicator = Color.FromArgb(36, 88, 196);
private void Render() private void Render()
{ {
@@ -63,11 +66,22 @@ namespace CMLeonOS.Gui.ShellComponents.Dock
window.MoveAndResize((int)(wm.ScreenWidth / 2 - newDockWidth / 2), window.Y, newDockWidth, window.Height); window.MoveAndResize((int)(wm.ScreenWidth / 2 - newDockWidth / 2), window.Y, newDockWidth, window.Height);
} }
window.Clear(Color.FromArgb(211, 211, 211)); window.Clear(DockBackground);
AppWindow focusedApp = wm.GetOwningAppWindow(wm.Focus);
int x = 0; int x = 0;
foreach (var icon in Icons) foreach (var icon in Icons)
{ {
int iconWidth = (int)icon.Size;
bool isSelected = icon is AppDockIcon appDockIcon && appDockIcon.AppWindow == focusedApp;
if (isSelected && iconWidth > 4 && window.Height > 4)
{
window.DrawFilledRectangle(x + 2, 2, iconWidth - 4, window.Height - 4, ActiveIconBackground);
window.DrawFilledRectangle(x + 10, window.Height - 5, Math.Max(8, iconWidth - 20), 3, ActiveIndicator);
}
if (icon.Image != null) if (icon.Image != null)
{ {
Bitmap resizedImage = icon.Image.ResizeWidthKeepRatio((uint)Math.Min(IconImageMaxSize, icon.Size)); Bitmap resizedImage = icon.Image.ResizeWidthKeepRatio((uint)Math.Min(IconImageMaxSize, icon.Size));
@@ -76,7 +90,7 @@ namespace CMLeonOS.Gui.ShellComponents.Dock
window.DrawImageAlpha(resizedImage, imageX, (int)((window.Height / 2) - (resizedImage.Height / 2))); window.DrawImageAlpha(resizedImage, imageX, (int)((window.Height / 2) - (resizedImage.Height / 2)));
} }
x += (int)icon.Size; x += iconWidth;
} }
wm.Update(window); wm.Update(window);

View File

@@ -18,6 +18,7 @@ using Cosmos.System;
using Cosmos.System.Graphics; using Cosmos.System.Graphics;
using CMLeonOS; using CMLeonOS;
using CMLeonOS.Gui.ShellComponents; using CMLeonOS.Gui.ShellComponents;
using CMLeonOS.Gui.UILib;
using CMLeonOS.Settings; using CMLeonOS.Settings;
using CMLeonOS.Driver; using CMLeonOS.Driver;
using CMLeonOS.Logger; using CMLeonOS.Logger;
@@ -193,6 +194,95 @@ namespace CMLeonOS.Gui
UpdateDock(); UpdateDock();
} }
private bool IsDescendantOf(Window window, Window ancestor)
{
Window current = window;
while (current != null)
{
if (current == ancestor)
{
return true;
}
current = current.RelativeTo;
}
return false;
}
internal AppWindow GetOwningAppWindow(Window window)
{
Window current = window;
while (current != null)
{
if (current is AppWindow appWindow)
{
return appWindow;
}
current = current.RelativeTo;
}
return null;
}
internal void SetFocus(Window window, bool updateDock = true)
{
if (window == null || !Windows.Contains(window))
{
return;
}
if (Focus != null && Focus != window)
{
Focus.OnUnfocused?.Invoke();
}
Focus = window;
window.OnFocused?.Invoke();
if (updateDock)
{
UpdateDock();
}
}
internal void BringToFrontAndFocus(Window window)
{
if (window == null || !Windows.Contains(window))
{
return;
}
List<Window> toMove = new List<Window>();
for (int i = 0; i < Windows.Count; i++)
{
Window current = Windows[i];
if (current == window || IsDescendantOf(current, window))
{
toMove.Add(current);
}
}
if (toMove.Count > 0)
{
for (int i = 0; i < toMove.Count; i++)
{
Windows.Remove(toMove[i]);
}
for (int i = 0; i < toMove.Count; i++)
{
Windows.Add(toMove[i]);
}
}
SetFocus(window, updateDock: false);
RerenderAll();
UpdateDock();
}
internal void RemoveWindow(Window window, bool rerender = true) internal void RemoveWindow(Window window, bool rerender = true)
{ {
Windows.Remove(window); Windows.Remove(window);
@@ -292,13 +382,12 @@ namespace CMLeonOS.Gui
else if (MouseManager.MouseState == MouseState.None && lastMouseState == MouseState.Left) else if (MouseManager.MouseState == MouseState.None && lastMouseState == MouseState.Left)
{ {
lastMouseState = MouseManager.MouseState; lastMouseState = MouseManager.MouseState;
Window focusTarget = GetOwningAppWindow(window) ?? window;
if (Focus != null && Focus != window) BringToFrontAndFocus(focusTarget);
if (window != focusTarget && Windows.Contains(window))
{ {
Focus.OnUnfocused?.Invoke(); SetFocus(window);
} }
Focus = window;
window.OnFocused?.Invoke();
window.OnClick?.Invoke(relativeX, relativeY); window.OnClick?.Invoke(relativeX, relativeY);

View File

@@ -34,5 +34,58 @@ namespace CMLeonOS.OSGraphicDraw
target.DrawLine(ax, ay, bx, by, color); target.DrawLine(ax, ay, bx, by, color);
} }
private static void DrawScanline(Window target, int x1, int x2, int y, Color color)
{
if (y < 0 || y >= target.Height) return;
if (x1 > x2)
{
int t = x1;
x1 = x2;
x2 = t;
}
if (x2 < 0 || x1 >= target.Width) return;
if (x1 < 0) x1 = 0;
if (x2 >= target.Width) x2 = target.Width - 1;
target.DrawHorizontalLine((x2 - x1) + 1, x1, y, color);
}
private static void DrawTriangle2D(Window target, int x1, int y1, int x2, int y2, int x3, int y3, Color color)
{
if (y1 > y2) { int tx = x1; int ty = y1; x1 = x2; y1 = y2; x2 = tx; y2 = ty; }
if (y1 > y3) { int tx = x1; int ty = y1; x1 = x3; y1 = y3; x3 = tx; y3 = ty; }
if (y2 > y3) { int tx = x2; int ty = y2; x2 = x3; y2 = y3; x3 = tx; y3 = ty; }
if (y1 == y3) return;
for (int y = y1; y <= y3; y++)
{
bool lowerHalf = y > y2 || y2 == y1;
int segmentHeight = lowerHalf ? (y3 - y2) : (y2 - y1);
if (segmentHeight == 0) continue;
double alpha = (double)(y - y1) / (y3 - y1);
double beta = lowerHalf
? (double)(y - y2) / segmentHeight
: (double)(y - y1) / segmentHeight;
int ax = x1 + (int)((x3 - x1) * alpha);
int bx = lowerHalf
? x2 + (int)((x3 - x2) * beta)
: x1 + (int)((x2 - x1) * beta);
DrawScanline(target, ax, bx, y, color);
}
}
internal static void DrawTriangle3D(Window target, Vec3 a, Vec3 b, Vec3 c, Color color, double fovScale, double cameraDistance)
{
if (!Project(a, target.Width, target.Height, fovScale, cameraDistance, out int ax, out int ay)) return;
if (!Project(b, target.Width, target.Height, fovScale, cameraDistance, out int bx, out int by)) return;
if (!Project(c, target.Width, target.Height, fovScale, cameraDistance, out int cx, out int cy)) return;
DrawTriangle2D(target, ax, ay, bx, by, cx, cy, color);
}
} }
} }