Make the screen window look sane even when it's ridiculously small

This commit is contained in:
Fingercomp 2025-07-31 22:51:14 +03:00
parent 182d42a843
commit 04550de173
No known key found for this signature in database
GPG Key ID: BBC71CEE45D86E37
27 changed files with 196 additions and 86 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

View File

@ -47,6 +47,8 @@ ComputerAddress = #333333
ScreenOff = #000000
WindowBackground = #c6c6c6
StatusBar = #181818
StatusBarActive = #ffffff04
StatusBarBorder = #222222

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

@ -11,7 +11,7 @@ ShadowBorder 201 540 1 24
ShadowCorner 233 674 24 24
TabArrow 225 600 8 14
blocks/Generic 151 618 16 16
blocks/HologramEffect 209 549 4 4
blocks/HologramEffect 213 540 4 4
blocks/HologramProjector1Top 168 618 16 16
blocks/HologramProjector2Top 185 618 16 16
blocks/HologramProjectorSide 202 618 16 16
@ -174,15 +174,15 @@ items/WirelessNetworkCard0 1001 635 16 16
items/WirelessNetworkCard1 358 674 16 16
light-panel/BookmarkLeft 882 707 18 14
light-panel/BookmarkRight 188 600 20 14
light-panel/BorderB 214 549 4 4
light-panel/BorderL 304 549 4 2
light-panel/BorderR 219 549 4 4
light-panel/BorderT 224 549 4 4
light-panel/CornerBL 229 549 4 4
light-panel/CornerBR 234 549 4 4
light-panel/CornerTL 239 549 4 4
light-panel/CornerTR 244 549 4 4
light-panel/Fill 207 560 2 2
light-panel/BorderB 218 540 4 4
light-panel/BorderL 206 549 4 2
light-panel/BorderR 223 540 4 4
light-panel/BorderT 228 540 4 4
light-panel/CornerBL 233 540 4 4
light-panel/CornerBR 238 540 4 4
light-panel/CornerTL 243 540 4 4
light-panel/CornerTR 248 540 4 4
light-panel/Fill 332 540 2 2
light-panel/Vent 356 434 2 38
nodes/Cable 377 445 8 8
nodes/Camera 375 674 16 16
@ -273,49 +273,54 @@ nodes/screen/Standalone 814 707 16 16
nodes/screen/TopLeft 831 707 16 16
nodes/screen/TopMiddle 848 707 16 16
nodes/screen/TopRight 865 707 16 16
panel/BorderB 249 549 4 4
panel/BorderL 309 549 4 2
panel/BorderR 254 549 4 4
panel/BorderT 259 549 4 4
panel/CornerBL 264 549 4 4
panel/CornerBR 269 549 4 4
panel/CornerTL 274 549 4 4
panel/CornerTR 279 549 4 4
panel/Fill 210 560 2 2
panel/BorderB 253 540 4 4
panel/BorderL 211 549 4 2
panel/BorderR 258 540 4 4
panel/BorderT 263 540 4 4
panel/CornerBL 268 540 4 4
panel/CornerBR 273 540 4 4
panel/CornerTL 278 540 4 4
panel/CornerTR 283 540 4 4
panel/Fill 335 540 2 2
particles/Note 377 434 7 10
screen/BorderB 206 549 2 8
screen/BorderT 203 549 2 10
screen/CornerBL 386 445 8 8
screen/CornerBR 395 445 8 8
screen/CornerTL 359 434 8 10
screen/CornerTR 368 434 8 10
window/BorderDark 203 560 1 4
window/BorderLight 205 560 1 4
window/CornerBL 284 549 4 4
window/CornerBR 289 549 4 4
window/CornerTL 294 549 4 4
window/CornerTR 299 549 4 4
screen/InnerBorderB 203 556 2 4
screen/InnerBorderT 206 556 2 4
screen/InnerCornerBL 288 540 4 4
screen/InnerCornerBR 293 540 4 4
screen/InnerCornerTL 298 540 4 4
screen/InnerCornerTR 303 540 4 4
screen/OuterBorderT 203 549 2 6
screen/OuterCornerBL 386 445 8 8
screen/OuterCornerBR 395 445 8 8
screen/OuterCornerTL 359 434 8 10
screen/OuterCornerTR 368 434 8 10
window/BorderDark 328 540 1 4
window/BorderLight 330 540 1 4
window/CornerBL 308 540 4 4
window/CornerBR 313 540 4 4
window/CornerTL 318 540 4 4
window/CornerTR 323 540 4 4
window/OpenFMRadio 474 0 232 105
window/case/Motherboard 123 434 79 70
window/rack/Lines 49 434 73 91
window/rack/Motherboard 178 305 100 78
window/rack/NetworkBack 221 554 1 2
window/rack/NetworkBottom 223 554 1 2
window/rack/NetworkConnector 225 554 1 2
window/rack/NetworkLeft 227 554 1 2
window/rack/NetworkRight 229 554 1 2
window/rack/NetworkTop 231 554 1 2
window/rack/NodeBack 314 549 5 1
window/rack/NodeBottom 320 549 5 1
window/rack/NodeLeft 326 549 5 1
window/rack/NodeRight 332 549 5 1
window/rack/NodeTop 338 549 5 1
window/rack/SideBack 209 554 1 3
window/rack/SideBottom 211 554 1 3
window/rack/SideConnector 213 554 1 3
window/rack/SideLeft 215 554 1 3
window/rack/SideRight 217 554 1 3
window/rack/SideTop 219 554 1 3
window/rack/NetworkBack 215 561 1 2
window/rack/NetworkBottom 217 561 1 2
window/rack/NetworkConnector 219 561 1 2
window/rack/NetworkLeft 221 561 1 2
window/rack/NetworkRight 223 561 1 2
window/rack/NetworkTop 225 561 1 2
window/rack/NodeBack 209 556 5 1
window/rack/NodeBottom 215 556 5 1
window/rack/NodeLeft 221 556 5 1
window/rack/NodeRight 227 556 5 1
window/rack/NodeTop 233 556 5 1
window/rack/SideBack 203 561 1 3
window/rack/SideBottom 205 561 1 3
window/rack/SideConnector 207 561 1 3
window/rack/SideLeft 209 561 1 3
window/rack/SideRight 211 561 1 3
window/rack/SideTop 213 561 1 3
window/raid/Slots 134 540 66 26
window/tape/Back 332 567 20 15
window/tape/BackPressed 353 567 20 15

