Compare commits
9 Commits
18831c3e0e
...
master
Author | SHA1 | Date | |
---|---|---|---|
522fc7c8c4 | |||
f62f2414b0 | |||
f501dc046e | |||
244a340764 | |||
9543851867 | |||
1caf43c6de | |||
d9c063cba7 | |||
8adb89ef2b | |||
ea5f1a7902 |
@@ -1,6 +1,7 @@
|
|||||||
import configparser
|
import configparser
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import infi.systray
|
import infi.systray
|
||||||
@@ -42,12 +43,16 @@ def main():
|
|||||||
|
|
||||||
conf = configparser.ConfigParser()
|
conf = configparser.ConfigParser()
|
||||||
conf.read_dict({
|
conf.read_dict({
|
||||||
'general': {'log_level': 'info'},
|
'general': {
|
||||||
|
'log_level': 'info',
|
||||||
|
'dummy_impl': False,
|
||||||
|
},
|
||||||
'valorant': {'player_uuid': ''},
|
'valorant': {'player_uuid': ''},
|
||||||
})
|
})
|
||||||
conf.read(CONFIG_FILE)
|
conf.read(CONFIG_FILE)
|
||||||
with open(CONFIG_FILE, 'w') as f:
|
with open(CONFIG_FILE, 'w') as f:
|
||||||
conf.write(f)
|
conf.write(f)
|
||||||
|
use_dummy_impl = conf.getboolean('general', 'dummy_impl')
|
||||||
|
|
||||||
log_level = parse_log_level(conf['general']['log_level'])
|
log_level = parse_log_level(conf['general']['log_level'])
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@@ -59,20 +64,28 @@ def main():
|
|||||||
log.error(f'No player UUID set, exiting...')
|
log.error(f'No player UUID set, exiting...')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
val_handler = valconomy.ValconomyHandler()
|
if use_dummy_impl:
|
||||||
|
val_handler = valconomy.ValconomyHandler()
|
||||||
|
else:
|
||||||
|
val_handler = valconomy.HIDValconomyHandler()
|
||||||
|
val_handler.start()
|
||||||
val_sm = valconomy.ValconomyStateMachine(conf['valorant']['player_uuid'], val_handler)
|
val_sm = valconomy.ValconomyStateMachine(conf['valorant']['player_uuid'], val_handler)
|
||||||
|
|
||||||
val_client = valconomy.ValorantLocalClient(val_sm.handle_presence)
|
val_client = valconomy.ValorantLocalClient(val_sm.handle_presence)
|
||||||
def do_quit(tray: infi.systray.SysTrayIcon):
|
def do_quit(*args):
|
||||||
log.info('Shutting down')
|
log.info('Shutting down')
|
||||||
val_client.stop()
|
val_client.stop()
|
||||||
|
if not use_dummy_impl:
|
||||||
|
val_handler.stop()
|
||||||
|
|
||||||
with infi.systray.SysTrayIcon(
|
with infi.systray.SysTrayIcon(
|
||||||
data_file('icon.ico'), 'Valconomy', on_quit=do_quit,
|
data_file('icon.ico'), 'Valconomy', on_quit=do_quit,
|
||||||
menu_options=(
|
menu_options=(
|
||||||
('Open data directory', None, do_open_datadir),
|
('Open data directory', None, do_open_datadir),
|
||||||
)) as tray:
|
)) as tray:
|
||||||
val_client.run()
|
signal.signal(signal.SIGINT, do_quit)
|
||||||
|
signal.signal(signal.SIGTERM, do_quit)
|
||||||
|
val_client.run()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
import valconomy
|
import valconomy
|
||||||
from valconomy import ValorantPlayerInfo, RiotPlayerInfo
|
from valconomy import ValorantPlayerInfo, RiotPlayerInfo, EconomyDecision
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@@ -18,6 +18,26 @@ def main():
|
|||||||
h.idle(None)
|
h.idle(None)
|
||||||
h.queue_start(RiotPlayerInfo.dummy(
|
h.queue_start(RiotPlayerInfo.dummy(
|
||||||
valorant=ValorantPlayerInfo(queue_type='unrated', is_party_owner=True)))
|
valorant=ValorantPlayerInfo(queue_type='unrated', is_party_owner=True)))
|
||||||
|
h.match_found(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(queue_type='premier-seasonmatch')))
|
||||||
|
h.pregame(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(map='/Game/Maps/Bonsai/Bonsai')))
|
||||||
|
h.match_found(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo()))
|
||||||
|
h.pregame(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo()))
|
||||||
|
h.game_generic(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(queue_type='ggteam')))
|
||||||
|
h.game_start(None)
|
||||||
|
h.game_over(None, False)
|
||||||
|
h.game_over(None, True)
|
||||||
|
h.round_start(
|
||||||
|
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=3, enemy_score=7)),
|
||||||
|
won=True, economy=EconomyDecision.SAVE)
|
||||||
|
h.round_start(
|
||||||
|
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=10, enemy_score=2)),
|
||||||
|
won=False, economy=EconomyDecision.BUY)
|
||||||
|
h.round_start(
|
||||||
|
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=10, enemy_score=2)),
|
||||||
|
won=None, economy=EconomyDecision.MATCH_TEAM)
|
||||||
|
h.round_start(
|
||||||
|
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=2, enemy_score=0)),
|
||||||
|
won=True, economy=EconomyDecision.BONUS)
|
||||||
|
|
||||||
h.service()
|
h.service()
|
||||||
finally:
|
finally:
|
||||||
|
@@ -81,7 +81,8 @@ class TestSm:
|
|||||||
('round_start', True, 2, 0, EconomyDecision.BONUS),
|
('round_start', True, 2, 0, EconomyDecision.BONUS),
|
||||||
('round_start', False, 2, 1, EconomyDecision.MATCH_TEAM),
|
('round_start', False, 2, 1, EconomyDecision.MATCH_TEAM),
|
||||||
] + [
|
] + [
|
||||||
('round_start', False, 2, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(8)] + [
|
('round_start', False, 2, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(7)] + [
|
||||||
|
('round_start', False, 2, 9, EconomyDecision.BUY), # last round in half
|
||||||
('round_start', False, 2, 10, EconomyDecision.BUY),
|
('round_start', False, 2, 10, EconomyDecision.BUY),
|
||||||
('round_start', False, 2, 11, EconomyDecision.SAVE),
|
('round_start', False, 2, 11, EconomyDecision.SAVE),
|
||||||
('round_start', False, 2, 12, EconomyDecision.BUY),
|
('round_start', False, 2, 12, EconomyDecision.BUY),
|
||||||
@@ -112,7 +113,8 @@ class TestSm:
|
|||||||
('round_start', True, 1, 0, EconomyDecision.BUY),
|
('round_start', True, 1, 0, EconomyDecision.BUY),
|
||||||
('round_start', False, 1, 1, EconomyDecision.SAVE),
|
('round_start', False, 1, 1, EconomyDecision.SAVE),
|
||||||
] + [
|
] + [
|
||||||
('round_start', False, 1, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(9)] + [
|
('round_start', False, 1, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(8)] + [
|
||||||
|
('round_start', False, 1, 10, EconomyDecision.BUY), # last round in half
|
||||||
('round_start', False, 1, 11, EconomyDecision.BUY),
|
('round_start', False, 1, 11, EconomyDecision.BUY),
|
||||||
('round_start', False, 1, 12, EconomyDecision.BUY),
|
('round_start', False, 1, 12, EconomyDecision.BUY),
|
||||||
] + [
|
] + [
|
||||||
@@ -133,8 +135,10 @@ class TestSm:
|
|||||||
|
|
||||||
self.do(queue_type='swiftplay', game_state='PREGAME')
|
self.do(queue_type='swiftplay', game_state='PREGAME')
|
||||||
self.do(queue_type='swiftplay', game_state='INGAME')
|
self.do(queue_type='swiftplay', game_state='INGAME')
|
||||||
for i in range(5):
|
for i in range(4):
|
||||||
self.do(queue_type='swiftplay', game_state='INGAME', enemy_score=1 + i)
|
self.do(queue_type='swiftplay', game_state='INGAME', enemy_score=1 + i)
|
||||||
|
for i in range(5):
|
||||||
|
self.do(queue_type='swiftplay', game_state='INGAME', score=1 + i, enemy_score=4)
|
||||||
self.do(queue_type='swiftplay', game_state='INGAME')
|
self.do(queue_type='swiftplay', game_state='INGAME')
|
||||||
|
|
||||||
assert self.mock.seq == [
|
assert self.mock.seq == [
|
||||||
@@ -144,9 +148,15 @@ class TestSm:
|
|||||||
('pregame', False),
|
('pregame', False),
|
||||||
'game_start',
|
'game_start',
|
||||||
('round_start', None, 0, 0, EconomyDecision.BUY),
|
('round_start', None, 0, 0, EconomyDecision.BUY),
|
||||||
] + [
|
('round_start', False, 0, 1, EconomyDecision.BUY),
|
||||||
('round_start', False, 0, 1 + i, EconomyDecision.BUY) for i in range(4)] + [
|
('round_start', False, 0, 2, EconomyDecision.BUY),
|
||||||
('game_over', False),
|
('round_start', False, 0, 3, EconomyDecision.BUY),
|
||||||
|
('round_start', False, 0, 4, EconomyDecision.BUY),
|
||||||
|
('round_start', True, 1, 4, EconomyDecision.BUY),
|
||||||
|
('round_start', True, 2, 4, EconomyDecision.BUY),
|
||||||
|
('round_start', True, 3, 4, EconomyDecision.BUY),
|
||||||
|
('round_start', True, 4, 4, EconomyDecision.BUY),
|
||||||
|
('game_over', True),
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_tdm(self):
|
def test_tdm(self):
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
import base64
|
import base64
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import errno
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import os
|
import os
|
||||||
import queue
|
import queue
|
||||||
import struct
|
import struct
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
@@ -242,6 +242,7 @@ class HIDValconomyHandler(ValconomyHandler):
|
|||||||
self.dev = None
|
self.dev = None
|
||||||
self.running = True
|
self.running = True
|
||||||
self.queue = queue.Queue(128)
|
self.queue = queue.Queue(128)
|
||||||
|
self._thread = None
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.dev is not None:
|
if self.dev is not None:
|
||||||
@@ -285,7 +286,7 @@ class HIDValconomyHandler(ValconomyHandler):
|
|||||||
|
|
||||||
while not self._dev_ready():
|
while not self._dev_ready():
|
||||||
if not self.running:
|
if not self.running:
|
||||||
break
|
return
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -296,10 +297,23 @@ class HIDValconomyHandler(ValconomyHandler):
|
|||||||
def run(self):
|
def run(self):
|
||||||
while self.running:
|
while self.running:
|
||||||
while self.queue.empty():
|
while self.queue.empty():
|
||||||
|
if not self.running:
|
||||||
|
return
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
self.service()
|
self.service()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
assert self._thread is None
|
||||||
|
self._thread = threading.Thread(name='HIDValconomyHandler', target=self.run)
|
||||||
|
self._thread.start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self._thread is None or not self.running:
|
||||||
|
return
|
||||||
|
self.running = False
|
||||||
|
self._thread.join()
|
||||||
|
|
||||||
def none(self):
|
def none(self):
|
||||||
self._enq(0)
|
self._enq(0)
|
||||||
|
|
||||||
@@ -313,6 +327,52 @@ class HIDValconomyHandler(ValconomyHandler):
|
|||||||
ms_not_comp = info.valorant.is_party_owner and info.valorant.queue_type == 'unrated'
|
ms_not_comp = info.valorant.is_party_owner and info.valorant.queue_type == 'unrated'
|
||||||
self._enq(3, 1 if ms_not_comp else 0, fmt='B')
|
self._enq(3, 1 if ms_not_comp else 0, fmt='B')
|
||||||
|
|
||||||
|
def match_found(self, info: RiotPlayerInfo):
|
||||||
|
self._enq(4, 1 if info.valorant.queue_type == 'premier-seasonmatch' else 0, fmt='B')
|
||||||
|
|
||||||
|
def pregame(self, info: RiotPlayerInfo):
|
||||||
|
self._enq(5, 1 if info.valorant.map == '/Game/Maps/Bonsai/Bonsai' else 0, fmt='B')
|
||||||
|
|
||||||
|
def game_generic(self, info: RiotPlayerInfo):
|
||||||
|
match info.valorant.queue_type:
|
||||||
|
case 'hurm': # tdm
|
||||||
|
gm = 0
|
||||||
|
case 'deathmatch':
|
||||||
|
gm = 1
|
||||||
|
case 'ggteam': # escalation
|
||||||
|
gm = 2
|
||||||
|
case 'spikerush':
|
||||||
|
gm = 3
|
||||||
|
case _:
|
||||||
|
if info.valorant.max_party_size == 12: # custom
|
||||||
|
gm = 4
|
||||||
|
else:
|
||||||
|
gm = 5
|
||||||
|
|
||||||
|
self._enq(6, gm, fmt='B')
|
||||||
|
|
||||||
|
def game_start(self, info: RiotPlayerInfo):
|
||||||
|
self._enq(7)
|
||||||
|
|
||||||
|
def round_start(self, info: RiotPlayerInfo, won: bool, economy: EconomyDecision):
|
||||||
|
match won:
|
||||||
|
case False:
|
||||||
|
won_val = 0
|
||||||
|
case True:
|
||||||
|
won_val = 1
|
||||||
|
case None:
|
||||||
|
won_val = 2
|
||||||
|
|
||||||
|
self._enq(
|
||||||
|
8,
|
||||||
|
info.valorant.score, info.valorant.enemy_score,
|
||||||
|
won_val,
|
||||||
|
economy.value,
|
||||||
|
fmt='BBBB')
|
||||||
|
|
||||||
|
def game_over(self, info: RiotPlayerInfo, won: bool):
|
||||||
|
self._enq(9, 1 if won else 0, fmt='B')
|
||||||
|
|
||||||
class GameState(Enum):
|
class GameState(Enum):
|
||||||
NONE = 0
|
NONE = 0
|
||||||
MENU = 1
|
MENU = 1
|
||||||
@@ -348,17 +408,16 @@ class ValconomyStateMachine:
|
|||||||
won_last = True if p.valorant.score > self.score else False
|
won_last = True if p.valorant.score > self.score else False
|
||||||
self.round_history.append(won_last)
|
self.round_history.append(won_last)
|
||||||
|
|
||||||
|
over = False
|
||||||
if p.valorant.queue_type == 'swiftplay':
|
if p.valorant.queue_type == 'swiftplay':
|
||||||
if p.valorant.score == 5 or p.valorant.enemy_score == 5:
|
if p.valorant.score == 5 or p.valorant.enemy_score == 5:
|
||||||
# Game is over
|
over = True
|
||||||
return
|
|
||||||
|
|
||||||
eco = EconomyDecision.BUY
|
eco = EconomyDecision.BUY
|
||||||
else:
|
else:
|
||||||
if p.valorant.score > 12 or p.valorant.enemy_score > 12:
|
if p.valorant.score > 12 or p.valorant.enemy_score > 12:
|
||||||
if p.valorant.queue_type == 'unrated' or abs(p.valorant.score - p.valorant.enemy_score) >= 2:
|
if p.valorant.queue_type == 'unrated' or abs(p.valorant.score - p.valorant.enemy_score) >= 2:
|
||||||
# Match is over
|
over = True
|
||||||
return
|
|
||||||
|
|
||||||
eco = EconomyDecision.MATCH_TEAM
|
eco = EconomyDecision.MATCH_TEAM
|
||||||
rounds_played = p.valorant.score + p.valorant.enemy_score
|
rounds_played = p.valorant.score + p.valorant.enemy_score
|
||||||
@@ -383,8 +442,12 @@ class ValconomyStateMachine:
|
|||||||
elif rounds_played >= 24:
|
elif rounds_played >= 24:
|
||||||
# Sudden death or overtime (buy either way)
|
# Sudden death or overtime (buy either way)
|
||||||
eco = EconomyDecision.BUY
|
eco = EconomyDecision.BUY
|
||||||
|
elif rounds_played == 11:
|
||||||
|
# Last round of half
|
||||||
|
eco = EconomyDecision.BUY
|
||||||
|
|
||||||
self.handler.round_start(p, won_last, eco)
|
if not over:
|
||||||
|
self.handler.round_start(p, won_last, eco)
|
||||||
self.score = p.valorant.score
|
self.score = p.valorant.score
|
||||||
self.score_enemy = p.valorant.enemy_score
|
self.score_enemy = p.valorant.enemy_score
|
||||||
self.last = GameState.IN_GAME
|
self.last = GameState.IN_GAME
|
||||||
|
@@ -2,12 +2,34 @@
|
|||||||
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
||||||
|
const char *val_ext_gamemodes[] = {
|
||||||
|
"TDM",
|
||||||
|
"DEATHMATCH",
|
||||||
|
"ESCALATION",
|
||||||
|
"SPIKE RUSH",
|
||||||
|
"CUSTOM",
|
||||||
|
"GAME",
|
||||||
|
};
|
||||||
|
|
||||||
static const char* M_VAL_TIME = "VAL TIME?";
|
static const char* M_VAL_TIME = "VAL TIME?";
|
||||||
|
static const char *val_eco_titles[] = {
|
||||||
|
"BUY",
|
||||||
|
"SAVE",
|
||||||
|
"BONUS",
|
||||||
|
"MATCH TEAM",
|
||||||
|
};
|
||||||
|
static const char *val_eco_subtitles[] = {
|
||||||
|
"SPEND ALL YOUR MONEY!",
|
||||||
|
"MAKE SURE YOU CAN BUY NEXT ROUND!",
|
||||||
|
"KEEP YOUR GUN FROM LAST ROUND!",
|
||||||
|
"FOLLOW THE TEAM ECONOMY",
|
||||||
|
};
|
||||||
|
|
||||||
static const lv_font_t *font_normal = &lv_font_montserrat_24;
|
static const lv_font_t *font_normal = &lv_font_montserrat_24;
|
||||||
|
|
||||||
static lv_color_t color_primary, color_secondary;
|
static lv_color_t color_primary, color_secondary;
|
||||||
static lv_color_t color_text_hero, color_text_subtitle;
|
static lv_color_t color_text_hero, color_text_subtitle;
|
||||||
|
static lv_color_t color_text_won, color_text_lost;
|
||||||
|
|
||||||
static lv_style_t s_hero, s_subtitle;
|
static lv_style_t s_hero, s_subtitle;
|
||||||
|
|
||||||
@@ -66,6 +88,7 @@ static void setup_next_state() {
|
|||||||
lv_obj_set_style_bg_opa(o_active, LV_OPA_0, 0);
|
lv_obj_set_style_bg_opa(o_active, LV_OPA_0, 0);
|
||||||
lv_obj_set_style_border_width(o_active, 0, 0);
|
lv_obj_set_style_border_width(o_active, 0, 0);
|
||||||
lv_obj_set_size(o_active, lv_pct(100), lv_pct(100));
|
lv_obj_set_size(o_active, lv_pct(100), lv_pct(100));
|
||||||
|
lv_obj_set_scrollbar_mode(o_active, LV_SCROLLBAR_MODE_OFF);
|
||||||
|
|
||||||
at_active = lv_anim_timeline_create();
|
at_active = lv_anim_timeline_create();
|
||||||
at_active_rep = lv_anim_timeline_create();
|
at_active_rep = lv_anim_timeline_create();
|
||||||
@@ -183,7 +206,7 @@ void val_ui_menu(bool was_idle) {
|
|||||||
lv_anim_set_var(&a_title, l_main);
|
lv_anim_set_var(&a_title, l_main);
|
||||||
lv_anim_set_values(
|
lv_anim_set_values(
|
||||||
&a_title,
|
&a_title,
|
||||||
-(lv_obj_get_height(o_container) - lv_obj_get_height(l_main)) / 2, 0);
|
-(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2, 0);
|
||||||
lv_anim_set_exec_cb(&a_title, anim_y_cb);
|
lv_anim_set_exec_cb(&a_title, anim_y_cb);
|
||||||
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_in);
|
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_in);
|
||||||
lv_anim_set_duration(&a_title, 500);
|
lv_anim_set_duration(&a_title, 500);
|
||||||
@@ -193,7 +216,7 @@ void val_ui_menu(bool was_idle) {
|
|||||||
lv_anim_set_var(&a_sub, l_subtitle);
|
lv_anim_set_var(&a_sub, l_subtitle);
|
||||||
lv_anim_set_values(
|
lv_anim_set_values(
|
||||||
&a_sub,
|
&a_sub,
|
||||||
(lv_obj_get_height(o_container) - lv_obj_get_height(l_main)) / 2,
|
(lv_obj_get_height(o_container) + lv_obj_get_height(l_subtitle)) / 2,
|
||||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||||
lv_anim_set_exec_cb(&a_sub, anim_y_cb);
|
lv_anim_set_exec_cb(&a_sub, anim_y_cb);
|
||||||
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_in);
|
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_in);
|
||||||
@@ -284,7 +307,7 @@ void val_ui_queue_start(bool ms_not_comp) {
|
|||||||
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||||
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||||
lv_obj_center(l_subtitle);
|
lv_obj_center(l_subtitle);
|
||||||
lv_label_set_text_static(l_subtitle, ms_not_comp ? "UHHH SHOULD THAT BE COMP?" : "I HOPE IT'S NOT SPLIT...");
|
lv_label_set_text_static(l_subtitle, ms_not_comp ? "UHHH SHOULD THAT BE COMP?" : "HOPE YOU FIND A GAME QUICKLY!");
|
||||||
|
|
||||||
lv_obj_t *spinner = lv_spinner_create(o_active);
|
lv_obj_t *spinner = lv_spinner_create(o_active);
|
||||||
lv_obj_set_size(spinner, 100, 100);
|
lv_obj_set_size(spinner, 100, 100);
|
||||||
@@ -301,7 +324,6 @@ void val_ui_queue_start(bool ms_not_comp) {
|
|||||||
lv_obj_set_y(
|
lv_obj_set_y(
|
||||||
spinner,
|
spinner,
|
||||||
lv_obj_get_height(o_container) / 4);
|
lv_obj_get_height(o_container) / 4);
|
||||||
// offset + (lv_obj_get_height(l_main)/2) + lv_obj_get_height(l_subtitle) + (lv_obj_get_height(spinner)/2) + 15);
|
|
||||||
|
|
||||||
// Animations
|
// Animations
|
||||||
lv_anim_t a_title;
|
lv_anim_t a_title;
|
||||||
@@ -309,7 +331,7 @@ void val_ui_queue_start(bool ms_not_comp) {
|
|||||||
lv_anim_set_var(&a_title, l_main);
|
lv_anim_set_var(&a_title, l_main);
|
||||||
lv_anim_set_values(
|
lv_anim_set_values(
|
||||||
&a_title,
|
&a_title,
|
||||||
-(lv_obj_get_width(o_container) - lv_obj_get_width(l_main)) / 2, 0);
|
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_main)) / 2, 0);
|
||||||
lv_anim_set_exec_cb(&a_title, anim_x_cb);
|
lv_anim_set_exec_cb(&a_title, anim_x_cb);
|
||||||
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_out);
|
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_out);
|
||||||
lv_anim_set_duration(&a_title, 750);
|
lv_anim_set_duration(&a_title, 750);
|
||||||
@@ -319,7 +341,7 @@ void val_ui_queue_start(bool ms_not_comp) {
|
|||||||
lv_anim_set_var(&a_sub, l_subtitle);
|
lv_anim_set_var(&a_sub, l_subtitle);
|
||||||
lv_anim_set_values(
|
lv_anim_set_values(
|
||||||
&a_sub,
|
&a_sub,
|
||||||
(lv_obj_get_width(o_container) - lv_obj_get_width(l_subtitle)) / 2, 0);
|
(lv_obj_get_width(o_container) + lv_obj_get_width(l_subtitle)) / 2, 0);
|
||||||
lv_anim_set_exec_cb(&a_sub, anim_x_cb);
|
lv_anim_set_exec_cb(&a_sub, anim_x_cb);
|
||||||
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_out);
|
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_out);
|
||||||
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
||||||
@@ -347,19 +369,354 @@ void val_ui_queue_start(bool ms_not_comp) {
|
|||||||
lv_anim_timeline_start(at_active);
|
lv_anim_timeline_start(at_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void val_ui_match_found(bool is_premier) {
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
lv_obj_t *l_main = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_main, &s_hero, 0);
|
||||||
|
lv_obj_center(l_main);
|
||||||
|
lv_label_set_text_static(l_main, "MATCH FOUND");
|
||||||
|
|
||||||
|
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||||
|
lv_obj_center(l_subtitle);
|
||||||
|
lv_label_set_text_static(l_subtitle, is_premier ? "DO THE COSMONAUTS PROUD!" : "I HOPE IT'S NOT SPLIT...");
|
||||||
|
|
||||||
|
lv_obj_update_layout(o_active);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
lv_anim_t a_title;
|
||||||
|
lv_anim_init(&a_title);
|
||||||
|
lv_anim_set_var(&a_title, l_main);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_title,
|
||||||
|
(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2, 0);
|
||||||
|
lv_anim_set_exec_cb(&a_title, anim_y_cb);
|
||||||
|
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_duration(&a_title, 500);
|
||||||
|
|
||||||
|
lv_anim_t a_sub;
|
||||||
|
lv_anim_init(&a_sub);
|
||||||
|
lv_anim_set_var(&a_sub, l_subtitle);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_sub,
|
||||||
|
-(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2,
|
||||||
|
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||||
|
lv_anim_set_exec_cb(&a_sub, anim_y_cb);
|
||||||
|
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
||||||
|
lv_anim_set_duration(&a_sub, 500);
|
||||||
|
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_title);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||||
|
lv_anim_timeline_start(at_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void val_ui_pregame(bool is_split) {
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
lv_obj_t *l_main = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_main, &s_hero, 0);
|
||||||
|
lv_obj_center(l_main);
|
||||||
|
lv_label_set_text_static(l_main, "CHOOSE AGENT");
|
||||||
|
|
||||||
|
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||||
|
lv_obj_center(l_subtitle);
|
||||||
|
lv_label_set_text_static(l_subtitle, is_split ? "EWWW, SPLIT..." : "PICK SOMETHING GOOD!");
|
||||||
|
|
||||||
|
lv_obj_update_layout(o_active);
|
||||||
|
lv_obj_set_y(
|
||||||
|
l_subtitle,
|
||||||
|
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
lv_anim_t a_fade_in;
|
||||||
|
lv_anim_init(&a_fade_in);
|
||||||
|
lv_anim_set_values(&a_fade_in, 0, 255);
|
||||||
|
lv_anim_set_exec_cb(&a_fade_in, anim_opa_cb);
|
||||||
|
lv_anim_set_path_cb(&a_fade_in, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_duration(&a_fade_in, 500);
|
||||||
|
|
||||||
|
lv_anim_set_var(&a_fade_in, l_main);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||||
|
|
||||||
|
lv_anim_set_var(&a_fade_in, l_subtitle);
|
||||||
|
lv_anim_set_completed_cb(&a_fade_in, anim_state_ready_cb);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||||
|
|
||||||
|
lv_anim_t a_warn;
|
||||||
|
lv_anim_init(&a_warn);
|
||||||
|
lv_anim_set_early_apply(&a_warn, false);
|
||||||
|
lv_anim_set_var(&a_warn, l_main);
|
||||||
|
lv_anim_set_path_cb(&a_warn, lv_anim_path_linear);
|
||||||
|
lv_anim_set_duration(&a_warn, 2000);
|
||||||
|
lv_anim_set_exec_cb(&a_warn, anim_text_color_mix_hero_sub);
|
||||||
|
|
||||||
|
lv_anim_set_values(&a_warn, 255, 0);
|
||||||
|
lv_anim_timeline_add(at_active_rep, 0, &a_warn);
|
||||||
|
|
||||||
|
lv_anim_set_values(&a_warn, 0, 255);
|
||||||
|
lv_anim_timeline_add(at_active_rep, 2000, &a_warn);
|
||||||
|
|
||||||
|
lv_anim_timeline_start(at_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void val_ui_game_generic(const char *gamemode) {
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
lv_obj_t *l_main = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_main, &s_hero, 0);
|
||||||
|
lv_obj_center(l_main);
|
||||||
|
lv_label_set_text_static(l_main, "HAVE FUN!");
|
||||||
|
|
||||||
|
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||||
|
lv_obj_center(l_subtitle);
|
||||||
|
lv_label_set_text_fmt(l_subtitle, "ENJOY YOUR %s!", gamemode);
|
||||||
|
|
||||||
|
lv_obj_update_layout(o_active);
|
||||||
|
lv_obj_set_y(
|
||||||
|
l_subtitle,
|
||||||
|
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
lv_anim_t a_title;
|
||||||
|
lv_anim_init(&a_title);
|
||||||
|
lv_anim_set_var(&a_title, l_main);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_title,
|
||||||
|
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_main)) / 2, 0);
|
||||||
|
lv_anim_set_exec_cb(&a_title, anim_x_cb);
|
||||||
|
lv_anim_set_path_cb(&a_title, lv_anim_path_bounce);
|
||||||
|
lv_anim_set_duration(&a_title, 750);
|
||||||
|
|
||||||
|
lv_anim_t a_sub;
|
||||||
|
lv_anim_init(&a_sub);
|
||||||
|
lv_anim_set_var(&a_sub, l_subtitle);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_sub,
|
||||||
|
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_subtitle)) / 2,
|
||||||
|
-(lv_obj_get_width(l_main) - lv_obj_get_width(l_subtitle)) / 2);
|
||||||
|
lv_anim_set_exec_cb(&a_sub, anim_x_cb);
|
||||||
|
lv_anim_set_path_cb(&a_sub, lv_anim_path_bounce);
|
||||||
|
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
||||||
|
lv_anim_set_duration(&a_sub, 750);
|
||||||
|
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_title);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||||
|
lv_anim_timeline_start(at_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void val_ui_game_start() {
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
lv_obj_t *l_main = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_main, &s_hero, 0);
|
||||||
|
lv_obj_center(l_main);
|
||||||
|
lv_label_set_text_static(l_main, "GOOD LUCK!");
|
||||||
|
|
||||||
|
state_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void anim_text_color_mix_hero_won(void *var, int32_t v) {
|
||||||
|
lv_obj_set_style_text_color(
|
||||||
|
var, lv_color_mix(color_text_hero, color_text_won, v), 0);
|
||||||
|
}
|
||||||
|
static void anim_text_color_mix_hero_lost(void *var, int32_t v) {
|
||||||
|
lv_obj_set_style_text_color(
|
||||||
|
var, lv_color_mix(color_text_hero, color_text_lost, v), 0);
|
||||||
|
}
|
||||||
|
void val_ui_round_start(uint8_t score, uint8_t score_enemy, val_won_t won, val_eco_decision_t eco) {
|
||||||
|
assert(won <= ROUND_NONE && eco <= ECO_MATCH_TEAM);
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
lv_obj_t *l_score = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_score, &s_hero, 0);
|
||||||
|
lv_obj_center(l_score);
|
||||||
|
lv_label_set_text_fmt(l_score, "%hhu-%hhu", score, score_enemy);
|
||||||
|
|
||||||
|
lv_obj_t *l_eco = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_eco, &s_hero, 0);
|
||||||
|
lv_obj_center(l_eco);
|
||||||
|
lv_label_set_text_static(l_eco, val_eco_titles[eco]);
|
||||||
|
|
||||||
|
lv_obj_t *l_advice = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_advice, &s_subtitle, 0);
|
||||||
|
lv_obj_center(l_advice);
|
||||||
|
lv_label_set_text_static(l_advice, val_eco_subtitles[eco]);
|
||||||
|
|
||||||
|
lv_obj_update_layout(o_active);
|
||||||
|
lv_obj_set_y(
|
||||||
|
l_score,
|
||||||
|
-(lv_obj_get_height(l_score) / 2) - 20);
|
||||||
|
lv_obj_set_y(
|
||||||
|
l_eco,
|
||||||
|
lv_obj_get_height(l_eco) / 2);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
// Score and eco fade in
|
||||||
|
lv_anim_t a_fade_in;
|
||||||
|
lv_anim_init(&a_fade_in);
|
||||||
|
lv_anim_set_values(&a_fade_in, 0, 255);
|
||||||
|
lv_anim_set_exec_cb(&a_fade_in, anim_opa_cb);
|
||||||
|
lv_anim_set_path_cb(&a_fade_in, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_duration(&a_fade_in, 750);
|
||||||
|
|
||||||
|
lv_anim_set_var(&a_fade_in, l_score);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||||
|
|
||||||
|
lv_anim_set_var(&a_fade_in, l_eco);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||||
|
|
||||||
|
// Advice slide up
|
||||||
|
lv_anim_t a_advice;
|
||||||
|
lv_anim_init(&a_advice);
|
||||||
|
lv_anim_set_var(&a_advice, l_advice);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_advice,
|
||||||
|
(lv_obj_get_height(o_container) + lv_obj_get_height(l_advice)) / 2,
|
||||||
|
lv_obj_get_height(l_eco) + (lv_obj_get_height(l_advice) / 2) + 5);
|
||||||
|
lv_anim_set_exec_cb(&a_advice, anim_y_cb);
|
||||||
|
lv_anim_set_path_cb(&a_advice, lv_anim_path_ease_out);
|
||||||
|
lv_anim_set_duration(&a_advice, 750);
|
||||||
|
|
||||||
|
if (won != ROUND_NONE) {
|
||||||
|
// Score colour
|
||||||
|
lv_anim_t a_score;
|
||||||
|
lv_anim_init(&a_score);
|
||||||
|
lv_anim_set_var(&a_score, l_score);
|
||||||
|
lv_anim_set_path_cb(&a_score, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_exec_cb(
|
||||||
|
&a_score,
|
||||||
|
won == ROUND_WON ? anim_text_color_mix_hero_won : anim_text_color_mix_hero_lost);
|
||||||
|
lv_anim_set_duration(&a_score, 2000);
|
||||||
|
lv_anim_set_values(&a_score, 0, 255);
|
||||||
|
lv_anim_set_completed_cb(&a_score, anim_state_ready_cb);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_score);
|
||||||
|
} else {
|
||||||
|
lv_anim_set_completed_cb(&a_advice, anim_state_ready_cb);
|
||||||
|
}
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_advice);
|
||||||
|
|
||||||
|
// Eco flash
|
||||||
|
lv_anim_t a_eco;
|
||||||
|
lv_anim_init(&a_eco);
|
||||||
|
lv_anim_set_early_apply(&a_eco, false);
|
||||||
|
lv_anim_set_var(&a_eco, l_eco);
|
||||||
|
lv_anim_set_path_cb(&a_eco, lv_anim_path_linear);
|
||||||
|
lv_anim_set_duration(&a_eco, 1000);
|
||||||
|
lv_anim_set_exec_cb(&a_eco, anim_text_color_mix_hero_sub);
|
||||||
|
|
||||||
|
lv_anim_set_values(&a_eco, 255, 0);
|
||||||
|
lv_anim_timeline_add(at_active_rep, 0, &a_eco);
|
||||||
|
|
||||||
|
lv_anim_set_values(&a_eco, 0, 255);
|
||||||
|
lv_anim_timeline_add(at_active_rep, 1000, &a_eco);
|
||||||
|
|
||||||
|
lv_anim_timeline_start(at_active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void val_ui_game_over(bool won) {
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
lv_obj_t *l_main = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_main, &s_hero, 0);
|
||||||
|
lv_obj_center(l_main);
|
||||||
|
lv_label_set_text_static(l_main, won ? "VICTORY" : "DEFEAT");
|
||||||
|
lv_obj_set_style_text_color(l_main, won ? color_text_won : color_text_lost, 0);
|
||||||
|
|
||||||
|
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||||
|
lv_obj_center(l_subtitle);
|
||||||
|
lv_label_set_text_static(l_subtitle, won ? "WELL PLAYED!" : "HARD LUCK...");
|
||||||
|
|
||||||
|
lv_obj_update_layout(o_active);
|
||||||
|
lv_obj_set_y(
|
||||||
|
l_subtitle,
|
||||||
|
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
if (won) {
|
||||||
|
lv_anim_t a_fly;
|
||||||
|
lv_anim_init(&a_fly);
|
||||||
|
lv_anim_set_path_cb(&a_fly, lv_anim_path_ease_out);
|
||||||
|
lv_anim_set_duration(&a_fly, 750);
|
||||||
|
|
||||||
|
// Main text from top-left
|
||||||
|
// Y
|
||||||
|
lv_anim_set_var(&a_fly, l_main);
|
||||||
|
lv_anim_set_exec_cb(&a_fly, anim_y_cb);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_fly,
|
||||||
|
-(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2, 0);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||||
|
|
||||||
|
// X
|
||||||
|
lv_anim_set_exec_cb(&a_fly, anim_x_cb);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_fly,
|
||||||
|
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_main)) / 2, 0);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||||
|
|
||||||
|
|
||||||
|
// Subtitle from bottom-right
|
||||||
|
// Y
|
||||||
|
lv_anim_set_var(&a_fly, l_subtitle);
|
||||||
|
lv_anim_set_exec_cb(&a_fly, anim_y_cb);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_fly,
|
||||||
|
(lv_obj_get_height(o_container) + lv_obj_get_height(l_subtitle)) / 2,
|
||||||
|
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||||
|
|
||||||
|
// X
|
||||||
|
lv_anim_set_exec_cb(&a_fly, anim_x_cb);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_fly,
|
||||||
|
(lv_obj_get_width(o_container) + lv_obj_get_width(l_subtitle)) / 2, 0);
|
||||||
|
lv_anim_set_completed_cb(&a_fly, anim_state_ready_cb);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||||
|
} else {
|
||||||
|
lv_anim_t a_fade_in;
|
||||||
|
lv_anim_init(&a_fade_in);
|
||||||
|
lv_anim_set_values(&a_fade_in, 0, 255);
|
||||||
|
lv_anim_set_exec_cb(&a_fade_in, anim_opa_cb);
|
||||||
|
lv_anim_set_path_cb(&a_fade_in, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_duration(&a_fade_in, 1000);
|
||||||
|
|
||||||
|
lv_anim_set_var(&a_fade_in, l_main);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||||
|
|
||||||
|
lv_anim_set_var(&a_fade_in, l_subtitle);
|
||||||
|
lv_anim_set_completed_cb(&a_fade_in, anim_state_ready_cb);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_anim_timeline_start(at_active);
|
||||||
|
}
|
||||||
|
|
||||||
void val_lvgl_ui(lv_display_t *disp) {
|
void val_lvgl_ui(lv_display_t *disp) {
|
||||||
color_primary = lv_color_hex(0xff4655);
|
color_primary = lv_color_hex(0xff4655);
|
||||||
color_secondary = lv_color_hex(0xf7518f);
|
color_secondary = lv_color_hex(0xf7518f);
|
||||||
|
|
||||||
color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
|
color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
|
||||||
color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 1);
|
color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 1);
|
||||||
|
color_text_won = lv_palette_lighten(LV_PALETTE_GREEN, 1);
|
||||||
|
color_text_lost = lv_palette_darken(LV_PALETTE_RED, 4);
|
||||||
|
|
||||||
// init default theme
|
// init default theme
|
||||||
lv_theme_default_init(
|
lv_theme_default_init(
|
||||||
disp, color_primary, color_secondary,
|
disp, color_primary, color_secondary,
|
||||||
true, // dark theme
|
true, // dark theme
|
||||||
font_normal);
|
font_normal);
|
||||||
// lv_sysmon_hide_performance(disp);
|
lv_sysmon_hide_performance(disp);
|
||||||
|
|
||||||
lv_font_t *f_hero_emoji = lv_imgfont_create(120, imgfont_get_path, NULL);
|
lv_font_t *f_hero_emoji = lv_imgfont_create(120, imgfont_get_path, NULL);
|
||||||
assert(f_hero_emoji);
|
assert(f_hero_emoji);
|
||||||
@@ -383,6 +740,7 @@ void val_lvgl_ui(lv_display_t *disp) {
|
|||||||
lv_obj_set_style_border_width(o_container, 0, 0);
|
lv_obj_set_style_border_width(o_container, 0, 0);
|
||||||
lv_obj_set_style_pad_all(o_container, 0, 0);
|
lv_obj_set_style_pad_all(o_container, 0, 0);
|
||||||
lv_obj_set_size(o_container, lv_pct(100), lv_pct(100));
|
lv_obj_set_size(o_container, lv_pct(100), lv_pct(100));
|
||||||
|
lv_obj_set_scrollbar_mode(o_container, LV_SCROLLBAR_MODE_OFF);
|
||||||
|
|
||||||
// Settings button
|
// Settings button
|
||||||
lv_obj_t *b_cfg = lv_button_create(lv_screen_active());
|
lv_obj_t *b_cfg = lv_button_create(lv_screen_active());
|
||||||
|
@@ -2,6 +2,21 @@
|
|||||||
|
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
extern const char *val_ext_gamemodes[];
|
||||||
|
#define VAL_EXT_GAMEMODES_SIZE 6
|
||||||
|
|
||||||
|
typedef enum val_eco_decision {
|
||||||
|
ECO_BUY,
|
||||||
|
ECO_SAVE,
|
||||||
|
ECO_BONUS,
|
||||||
|
ECO_MATCH_TEAM,
|
||||||
|
} val_eco_decision_t;
|
||||||
|
typedef enum val_won {
|
||||||
|
ROUND_LOST,
|
||||||
|
ROUND_WON,
|
||||||
|
ROUND_NONE,
|
||||||
|
} val_won_t;
|
||||||
|
|
||||||
LV_FONT_DECLARE(lv_font_tungsten_40)
|
LV_FONT_DECLARE(lv_font_tungsten_40)
|
||||||
LV_FONT_DECLARE(lv_font_tungsten_180)
|
LV_FONT_DECLARE(lv_font_tungsten_180)
|
||||||
|
|
||||||
@@ -16,5 +31,11 @@ void val_ui_none();
|
|||||||
void val_ui_menu(bool was_idle);
|
void val_ui_menu(bool was_idle);
|
||||||
void val_ui_idle();
|
void val_ui_idle();
|
||||||
void val_ui_queue_start(bool ms_not_comp);
|
void val_ui_queue_start(bool ms_not_comp);
|
||||||
|
void val_ui_match_found(bool is_premier);
|
||||||
|
void val_ui_pregame(bool is_split);
|
||||||
|
void val_ui_game_generic(const char *gamemode);
|
||||||
|
void val_ui_game_start();
|
||||||
|
void val_ui_round_start(uint8_t score, uint8_t score_enemy, val_won_t won, val_eco_decision_t eco);
|
||||||
|
void val_ui_game_over(bool won);
|
||||||
|
|
||||||
void val_lvgl_ui(lv_display_t *disp);
|
void val_lvgl_ui(lv_display_t *disp);
|
||||||
|
@@ -101,7 +101,7 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
|||||||
ESP_LOGE(TAG, "Failed to grab LVGL lock");
|
ESP_LOGE(TAG, "Failed to grab LVGL lock");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (buf[0] > ST_QUEUE_START) {
|
if (buf[0] > ST_GAME_OVER) {
|
||||||
ESP_LOGW(TAG, "Unknown state %hhu", buf[0]);
|
ESP_LOGW(TAG, "Unknown state %hhu", buf[0]);
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
@@ -130,6 +130,44 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
|||||||
}
|
}
|
||||||
val_ui_queue_start((bool)buf[1]);
|
val_ui_queue_start((bool)buf[1]);
|
||||||
break;
|
break;
|
||||||
|
case ST_MATCH_FOUND:
|
||||||
|
if (bufsize < 2) {
|
||||||
|
ESP_LOGE(TAG, "Invalid ST_MATCH_FOUND command");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
val_ui_match_found((bool)buf[1]);
|
||||||
|
break;
|
||||||
|
case ST_PREGAME:
|
||||||
|
if (bufsize < 2) {
|
||||||
|
ESP_LOGE(TAG, "Invalid ST_PREGAME command");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
val_ui_pregame((bool)buf[1]);
|
||||||
|
break;
|
||||||
|
case ST_GAME_GENERIC:
|
||||||
|
if (bufsize < 2 || buf[1] > VAL_EXT_GAMEMODES_SIZE) {
|
||||||
|
ESP_LOGE(TAG, "Invalid ST_PREGAME command");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
val_ui_game_generic(val_ext_gamemodes[buf[1]]);
|
||||||
|
break;
|
||||||
|
case ST_GAME_START:
|
||||||
|
val_ui_game_start();
|
||||||
|
break;
|
||||||
|
case ST_ROUND_START:
|
||||||
|
if (bufsize < 5 || buf[3] > ROUND_NONE || buf[4] > ECO_MATCH_TEAM) {
|
||||||
|
ESP_LOGE(TAG, "Invalid ST_ROUND_START command");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
val_ui_round_start(buf[1], buf[2], buf[3], buf[4]);
|
||||||
|
break;
|
||||||
|
case ST_GAME_OVER:
|
||||||
|
if (bufsize < 2) {
|
||||||
|
ESP_LOGE(TAG, "Invalid ST_GAME_OVER command");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
val_ui_game_over((bool)buf[1]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret:
|
ret:
|
||||||
|
@@ -10,6 +10,12 @@ typedef enum val_state {
|
|||||||
ST_MENU,
|
ST_MENU,
|
||||||
ST_IDLE,
|
ST_IDLE,
|
||||||
ST_QUEUE_START,
|
ST_QUEUE_START,
|
||||||
|
ST_MATCH_FOUND,
|
||||||
|
ST_PREGAME,
|
||||||
|
ST_GAME_GENERIC,
|
||||||
|
ST_GAME_START,
|
||||||
|
ST_ROUND_START,
|
||||||
|
ST_GAME_OVER,
|
||||||
} val_state_t;
|
} val_state_t;
|
||||||
|
|
||||||
void val_usb_init(void);
|
void val_usb_init(void);
|
||||||
|
Reference in New Issue
Block a user