Skip to content

Commit

Permalink
feat: add more shapes to display package
Browse files Browse the repository at this point in the history
  • Loading branch information
doinkythederp committed Nov 20, 2024
1 parent 0b938fc commit efedc85
Show file tree
Hide file tree
Showing 20 changed files with 286 additions and 35 deletions.
4 changes: 2 additions & 2 deletions examples/clawbot-kotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ plugins {
}

hydrozoa {
entrypoint = "dev.vexide.hydrozoa.clawbotkt.Main"
runtime = project.rootProject.layout.projectDirectory.file("runtime.bin")
entrypoint = "dev.vexide.hydrozoa.examples.clawbotkt.MainKt"
runtime = rootProject.layout.projectDirectory.file("hydrozoa.bin")
}

kotlin {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
@file:JvmName("Main")

package dev.vexide.hydrozoa.clawbotkt
package dev.vexide.hydrozoa.examples.clawbotkt

import dev.vexide.hydrozoa.CompetitionRuntime

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.vexide.hydrozoa.clawbotkt
package dev.vexide.hydrozoa.examples.clawbotkt

import dev.vexide.hydrozoa.CompetitionRobot
import dev.vexide.hydrozoa.Controller
Expand Down
4 changes: 2 additions & 2 deletions examples/clawbot/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ plugins {
}

hydrozoa {
entrypoint = "dev.vexide.hydrozoa.clawbot.Main"
runtime = project.rootProject.layout.projectDirectory.file("runtime.bin")
entrypoint = "dev.vexide.hydrozoa.examples.clawbot.Main"
runtime = rootProject.layout.projectDirectory.file("hydrozoa.bin")
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.vexide.hydrozoa.clawbot;
package dev.vexide.hydrozoa.examples.clawbot;

import dev.vexide.hydrozoa.CompetitionRuntime;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.vexide.hydrozoa.clawbot;
package dev.vexide.hydrozoa.examples.clawbot;

import dev.vexide.hydrozoa.CompetitionRobot;
import dev.vexide.hydrozoa.Controller;
Expand Down
13 changes: 13 additions & 0 deletions examples/screen/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
kotlin("jvm") version "1.9.20"
id("dev.vexide.hydrozoa")
}

kotlin {
jvmToolchain(21)
}

hydrozoa {
entrypoint = "dev.vexide.hydrozoa.examples.screen.MainKt"
runtime = rootProject.layout.projectDirectory.file("hydrozoa.bin")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.vexide.hydrozoa.examples.screen

import dev.vexide.hydrozoa.CompetitionRobot
import dev.vexide.hydrozoa.CompetitionRuntime
import dev.vexide.hydrozoa.Peripherals
import dev.vexide.hydrozoa.display.Rect
import dev.vexide.hydrozoa.display.Rgb
import dev.vexide.hydrozoa.display.Text

fun main() {
val peripherals = Peripherals.take().orElseThrow()
val display = peripherals.takeDisplay()

val rect = Rect(20, 20, 100, 100)
display.fill(rect, Rgb.fromInteger(0xFFFFFF))
display.stroke(rect, Rgb.fromInteger(0xFF00FF))

val text = Text("Nice to see you!", 80, 80)
display.write(text, Rgb.fromInteger(0x00FFFF), Rgb.fromInteger(0x000000))
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ val extension = extensions.create<HydrozoaPluginExtension>("hydrozoa")

extension.slot.convention(1)
extension.outputFile.convention("robot.wasm")
extension.runtime.convention(layout.projectDirectory.file("runtime.bin"))
extension.runtime.convention(layout.projectDirectory.file("hydrozoa.bin"))

abstract class UploadTask : Exec() {
@Input
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ include("examples:clawbot")
findProject(":examples:clawbot")?.name = "clawbot"
include("examples:clawbot-kotlin")
findProject(":examples:clawbot-kotlin")?.name = "clawbot-kotlin"
include("examples:screen")
findProject(":examples:screen")?.name = "screen"
12 changes: 3 additions & 9 deletions src/main/java/dev/vexide/hydrozoa/CompetitionRuntime.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
import java.util.function.Function;

public final class CompetitionRuntime {
private CompetitionRuntime() {}
private CompetitionRuntime() {
}

public static final Duration DEFAULT_PERIOD = Duration.ofMillis(2);
private static @Nullable Boolean wasConnected = null;
private static @Nullable Mode previousMode = null;
public static @NotNull Duration period = DEFAULT_PERIOD;
private static boolean hasStarted = false;

public static void assertRobotEnabled() throws DeviceException {
if (!mode().equals(Mode.Driver)) {
Expand All @@ -29,12 +29,7 @@ public static void assertRobotEnabled() throws DeviceException {

public static void start(@NotNull Function<@NotNull Peripherals, @NotNull CompetitionRobot> factory) throws IllegalStateException {
try {
if (hasStarted) {
throw new IllegalStateException("Competition runtime has already started");
}
hasStarted = true;

var robot = factory.apply(new Peripherals());
var robot = factory.apply(Peripherals.take().orElseThrow(() -> new IllegalStateException("Peripherals already taken")));

while (true) {
var begin = Instant.now();
Expand Down Expand Up @@ -83,7 +78,6 @@ public static void start(@NotNull Function<@NotNull Peripherals, @NotNull Compet
System.err.println("Uncaught exception in competition runtime");
e.printStackTrace();
}

}

@Contract(value = "-> new", pure = true)
Expand Down
18 changes: 17 additions & 1 deletion src/main/java/dev/vexide/hydrozoa/Peripherals.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,37 @@
import org.jetbrains.annotations.Nullable;

import java.util.NoSuchElementException;
import java.util.Optional;

public class Peripherals {
private static final Key key = new Key();
private static Peripherals instance = new Peripherals();

private final @Nullable SmartPort[] ports = new SmartPort[21];
private @Nullable Controller primaryController = new Controller(Controller.Id.Primary);
private @Nullable Controller partnerController = new Controller(Controller.Id.Partner);
private @Nullable Display display = new Display(key);

Peripherals() {
private Peripherals() {
for (int i = 0; i < ports.length; i++) {
ports[i] = new SmartPort(key, i);
}
}

public static Optional<Peripherals> take() {
if (instance == null) {
return Optional.empty();
}

var peripherals = instance;
instance = null;
return Optional.of(peripherals);
}

public static @NotNull Peripherals unsafelyCreate() {
return new Peripherals();
}

@Contract("_ -> new")
public @NotNull SmartPort takePort(int portNumber) throws IllegalArgumentException, NoSuchElementException {
if (portNumber < 0 || portNumber >= ports.length) {
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/dev/vexide/hydrozoa/display/Circle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.vexide.hydrozoa.display;

import dev.vexide.hydrozoa.sdk.VexSdk;
import org.jetbrains.annotations.NotNull;

public record Circle(int x, int y, int radius) implements Shape {
public Circle {
if (radius < 0) {
throw new IllegalArgumentException(String.format("Radius must be positive or zero, not `%d`", radius));
}
}

@Override
public void draw(@NotNull Display screen, @NotNull Rgb color, boolean fill) {
VexSdk.Display.vexDisplayForegroundColor(color.toInteger());
if (fill) {
VexSdk.Display.vexDisplayCircleFill(x, y + Display.HEADER_HEIGHT, radius);
} else {
VexSdk.Display.vexDisplayCircleDraw(x, y + Display.HEADER_HEIGHT, radius);
}
}
}
46 changes: 43 additions & 3 deletions src/main/java/dev/vexide/hydrozoa/display/Display.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,53 @@
package dev.vexide.hydrozoa.display;

import dev.vexide.hydrozoa.Peripherals;
import dev.vexide.hydrozoa.sdk.VexSdk;
import org.jetbrains.annotations.NotNull;

public class Display {
public Display(Peripherals.Key ignoredKey) {
public static final int HEADER_HEIGHT = 32;

public Display(@NotNull Peripherals.Key ignoredKey) {
}

private @NotNull RenderMode renderMode = RenderMode.Immediate;

public void setRenderMode(@NotNull RenderMode renderMode) {
switch (renderMode) {
case Immediate -> VexSdk.Display.vexDisplayDoubleBufferDisable();
case DoubleBuffered -> VexSdk.Display.vexDisplayRender(false, false);
}
this.renderMode = renderMode;
}

public @NotNull RenderMode getRenderMode() {
return renderMode;
}

public void render() {
if (renderMode == RenderMode.DoubleBuffered) {
VexSdk.Display.vexDisplayRender(false, false);
}
}

public void draw(@NotNull Shape shape, @NotNull Rgb color, boolean fill) {
shape.draw(this, color, fill);
}

public void fill(@NotNull Shape shape, @NotNull Rgb color) {
shape.draw(this, color, true);
}

public void stroke(@NotNull Shape shape, @NotNull Rgb color) {
shape.draw(this, color, false);
}

public void write(@NotNull Text text, @NotNull Rgb fgColor, @NotNull Rgb bgColor) {
text.draw(this, fgColor, bgColor);
}

public void fill(@NotNull Fillable shape, @NotNull Rgb color) {
shape.fill(this, color);
public enum RenderMode {
Immediate,
DoubleBuffered
}
}
7 changes: 0 additions & 7 deletions src/main/java/dev/vexide/hydrozoa/display/Fillable.java

This file was deleted.

10 changes: 7 additions & 3 deletions src/main/java/dev/vexide/hydrozoa/display/Rect.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

public record Rect(int x1, int y1, int x2, int y2) implements Fillable {
public record Rect(int x1, int y1, int x2, int y2) implements Shape {
@Contract(value = "_, _, _, _ -> new", pure = true)
public static @NotNull Rect fromDimensions(int x, int y, int width, int height) {
return new Rect(x, y, x + width, y + height);
Expand All @@ -16,8 +16,12 @@ public record Rect(int x1, int y1, int x2, int y2) implements Fillable {
}

@Override
public void fill(@NotNull Display screen, @NotNull Rgb color) {
public void draw(@NotNull Display screen, @NotNull Rgb color, boolean fill) {
VexSdk.Display.vexDisplayForegroundColor(color.toInteger());
VexSdk.Display.vexDisplayRectFill(x1, y1, x2, y2);
if (fill) {
VexSdk.Display.vexDisplayRectFill(x1, y1 + Display.HEADER_HEIGHT, x2, y2 + Display.HEADER_HEIGHT);
} else {
VexSdk.Display.vexDisplayRectDraw(x1, y1 + Display.HEADER_HEIGHT, x2, y2 + Display.HEADER_HEIGHT);
}
}
}
7 changes: 7 additions & 0 deletions src/main/java/dev/vexide/hydrozoa/display/Shape.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.vexide.hydrozoa.display;

import org.jetbrains.annotations.NotNull;

public interface Shape {
void draw(@NotNull Display screen, @NotNull Rgb color, boolean fill);
}
92 changes: 92 additions & 0 deletions src/main/java/dev/vexide/hydrozoa/display/Text.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package dev.vexide.hydrozoa.display;

import dev.vexide.hydrozoa.sdk.VexSdk;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

public record Text(@NotNull String text, @NotNull Size size, int x, int y, HAlign hAlign, VAlign vAlign) {
public Text(@NotNull String text, @NotNull Size size, int x, int y) {
this(text, size, x, y, HAlign.Left, VAlign.Top);
}

public Text(@NotNull String text, int x, int y) {
this(text, Size.Medium, x, y, HAlign.Left, VAlign.Top);
}

public @NotNull Text withSize(@NotNull Size size) {
return new Text(text, size, x, y, hAlign, vAlign);
}

public @NotNull Text withAlignment(@NotNull HAlign hAlign, @NotNull VAlign vAlign) {
return new Text(text, size, x, y, hAlign, vAlign);
}

private void configureTextMeasuring() {
switch (size) {
case Small -> VexSdk.Display.vexDisplaySmallStringAt(0, 0, "");
case Medium -> VexSdk.Display.vexDisplayStringAt(0, 0, "");
case Large -> VexSdk.Display.vexDisplayBigStringAt(0, 0, "");
}
}

/**
* Get the height of the rendered text
* @return the height of the text, in pixels
*/
@Contract(pure = true)
public int height() {
configureTextMeasuring();
return VexSdk.Display.vexDisplayStringHeightGet(text);
}

/**
* Get the width of the rendered text
* @return the width of the text, in pixels
*/
@Contract(pure = true)
public int width() {
configureTextMeasuring();
return VexSdk.Display.vexDisplayStringWidthGet(text);
}

public void draw(@NotNull Display display, @NotNull Rgb fgColor, @NotNull Rgb bgColor) {
VexSdk.Display.vexDisplayForegroundColor(fgColor.toInteger());
VexSdk.Display.vexDisplayBackgroundColor(bgColor.toInteger());

var x = switch (hAlign) {
case Left -> this.x;
case Center -> this.x - width() / 2;
case Right -> this.x - width();
};

var y = switch (vAlign) {
case Top -> this.y;
case Center -> this.y - height() / 2;
case Bottom -> this.y - height();
} + Display.HEADER_HEIGHT;

switch (size) {
case Small -> VexSdk.Display.vexDisplaySmallStringAt(x, y, text);
case Medium -> VexSdk.Display.vexDisplayStringAt(x, y, text);
case Large -> VexSdk.Display.vexDisplayBigStringAt(x, y, text);
}
}

public enum Size {
Small,
Medium,
Large
}

public enum HAlign {
Left,
Center,
Right
}

public enum VAlign {
Top,
Center,
Bottom
}
}
Loading

0 comments on commit efedc85

Please sign in to comment.