View File

@ -24,7 +24,7 @@ object Transform2D {
Transform2D.translate(-1f, 1f) >> Transform2D.scale(2f / width, -2f / height)
def rotate(angle: Float): Transform2D = {
val (s, c) = (math.sin(angle).asInstanceOf[Float], math.cos(angle).asInstanceOf[Float])
val (s, c) = (math.sin(angle).toFloat, math.cos(angle).toFloat)
// format: off
Transform2D(

View File

@ -334,4 +334,23 @@ object IconSource {
val Floppy: IconSource = IconSource(s"$prefix/Floppy")
}
object Screen {
protected val prefix: String = "screen"
val InnerCornerTL: IconSource = IconSource(s"$prefix/InnerCornerTL")
val InnerCornerTR: IconSource = IconSource(s"$prefix/InnerCornerTR")
val InnerCornerBL: IconSource = IconSource(s"$prefix/InnerCornerBL")
val InnerCornerBR: IconSource = IconSource(s"$prefix/InnerCornerBR")
val OuterCornerTL: IconSource = IconSource(s"$prefix/OuterCornerTL")
val OuterCornerTR: IconSource = IconSource(s"$prefix/OuterCornerTR")
val OuterCornerBL: IconSource = IconSource(s"$prefix/OuterCornerBL")
val OuterCornerBR: IconSource = IconSource(s"$prefix/OuterCornerBR")
val InnerBorderT: IconSource = IconSource(s"$prefix/InnerBorderT")
val OuterBorderT: IconSource = IconSource(s"$prefix/OuterBorderT")
val InnerBorderB: IconSource = IconSource(s"$prefix/InnerBorderB")
}
}

View File

@ -4,12 +4,16 @@ import ocelot.desktop.geometry.Size2D
import ocelot.desktop.ui.widget.Widget
import ocelot.desktop.util.Orientation
class LinearLayout(widget: Widget,
import scala.collection.immutable.ArraySeq
class LinearLayout(
widget: Widget,
orientation: Orientation.Value = Orientation.Horizontal,
justifyContent: JustifyContent.Value = JustifyContent.Start,
alignItems: AlignItems.Value = AlignItems.Stretch,
gap: Float = 0f)
extends Layout(widget) {
gap: Float = 0f,
) extends Layout(widget) {
override def recalculateBounds(): Unit = {
super.recalculateBounds()
@ -138,7 +142,12 @@ class LinearLayout(widget: Widget,
pos += child.size.width + gap
}
(orientation, alignItems) match {
val align = (child match {
case w: LinearLayout.WithOptions => w.align
case _ => None
}).getOrElse(alignItems)
(orientation, align) match {
case (Orientation.Vertical, AlignItems.Start)
| (Orientation.Vertical, AlignItems.Stretch) =>
child.rawSetPosition(child.position.setX(widget.position.x))
@ -160,3 +169,17 @@ class LinearLayout(widget: Widget,
}
}
}
object LinearLayout {
class WithOptions(widget: Widget, val align: Option[AlignItems.Value]) extends Widget {
override protected val layout: Layout = new CopyLayout(this)
children = ArraySeq(widget)
}
object WithOptions {
def apply(
align: Option[AlignItems.Value] = None,
)(widget: Widget) = new WithOptions(widget, align)
}
}

View File

@ -53,11 +53,9 @@ trait BasicWindow extends Window {
}
}
protected def borderRenderer: DrawUtils.BorderRenderer = DrawUtils.windowBorder
override def draw(g: Graphics): Unit = {
beginDraw(g)
DrawUtils.windowWithShadow(g, position.x, position.y, size.width, size.height, 1f, 0.5f, borderRenderer)
DrawUtils.windowWithShadow(g, position.x, position.y, size.width, size.height, 1f, 0.5f)
drawChildren(g)
endDraw(g)
}

View File

@ -18,6 +18,7 @@ trait PanelWindow extends BasicWindow {
inner: Widget,
padding: Padding2D = Padding2D(bottom = 13, left = 12, right = 12),
titlePadding: Padding2D = Padding2D(top = 8, left = 12, right = 12, bottom = 2),
contentFactory: (Widget, Padding2D) => Widget = new PaddingBox(_, _),
): Unit = {
children = ArraySeq.empty
@ -29,6 +30,6 @@ trait PanelWindow extends BasicWindow {
titlePadding,
)
children :+= new PaddingBox(inner, padding)
children :+= contentFactory(inner, padding)
}
}

View File

@ -1,7 +1,8 @@
package ocelot.desktop.util
import ocelot.desktop.ColorScheme
import ocelot.desktop.color.{Color, RGBAColor, RGBAColorNorm}
import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.geometry.{Rect2D, Vector2D}
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.graphics.IconSource.{DiskActivityIconSource, NetworkActivityIconSource, PowerIconSource}
import ocelot.desktop.node.Node.NoHighlightSize
@ -11,30 +12,82 @@ import totoro.ocelot.brain.entity.traits.{DiskActivityAware, NetworkActivityAwar
object DrawUtils {
def screenBorder(
g: Graphics,
x: Float,
y: Float,
w: Float,
h: Float,
outer: Rect2D,
inner: Rect2D,
color: Color = RGBAColor(255, 255, 255),
): Unit = {
g.sprite("screen/CornerTL", x, y, 16, 20, color)
g.sprite("screen/CornerTR", x + w - 16, y, 16, 20, color)
g.sprite("screen/CornerBL", x, y + h - 16, 16, 16, color)
g.sprite("screen/CornerBR", x + w - 16, y + h - 16, 16, 16, color)
val thicknessOuterTop = 12
val thickness = 8
val top = thickness + thicknessOuterTop
val side = 2 * thickness
val horizontal = 2 * side
val vertical = top + side
g.sprite("screen/BorderT", x + 16, y, w - 16 - 16, 20, color)
g.sprite("screen/BorderB", x + 16, y + h - 16, w - 16 - 16, 16, color)
val rightBorderX = outer.max.x - side
val bottomBorderY = outer.max.y - side
// filler (only visible if the screen view is too small).
g.rect(
outer.x + thickness,
outer.y + thicknessOuterTop,
outer.w - 2 * thickness,
outer.h - thickness - thicknessOuterTop,
ColorScheme("WindowBackground").withAlpha(color.toRGBANorm.a),
)
// inner border: corners.
g.sprite(IconSource.Screen.InnerCornerTL, inner.x - thickness, inner.y - thickness, thickness, thickness, color)
g.sprite(IconSource.Screen.InnerCornerTR, inner.max.x, inner.y - thickness, thickness, thickness, color)
g.sprite(IconSource.Screen.InnerCornerBL, inner.x - thickness, inner.max.y, thickness, thickness, color)
g.sprite(IconSource.Screen.InnerCornerBR, inner.max.x, inner.max.y, thickness, thickness, color)
// inner border: top and bottom.
g.sprite(IconSource.Screen.InnerBorderT, inner.x, inner.y - thickness, inner.w, thickness, color)
g.sprite(IconSource.Screen.InnerBorderB, inner.x, inner.max.y, inner.w, thickness, color)
// inner border: left.
g.save()
g.translate(x, y - 16)
g.translate(inner.x - thickness, inner.y)
g.rotate(270.toRadians)
g.sprite("screen/BorderB", -h, 0, h - 20 - 16, 16, color)
g.sprite(IconSource.Screen.InnerBorderT, -inner.h, 0, inner.h, thickness, color)
g.restore()
// inner border: right.
g.save()
g.translate(x + w - 16, y - 16)
g.translate(inner.max.x, inner.y)
g.rotate(270.toRadians)
g.sprite("screen/BorderB", -h, 0, h - 20 - 16, 16, color)
g.sprite(IconSource.Screen.InnerBorderB, -inner.h, 0, inner.h, thickness, color)
g.restore()
// outer border: corners.
g.sprite(IconSource.Screen.OuterCornerTL, outer.x, outer.y, side, top, color)
g.sprite(IconSource.Screen.OuterCornerTR, rightBorderX, outer.y, side, top, color)
g.sprite(IconSource.Screen.OuterCornerBL, outer.x, bottomBorderY, side, side, color)
g.sprite(IconSource.Screen.OuterCornerBR, rightBorderX, bottomBorderY, side, side, color)
// outer border: top and bottom.
g.sprite(IconSource.Screen.OuterBorderT, outer.x + side, outer.y, outer.w - horizontal, thicknessOuterTop, color)
g.sprite(
IconSource.Screen.InnerBorderT,
outer.x + side,
outer.max.y - thickness,
outer.w - horizontal,
thickness,
color,
)
// outer border: left.
g.save()
g.translate(outer.x, outer.y + top)
g.rotate(270.toRadians)
g.sprite(IconSource.Screen.InnerBorderB, -outer.h + vertical, 0, outer.h - vertical, thickness, color)
g.restore()
// outer border: right.
g.save()
g.translate(outer.max.x - thickness, outer.y + top)
g.rotate(270.toRadians)
g.sprite(IconSource.Screen.InnerBorderT, -outer.h + vertical, 0, outer.h - vertical, thickness, color)
g.restore()
}
@ -105,10 +158,9 @@ object DrawUtils {
h: Float,
backgroundAlpha: Float,
shadowAlpha: Float,
borderRenderer: BorderRenderer = windowBorder
): Unit = {
DrawUtils.shadow(g, x - 8, y - 8, w + 16, h + 20, shadowAlpha)
borderRenderer(g, x, y, w, h, RGBAColorNorm(1, 1, 1, backgroundAlpha))
DrawUtils.windowBorder(g, x, y, w, h, RGBAColorNorm(1, 1, 1, backgroundAlpha))
}
def ring(

View File

@ -1,14 +1,16 @@
package ocelot.desktop.windows
import ocelot.desktop.color.RGBAColorNorm
import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D, Vector2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.node.nodes.ScreenNode
import ocelot.desktop.node.nodes.ScreenNode.{FontHeight, FontWidth}
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{DragEvent, MouseEvent}
import ocelot.desktop.ui.widget.ScreenView
import ocelot.desktop.ui.layout.{AlignItems, LinearLayout}
import ocelot.desktop.ui.widget.window.PanelWindow
import ocelot.desktop.util.DrawUtils.BorderRenderer
import ocelot.desktop.ui.widget.{PaddingBox, ScreenView}
import ocelot.desktop.util.{DrawUtils, Logging}
import ocelot.desktop.windows.ScreenWindow._
import totoro.ocelot.brain.nbt.NBTTagCompound
@ -47,6 +49,8 @@ class ScreenWindow(screenNode: ScreenNode) extends PanelWindow with Logging {
bottom = 2,
left = BorderLeft - 4,
),
contentFactory =
(inner, padding) => LinearLayout.WithOptions(align = Some(AlignItems.Center))(new PaddingBox(inner, padding)),
)
eventHandlers += {
@ -148,15 +152,21 @@ class ScreenWindow(screenNode: ScreenNode) extends PanelWindow with Logging {
}
}
override protected def borderRenderer: BorderRenderer = DrawUtils.screenBorder
override def draw(g: Graphics): Unit = {
beginDraw(g)
DrawUtils.shadow(g, position.x - 8, position.y - 8, size.width + 16, size.height + 20, 0.5f)
DrawUtils.screenBorder(g, bounds, View.bounds, RGBAColorNorm(1, 1, 1))
drawChildren(g)
endDraw(g)
}
}
object ScreenWindow {
private val BorderTop = 20
private val BorderLeft = 16
private val BorderRight = 16
private val BorderBottom = 16
val BorderTop = 20
val BorderLeft = 16
val BorderRight = 16
val BorderBottom = 16
private val BorderVertical = BorderTop + BorderBottom
private val BorderHorizontal = BorderLeft + BorderRight
val BorderVertical: Int = BorderTop + BorderBottom
val BorderHorizontal: Int = BorderLeft + BorderRight
}