Merge branch 'master-new' into mads-new

# Conflicts:
#	opendbc_repo
This commit is contained in:
Jason Wen
2024-12-09 16:07:24 -05:00
48 changed files with 572 additions and 613 deletions
+25 -20
View File
@@ -99,9 +99,9 @@ send_queue: Queue[str] = queue.Queue()
upload_queue: Queue[UploadItem] = queue.Queue()
low_priority_send_queue: Queue[str] = queue.Queue()
log_recv_queue: Queue[str] = queue.Queue()
cancelled_uploads: set[str] = set()
cur_upload_items: dict[int, UploadItem | None] = {}
cur_upload_items_lock = threading.Lock()
def strip_zst_extension(fn: str) -> str:
@@ -129,8 +129,9 @@ class UploadQueueCache:
@staticmethod
def cache(upload_queue: Queue[UploadItem]) -> None:
try:
queue: list[UploadItem | None] = list(upload_queue.queue)
items = [asdict(i) for i in queue if i is not None and (i.id not in cancelled_uploads)]
with upload_queue.mutex:
items = [asdict(item) for item in upload_queue.queue]
Params().put("AthenadUploadQueue", json.dumps(items))
except Exception:
cloudlog.exception("athena.UploadQueueCache.cache.exception")
@@ -200,7 +201,8 @@ def retry_upload(tid: int, end_event: threading.Event, increase_count: bool = Tr
upload_queue.put_nowait(item)
UploadQueueCache.cache(upload_queue)
cur_upload_items[tid] = None
with cur_upload_items_lock:
cur_upload_items[tid] = None
for _ in range(RETRY_DELAY):
time.sleep(1)
@@ -219,7 +221,8 @@ def cb(sm, item, tid, end_event: threading.Event, sz: int, cur: int) -> None:
if end_event.is_set():
raise AbortTransferException
cur_upload_items[tid] = replace(item, progress=cur / sz if sz else 1)
with cur_upload_items_lock:
cur_upload_items[tid] = replace(item, progress=cur / sz if sz else 1)
def upload_handler(end_event: threading.Event) -> None:
@@ -227,14 +230,10 @@ def upload_handler(end_event: threading.Event) -> None:
tid = threading.get_ident()
while not end_event.is_set():
cur_upload_items[tid] = None
try:
cur_upload_items[tid] = item = replace(upload_queue.get(timeout=1), current=True)
if item.id in cancelled_uploads:
cancelled_uploads.remove(item.id)
continue
with cur_upload_items_lock:
cur_upload_items[tid] = None
cur_upload_items[tid] = item = replace(upload_queue.get(timeout=1), current=True)
# Remove item if too old
age = datetime.now() - datetime.fromtimestamp(item.created_at / 1000)
@@ -413,8 +412,13 @@ def uploadFilesToUrls(files_data: list[UploadFileDict]) -> UploadFilesToUrlRespo
@dispatcher.add_method
def listUploadQueue() -> list[UploadItemDict]:
items = list(upload_queue.queue) + list(cur_upload_items.values())
return [asdict(i) for i in items if (i is not None) and (i.id not in cancelled_uploads)]
with upload_queue.mutex:
items = list(upload_queue.queue)
with cur_upload_items_lock:
items += list(cur_upload_items.values())
return [asdict(item) for item in items]
@dispatcher.add_method
@@ -422,13 +426,14 @@ def cancelUpload(upload_id: str | list[str]) -> dict[str, int | str]:
if not isinstance(upload_id, list):
upload_id = [upload_id]
uploading_ids = {item.id for item in list(upload_queue.queue)}
cancelled_ids = uploading_ids.intersection(upload_id)
if len(cancelled_ids) == 0:
return {"success": 0, "error": "not found"}
with upload_queue.mutex:
remaining_items = [item for item in upload_queue.queue if item.id not in upload_id]
if len(remaining_items) == len(upload_queue.queue):
return {"success": 0, "error": "not found"}
cancelled_uploads.update(cancelled_ids)
return {"success": 1}
upload_queue.queue.clear()
upload_queue.queue.extend(remaining_items)
return {"success": 1}
@dispatcher.add_method
def setRouteViewed(route: str) -> dict[str, int | str]:
+2 -6
View File
@@ -78,7 +78,6 @@ class TestAthenadMethods:
athenad.upload_queue = queue.Queue()
athenad.cur_upload_items.clear()
athenad.cancelled_uploads.clear()
for i in os.listdir(Paths.log_root()):
p = os.path.join(Paths.log_root(), i)
@@ -282,13 +281,10 @@ class TestAthenadMethods:
athenad.upload_queue.put_nowait(item)
dispatcher["cancelUpload"](item.id)
assert item.id in athenad.cancelled_uploads
self._wait_for_upload()
time.sleep(0.1)
assert athenad.upload_queue.qsize() == 0
assert len(athenad.cancelled_uploads) == 0
@with_upload_handler
def test_cancel_expiry(self):
@@ -331,7 +327,7 @@ class TestAthenadMethods:
assert items[0] == asdict(item)
assert not items[0]['current']
athenad.cancelled_uploads.add(item.id)
dispatcher["cancelUpload"](item.id)
items = dispatcher["listUploadQueue"]()
assert len(items) == 0
@@ -343,7 +339,7 @@ class TestAthenadMethods:
athenad.upload_queue.put_nowait(item2)
# Ensure canceled items are not persisted
athenad.cancelled_uploads.add(item2.id)
dispatcher["cancelUpload"](item2.id)
# serialize item
athenad.UploadQueueCache.cache(athenad.upload_queue)
+37 -35
View File
@@ -1,12 +1,12 @@
import pytest
import time
import numpy as np
from flaky import flaky
from collections import defaultdict
import cereal.messaging as messaging
from cereal import log
from cereal.services import SERVICE_LIST
from openpilot.common.retry import retry
from openpilot.system.manager.process_config import managed_processes
TEST_TIMESPAN = 10
@@ -17,44 +17,46 @@ FRAME_DELTA_TOLERANCE = {log.FrameData.ImageSensor.ar0231: 1.0,
CAMERAS = ('roadCameraState', 'driverCameraState', 'wideRoadCameraState')
# TODO: this shouldn't be needed
@flaky(max_runs=3)
@retry(attempts=3, delay=5.0)
def setup_camerad(cls):
# run camerad and record logs
managed_processes['camerad'].start()
time.sleep(3)
socks = {c: messaging.sub_sock(c, conflate=False, timeout=100) for c in CAMERAS}
cls.logs = defaultdict(list)
start_time = time.monotonic()
while time.monotonic()- start_time < TEST_TIMESPAN:
for cam, s in socks.items():
cls.logs[cam] += messaging.drain_sock(s)
time.sleep(0.2)
managed_processes['camerad'].stop()
cls.log_by_frame_id = defaultdict(list)
cls.sensor_type = None
for cam, msgs in cls.logs.items():
if cls.sensor_type is None:
cls.sensor_type = getattr(msgs[0], msgs[0].which()).sensor.raw
expected_frames = SERVICE_LIST[cam].frequency * TEST_TIMESPAN
assert expected_frames*0.95 < len(msgs) < expected_frames*1.05, f"unexpected frame count {cam}: {expected_frames=}, got {len(msgs)}"
dts = np.abs(np.diff([getattr(m, m.which()).timestampSof/1e6 for m in msgs]) - 1000/SERVICE_LIST[cam].frequency)
assert (dts < FRAME_DELTA_TOLERANCE[cls.sensor_type]).all(), f"{cam} dts(ms) out of spec: max diff {dts.max()}, 99 percentile {np.percentile(dts, 99)}"
for m in msgs:
cls.log_by_frame_id[getattr(m, m.which()).frameId].append(m)
# strip beginning and end
for _ in range(3):
mn, mx = min(cls.log_by_frame_id.keys()), max(cls.log_by_frame_id.keys())
del cls.log_by_frame_id[mn]
del cls.log_by_frame_id[mx]
@pytest.mark.tici
class TestCamerad:
@classmethod
def setup_class(cls):
# run camerad and record logs
managed_processes['camerad'].start()
time.sleep(3)
socks = {c: messaging.sub_sock(c, conflate=False, timeout=100) for c in CAMERAS}
cls.logs = defaultdict(list)
start_time = time.monotonic()
while time.monotonic()- start_time < TEST_TIMESPAN:
for cam, s in socks.items():
cls.logs[cam] += messaging.drain_sock(s)
time.sleep(0.2)
managed_processes['camerad'].stop()
cls.log_by_frame_id = defaultdict(list)
cls.sensor_type = None
for cam, msgs in cls.logs.items():
if cls.sensor_type is None:
cls.sensor_type = getattr(msgs[0], msgs[0].which()).sensor.raw
expected_frames = SERVICE_LIST[cam].frequency * TEST_TIMESPAN
assert expected_frames*0.95 < len(msgs) < expected_frames*1.05, f"unexpected frame count {cam}: {expected_frames=}, got {len(msgs)}"
dts = np.abs(np.diff([getattr(m, m.which()).timestampSof/1e6 for m in msgs]) - 1000/SERVICE_LIST[cam].frequency)
assert (dts < FRAME_DELTA_TOLERANCE[cls.sensor_type]).all(), f"{cam} dts(ms) out of spec: max diff {dts.max()}, 99 percentile {np.percentile(dts, 99)}"
for m in msgs:
cls.log_by_frame_id[getattr(m, m.which()).frameId].append(m)
# strip beginning and end
for _ in range(3):
mn, mx = min(cls.log_by_frame_id.keys()), max(cls.log_by_frame_id.keys())
del cls.log_by_frame_id[mn]
del cls.log_by_frame_id[mx]
setup_camerad(cls)
def test_frame_skips(self):
skips = {}
+3 -2
View File
@@ -1,12 +1,14 @@
import time
import numpy as np
import pytest
from openpilot.selfdrive.test.helpers import with_processes, phone_only
from openpilot.selfdrive.test.helpers import with_processes
from openpilot.system.camerad.snapshot.snapshot import get_snapshots
TEST_TIME = 45
REPEAT = 5
@pytest.mark.tici
class TestCamerad:
@classmethod
def setup_class(cls):
@@ -28,7 +30,6 @@ class TestCamerad:
print([i_median, i_mean])
return med_ex[0] < i_median < med_ex[1] and mean_ex[0] < i_mean < mean_ex[1]
@phone_only
@with_processes(['camerad'])
def test_camera_operation(self):
passed = 0
+46 -4
View File
@@ -1,11 +1,54 @@
import os
from abc import abstractmethod, ABC
from collections import namedtuple
from dataclasses import dataclass, fields
from cereal import log
ThermalConfig = namedtuple('ThermalConfig', ['cpu', 'gpu', 'mem', 'pmic', 'intake', 'exhaust'])
NetworkType = log.DeviceState.NetworkType
@dataclass
class ThermalZone:
# a zone from /sys/class/thermal/thermal_zone*
name: str # a.k.a type
scale: float = 1000. # scale to get degrees in C
zone_number = -1
def read(self) -> float:
if self.zone_number < 0:
for n in os.listdir("/sys/devices/virtual/thermal"):
if not n.startswith("thermal_zone"):
continue
with open(os.path.join("/sys/devices/virtual/thermal", n, "type")) as f:
if f.read().strip() == self.name:
self.zone_number = int(n.removeprefix("thermal_zone"))
break
try:
with open(f"/sys/devices/virtual/thermal/thermal_zone{self.zone_number}/temp") as f:
return int(f.read()) / self.scale
except FileNotFoundError:
return 0
@dataclass
class ThermalConfig:
cpu: list[ThermalZone] | None = None
gpu: list[ThermalZone] | None = None
pmic: list[ThermalZone] | None = None
memory: ThermalZone | None = None
intake: ThermalZone | None = None
exhaust: ThermalZone | None = None
case: ThermalZone | None = None
def get_msg(self):
ret = {}
for f in fields(ThermalConfig):
v = getattr(self, f.name)
if v is not None:
if isinstance(v, list):
ret[f.name + "TempC"] = [x.read() for x in v]
else:
ret[f.name + "TempC"] = v.read()
return ret
class HardwareBase(ABC):
@staticmethod
@@ -84,9 +127,8 @@ class HardwareBase(ABC):
def shutdown(self):
pass
@abstractmethod
def get_thermal_config(self):
pass
return ThermalConfig()
@abstractmethod
def set_screen_brightness(self, percentage):
+5 -39
View File
@@ -51,41 +51,6 @@ OFFROAD_DANGER_TEMP = 75
prev_offroad_states: dict[str, tuple[bool, str | None]] = {}
tz_by_type: dict[str, int] | None = None
def populate_tz_by_type():
global tz_by_type
tz_by_type = {}
for n in os.listdir("/sys/devices/virtual/thermal"):
if not n.startswith("thermal_zone"):
continue
with open(os.path.join("/sys/devices/virtual/thermal", n, "type")) as f:
tz_by_type[f.read().strip()] = int(n.removeprefix("thermal_zone"))
def read_tz(x):
if x is None:
return 0
if isinstance(x, str):
if tz_by_type is None:
populate_tz_by_type()
x = tz_by_type[x]
try:
with open(f"/sys/devices/virtual/thermal/thermal_zone{x}/temp") as f:
return int(f.read())
except FileNotFoundError:
return 0
def read_thermal(thermal_config):
dat = messaging.new_message('deviceState', valid=True)
dat.deviceState.cpuTempC = [read_tz(z) / thermal_config.cpu[1] for z in thermal_config.cpu[0]]
dat.deviceState.gpuTempC = [read_tz(z) / thermal_config.gpu[1] for z in thermal_config.gpu[0]]
dat.deviceState.memoryTempC = read_tz(thermal_config.mem[0]) / thermal_config.mem[1]
dat.deviceState.pmicTempC = [read_tz(z) / thermal_config.pmic[1] for z in thermal_config.pmic[0]]
dat.deviceState.intakeTempC = read_tz(thermal_config.intake[0]) / thermal_config.intake[1]
dat.deviceState.exhaustTempC = read_tz(thermal_config.exhaust[0]) / thermal_config.exhaust[1]
return dat
def set_offroad_alert_if_changed(offroad_alert: str, show_alert: bool, extra_text: str | None=None):
@@ -234,7 +199,8 @@ def hardware_thread(end_event, hw_queue) -> None:
if (sm.frame % round(SERVICE_LIST['pandaStates'].frequency * DT_HW) != 0) and not ign_edge:
continue
msg = read_thermal(thermal_config)
msg = messaging.new_message('deviceState', valid=True)
msg.deviceState = thermal_config.get_msg()
msg.deviceState.deviceType = HARDWARE.get_device_type()
try:
@@ -264,13 +230,13 @@ def hardware_thread(end_event, hw_queue) -> None:
# this subset is only used for offroad
temp_sources = [
msg.deviceState.memoryTempC,
max(msg.deviceState.cpuTempC),
max(msg.deviceState.gpuTempC),
max(msg.deviceState.cpuTempC, default=0.),
max(msg.deviceState.gpuTempC, default=0.),
]
offroad_comp_temp = offroad_temp_filter.update(max(temp_sources))
# this drives the thermal status while onroad
temp_sources.append(max(msg.deviceState.pmicTempC))
temp_sources.append(max(msg.deviceState.pmicTempC, default=0.))
all_comp_temp = all_temp_filter.update(max(temp_sources))
msg.deviceState.maxTempC = all_comp_temp
+1 -4
View File
@@ -1,7 +1,7 @@
import random
from cereal import log
from openpilot.system.hardware.base import HardwareBase, ThermalConfig
from openpilot.system.hardware.base import HardwareBase
NetworkType = log.DeviceState.NetworkType
NetworkStrength = log.DeviceState.NetworkStrength
@@ -53,9 +53,6 @@ class Pc(HardwareBase):
def shutdown(self):
print("SHUTDOWN!")
def get_thermal_config(self):
return ThermalConfig(cpu=((None,), 1), gpu=((None,), 1), mem=(None, 1), pmic=((None,), 1), intake=(None, 1), exhaust=(None, 1))
def set_screen_brightness(self, percentage):
pass
+19 -19
View File
@@ -1,19 +1,19 @@
[
{
"name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate-staging/boot-184b9edb429167dcc97110134cdeffaa9739a758b3069e3ea7700e6559b79a0a.img.xz",
"hash": "184b9edb429167dcc97110134cdeffaa9739a758b3069e3ea7700e6559b79a0a",
"hash_raw": "184b9edb429167dcc97110134cdeffaa9739a758b3069e3ea7700e6559b79a0a",
"size": 16414720,
"url": "https://commadist.azureedge.net/agnosupdate/boot-45e107ad65e6cc9ee95dc139f9ed11d56ef7f5f0657f579498a4a48f0a2f7ea3.img.xz",
"hash": "45e107ad65e6cc9ee95dc139f9ed11d56ef7f5f0657f579498a4a48f0a2f7ea3",
"hash_raw": "45e107ad65e6cc9ee95dc139f9ed11d56ef7f5f0657f579498a4a48f0a2f7ea3",
"size": 16418816,
"sparse": false,
"full_check": true,
"has_ab": true
},
{
"name": "system",
"url": "https://commadist.azureedge.net/agnosupdate-staging/system-93a86656670d6d8d99ea401bd5735cd1060c2355d65f2c14de522c77a80c57ea.img.xz",
"hash": "93a86656670d6d8d99ea401bd5735cd1060c2355d65f2c14de522c77a80c57ea",
"hash_raw": "93a86656670d6d8d99ea401bd5735cd1060c2355d65f2c14de522c77a80c57ea",
"url": "https://commadist.azureedge.net/agnosupdate/system-c0d738052c77f97b10bcea111479ddabd3fde2653d50533dd0fa2b17bb7881e9.img.xz",
"hash": "c0d738052c77f97b10bcea111479ddabd3fde2653d50533dd0fa2b17bb7881e9",
"hash_raw": "c0d738052c77f97b10bcea111479ddabd3fde2653d50533dd0fa2b17bb7881e9",
"size": 4404019200,
"sparse": false,
"full_check": false,
@@ -21,9 +21,9 @@
},
{
"name": "xbl",
"url": "https://commadist.azureedge.net/agnosupdate/xbl-446e37054b4c2f08bac3ee9d98256cdb93e876fb3343acfc8881124900f11050.img.xz",
"hash": "446e37054b4c2f08bac3ee9d98256cdb93e876fb3343acfc8881124900f11050",
"hash_raw": "446e37054b4c2f08bac3ee9d98256cdb93e876fb3343acfc8881124900f11050",
"url": "https://commadist.azureedge.net/agnosupdate/xbl-bece486a68d9470c165e87955e451339cd86ada6ca2c7fde13c49144624ce030.img.xz",
"hash": "bece486a68d9470c165e87955e451339cd86ada6ca2c7fde13c49144624ce030",
"hash_raw": "bece486a68d9470c165e87955e451339cd86ada6ca2c7fde13c49144624ce030",
"size": 3282256,
"sparse": false,
"full_check": true,
@@ -41,9 +41,9 @@
},
{
"name": "xbl_config",
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-80f3e644529d30e260bb9b8b6c765d76a4ccd0a2d3104cc07acf93b0eabb8995.img.xz",
"hash": "80f3e644529d30e260bb9b8b6c765d76a4ccd0a2d3104cc07acf93b0eabb8995",
"hash_raw": "80f3e644529d30e260bb9b8b6c765d76a4ccd0a2d3104cc07acf93b0eabb8995",
"url": "https://commadist.azureedge.net/agnosupdate/xbl_config-868b6f9aa98871dc50ef191a2d8f432578d1eca84f87d9185f8fb61242c3b66f.img.xz",
"hash": "868b6f9aa98871dc50ef191a2d8f432578d1eca84f87d9185f8fb61242c3b66f",
"hash_raw": "868b6f9aa98871dc50ef191a2d8f432578d1eca84f87d9185f8fb61242c3b66f",
"size": 98124,
"sparse": false,
"full_check": true,
@@ -51,9 +51,9 @@
},
{
"name": "devcfg",
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-8ea8a9e779b0bd43af41ed367e3c781ba666012eebb4707ce58328b81219f9f8.img.xz",
"hash": "8ea8a9e779b0bd43af41ed367e3c781ba666012eebb4707ce58328b81219f9f8",
"hash_raw": "8ea8a9e779b0bd43af41ed367e3c781ba666012eebb4707ce58328b81219f9f8",
"url": "https://commadist.azureedge.net/agnosupdate/devcfg-c27dc9ab628015ef265e1204ca736b2838ec179e9ecdd79e2ddb59d984b78df1.img.xz",
"hash": "c27dc9ab628015ef265e1204ca736b2838ec179e9ecdd79e2ddb59d984b78df1",
"hash_raw": "c27dc9ab628015ef265e1204ca736b2838ec179e9ecdd79e2ddb59d984b78df1",
"size": 40336,
"sparse": false,
"full_check": true,
@@ -61,9 +61,9 @@
},
{
"name": "aop",
"url": "https://commadist.azureedge.net/agnosupdate/aop-c1dbeefa20e742dde97eac76aaa00d1e6c2e2b01cfbd4c1242bd4e26c7d2aed4.img.xz",
"hash": "c1dbeefa20e742dde97eac76aaa00d1e6c2e2b01cfbd4c1242bd4e26c7d2aed4",
"hash_raw": "c1dbeefa20e742dde97eac76aaa00d1e6c2e2b01cfbd4c1242bd4e26c7d2aed4",
"url": "https://commadist.azureedge.net/agnosupdate/aop-588bb60f0f8194d2df12f041e320a6dfeafae7209b312be3e4f6fe0744192837.img.xz",
"hash": "588bb60f0f8194d2df12f041e320a6dfeafae7209b312be3e4f6fe0744192837",
"hash_raw": "588bb60f0f8194d2df12f041e320a6dfeafae7209b312be3e4f6fe0744192837",
"size": 184364,
"sparse": false,
"full_check": true,
+22 -17
View File
@@ -10,7 +10,7 @@ from pathlib import Path
from cereal import log
from openpilot.common.gpio import gpio_set, gpio_init, get_irqs_for_action
from openpilot.system.hardware.base import HardwareBase, ThermalConfig
from openpilot.system.hardware.base import HardwareBase, ThermalConfig, ThermalZone
from openpilot.system.hardware.tici import iwlist
from openpilot.system.hardware.tici.pins import GPIO
from openpilot.system.hardware.tici.amplifier import Amplifier
@@ -323,17 +323,19 @@ class Tici(HardwareBase):
os.system("sudo poweroff")
def get_thermal_config(self):
intake, exhaust = (None, 1), (None, 1)
intake, exhaust, case = None, None, None
if self.get_device_type() == "mici":
intake = ("intake", 1000)
exhaust = ("exhaust", 1000)
return ThermalConfig(cpu=([f"cpu{i}-silver-usr" for i in range(4)] +
[f"cpu{i}-gold-usr" for i in range(4)], 1000),
gpu=(("gpu0-usr", "gpu1-usr"), 1000),
mem=("ddr-usr", 1000),
pmic=(("pm8998_tz", "pm8005_tz"), 1000),
case = ThermalZone("case")
intake = ThermalZone("intake")
exhaust = ThermalZone("exhaust")
return ThermalConfig(cpu=[ThermalZone(f"cpu{i}-silver-usr") for i in range(4)] +
[ThermalZone(f"cpu{i}-gold-usr") for i in range(4)],
gpu=[ThermalZone("gpu0-usr"), ThermalZone("gpu1-usr")],
memory=ThermalZone("ddr-usr"),
pmic=[ThermalZone("pm8998_tz"), ThermalZone("pm8005_tz")],
intake=intake,
exhaust=exhaust)
exhaust=exhaust,
case=case)
def set_screen_brightness(self, percentage):
try:
@@ -485,14 +487,16 @@ class Tici(HardwareBase):
'AT$QCNETDEVCTL=3,1',
]
else:
cmds += [
# SIM sleep disable
'AT$QCSIMSLEEP=0',
'AT$QCSIMCFG=SimPowerSave,0',
# this modem gets upset with too many AT commands
if sim_id is None or len(sim_id) == 0:
cmds += [
# SIM sleep disable
'AT$QCSIMSLEEP=0',
'AT$QCSIMCFG=SimPowerSave,0',
# ethernet config
'AT$QCPCFG=usbNet,1',
]
# ethernet config
'AT$QCPCFG=usbNet,1',
]
for cmd in cmds:
try:
@@ -591,3 +595,4 @@ if __name__ == "__main__":
t.configure_modem()
t.initialize_hardware()
t.set_power_save(False)
print(t.get_sim_info())
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#define OPENPILOT_RAYLIB
#include "third_party/raylib/include/raylib.h"
+6 -7
View File
@@ -3,7 +3,6 @@
#include <iostream>
#include "system/ui/raylib/util.h"
#include "third_party/raylib/include/raylib.h"
constexpr int kProgressBarWidth = 1000;
constexpr int kProgressBarHeight = 20;
@@ -27,7 +26,7 @@ int main(int argc, char *argv[]) {
while (!WindowShouldClose()) {
BeginDrawing();
ClearBackground(BLACK);
ClearBackground(RAYLIB_BLACK);
rotation = fmod(rotation + kRotationRate, 360.0f);
Vector2 center = {GetScreenWidth() / 2.0f, GetScreenHeight() / 2.0f};
@@ -37,8 +36,8 @@ int main(int argc, char *argv[]) {
// Draw rotating spinner and static comma logo
DrawTexturePro(spinnerTexture, {0, 0, (float)kTextureSize, (float)kTextureSize},
{center.x, center.y, (float)kTextureSize, (float)kTextureSize},
spinnerOrigin, rotation, WHITE);
DrawTextureV(commaTexture, commaPosition, WHITE);
spinnerOrigin, rotation, RAYLIB_WHITE);
DrawTextureV(commaTexture, commaPosition, RAYLIB_WHITE);
// Check for user input
if (std::cin.rdbuf()->in_avail() > 0) {
@@ -50,14 +49,14 @@ int main(int argc, char *argv[]) {
float yPos = GetScreenHeight() - kMargin - kProgressBarHeight;
if (std::all_of(userInput.begin(), userInput.end(), ::isdigit)) {
Rectangle bar = {center.x - kProgressBarWidth / 2.0f, yPos, kProgressBarWidth, kProgressBarHeight};
DrawRectangleRounded(bar, 0.5f, 10, GRAY);
DrawRectangleRounded(bar, 0.5f, 10, RAYLIB_GRAY);
int progress = std::clamp(std::stoi(userInput), 0, 100);
bar.width *= progress / 100.0f;
DrawRectangleRounded(bar, 0.5f, 10, RAYWHITE);
DrawRectangleRounded(bar, 0.5f, 10, RAYLIB_RAYWHITE);
} else {
Vector2 textSize = MeasureTextEx(getFont(), userInput.c_str(), kFontSize, 1.0);
DrawTextEx(getFont(), userInput.c_str(), {center.x - textSize.x / 2, yPos}, kFontSize, 1.0, WHITE);
DrawTextEx(getFont(), userInput.c_str(), {center.x - textSize.x / 2, yPos}, kFontSize, 1.0, RAYLIB_WHITE);
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
#include <string>
#include "third_party/raylib/include/raylib.h"
#include "system/ui/raylib/raylib.h"
enum class FontWeight {
Normal,