mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 19:50:12 +01:00
finally refactor the song select boxes
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ cache
|
|||||||
dev-config.toml
|
dev-config.toml
|
||||||
libaudio.so
|
libaudio.so
|
||||||
latest.log
|
latest.log
|
||||||
|
Graphics1080
|
||||||
|
|||||||
@@ -1,86 +1,86 @@
|
|||||||
Command/Header,Support Status,Initial Sim Release
|
Command/Header,Support Status,Initial Sim Release
|
||||||
TITLE,Supported,TaikoJiro v0.80 (initial release)
|
TITLE,Supported,TaikoJiro v0.80 (initial release)
|
||||||
SUBTITLE,Supported,TaikoJiro v2.64
|
|
||||||
WAVE,Supported,TaikoJiro v0.80 (initial release)
|
WAVE,Supported,TaikoJiro v0.80 (initial release)
|
||||||
DEMOSTART,Supported,TaikoJiro v2.37
|
|
||||||
OFFSET,Supported,TaikoJiro v0.80 (initial release)
|
OFFSET,Supported,TaikoJiro v0.80 (initial release)
|
||||||
BPM,Supported,TaikoJiro v0.80 (initial release)
|
BPM,Supported,TaikoJiro v0.80 (initial release)
|
||||||
SCENEPRESET,Supported,OpenTaiko (0auBSQ) v0.6.0
|
|
||||||
BGMOVIE,Supported,TJAPlayer2 for.PC ver.2016021300
|
|
||||||
COURSE,Supported,TaikoJiro v1.76
|
|
||||||
LEVEL,Supported,TaikoJiro v0.80 (initial release)
|
LEVEL,Supported,TaikoJiro v0.80 (initial release)
|
||||||
BALLOON,Supported,TaikoJiro
|
BALLOON,Supported,TaikoJiro
|
||||||
|
COURSE,Supported,TaikoJiro v1.76
|
||||||
|
DEMOSTART,Supported,TaikoJiro v2.37
|
||||||
|
SUBTITLE,Supported,TaikoJiro v2.64
|
||||||
|
BGMOVIE,Supported,TJAPlayer2 for.PC ver.2016021300
|
||||||
|
SCENEPRESET,Supported,OpenTaiko (0auBSQ) v0.6.0
|
||||||
|
|
||||||
#START / #END,Supported,TaikoJiro v0.80 (initial release)
|
#START / #END,Supported,TaikoJiro v0.80 (initial release)
|
||||||
#BPMCHANGE,Supported,TaikoJiro v0.80 (initial release)
|
#BPMCHANGE,Supported,TaikoJiro v0.80 (initial release)
|
||||||
#MEASURE,Supported,TaikoJiro
|
#MEASURE,Supported,TaikoJiro
|
||||||
#GOGOSTART / #GOGOEND,Supported,TaikoJiro
|
#GOGOSTART / #GOGOEND,Supported,TaikoJiro
|
||||||
#SCROLL,Supported,TaikoJiro
|
#SCROLL,Supported,TaikoJiro
|
||||||
#BARLINEOFF / #BARLINEON,Supported,TaikoJiro v2.69
|
#DELAY,Supported,TaikoJiro v1.60
|
||||||
#LYRIC,Supported,TJAPlayer2 for.PC
|
|
||||||
#SECTION,Supported,TaikoJiro v1.63
|
#SECTION,Supported,TaikoJiro v1.63
|
||||||
#BRANCHSTART / #BRANCHEND,Supported,TaikoJiro v1.63
|
#BRANCHSTART / #BRANCHEND,Supported,TaikoJiro v1.63
|
||||||
#N / #E / #M,Supported,TaikoJiro v1.63
|
#N / #E / #M,Supported,TaikoJiro v1.63
|
||||||
#DELAY,Supported,TaikoJiro v1.60
|
#BARLINEOFF / #BARLINEON,Supported,TaikoJiro v2.69
|
||||||
|
#LYRIC,Supported,TJAPlayer2 for.PC
|
||||||
#SUDDEN,Supported,TJAPlayer2 for.PC
|
#SUDDEN,Supported,TJAPlayer2 for.PC
|
||||||
#JPOSSCROLL,Supported,TJAPlayer2 for.PC
|
#JPOSSCROLL,Supported,TJAPlayer2 for.PC
|
||||||
|
|
||||||
ARTIST,Unsupported,Malody
|
|
||||||
MAKER,Unsupported,taiko-web ver.19.11.25
|
|
||||||
NOTESDESIGNER,Unsupported,(Better)TaikoCatsCaffe
|
|
||||||
AUTHOR,Unsupported,Malody
|
|
||||||
GENRE,Unsupported,TJAPlayer2 for.PC
|
|
||||||
SIDE,Unsupported,TaikoJiro v2.49
|
|
||||||
SIDEREV,Unsupported,TaikoJiro 2 v0.70
|
|
||||||
SONGVOL,Unsupported,TaikoJiro v1.66
|
SONGVOL,Unsupported,TaikoJiro v1.66
|
||||||
SEVOL,Unsupported,TaikoJiro v1.66
|
SEVOL,Unsupported,TaikoJiro v1.66
|
||||||
|
SCOREINIT,Unsupported,TaikoJiro v1.67
|
||||||
|
SCOREDIFF,Unsupported,TaikoJiro v1.67
|
||||||
|
STYLE,Unsupported,TaikoJiro v1.99
|
||||||
|
GAME,Unsupported,TaikoJiro v2.13
|
||||||
|
LIFE,Unsupported,TaikoJiro v2.19
|
||||||
|
SIDE,Unsupported,TaikoJiro v2.49
|
||||||
|
SCOREMODE,Unsupported,TaikoJiro v2.85
|
||||||
|
SIDEREV,Unsupported,TaikoJiro 2 v0.70
|
||||||
|
TOTAL,Unsupported,TaikoJiro v2.92 & TaikoJiro 2 v0.93
|
||||||
|
GENRE,Unsupported,TJAPlayer2 for.PC
|
||||||
|
HIDDENBRANCH,Unsupported,TJAPlayer2 for.PC
|
||||||
HEADSCROLL,Unsupported,TJAPlayer2 for.PC
|
HEADSCROLL,Unsupported,TJAPlayer2 for.PC
|
||||||
PREIMAGE,Unsupported,OpenTaiko (0auBSQ) v0.5.4
|
MOVIEOFFSET,Unsupported,TJAPlayer2 for.PC ver.2015081100
|
||||||
COVER,Unsupported,Malody
|
BGIMAGE,Unsupported,TJAPlayer2 for.PC ver.2016021300
|
||||||
|
EXAM,Unsupported,TJAPlayer3 v1.5.0
|
||||||
|
GAUGEINCR,Unsupported,TJAPlayer3 v1.5.4
|
||||||
TAIKOWEBSKIN,Unsupported,taiko-web ver.19.02.03
|
TAIKOWEBSKIN,Unsupported,taiko-web ver.19.02.03
|
||||||
|
MAKER,Unsupported,taiko-web ver.19.11.25
|
||||||
|
LYRICS: / LYRICFILE,Unsupported,taiko-web ver.20.03.31
|
||||||
|
NOTESDESIGNER,Unsupported,(Better)TaikoCatsCaffe
|
||||||
TOWERTYPE,Unsupported,OpenTaiko (0auBSQ) v0.5.0
|
TOWERTYPE,Unsupported,OpenTaiko (0auBSQ) v0.5.0
|
||||||
DANTICK,Unsupported,OpenTaiko (0auBSQ) v0.5.1
|
DANTICK,Unsupported,OpenTaiko (0auBSQ) v0.5.1
|
||||||
DANTICKCOLOR,Unsupported,OpenTaiko (0auBSQ) v0.5.1
|
DANTICKCOLOR,Unsupported,OpenTaiko (0auBSQ) v0.5.1
|
||||||
|
PREIMAGE,Unsupported,OpenTaiko (0auBSQ) v0.5.4
|
||||||
SELECTBG,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
SELECTBG,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
||||||
BGIMAGE,Unsupported,TJAPlayer2 for.PC ver.2016021300
|
|
||||||
BGOFFSET,Unsupported,Unknown
|
|
||||||
MOVIEOFFSET,Unsupported,TJAPlayer2 for.PC ver.2015081100
|
|
||||||
BGA Headers,Unsupported,C-Taiko
|
|
||||||
LYRICS: / LYRICFILE,Unsupported,taiko-web ver.20.03.31
|
|
||||||
EXPLICIT,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
EXPLICIT,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
||||||
GAME,Unsupported,TaikoJiro v2.13
|
BGA Headers,Unsupported,C-Taiko
|
||||||
STYLE,Unsupported,TaikoJiro v1.99
|
ARTIST,Unsupported,Malody
|
||||||
LIFE,Unsupported,TaikoJiro v2.19
|
COVER,Unsupported,Malody
|
||||||
TOTAL,Unsupported,TaikoJiro v2.92 & TaikoJiro 2 v0.93
|
AUTHOR,Unsupported,Malody
|
||||||
GAUGEINCR,Unsupported,TJAPlayer3 v1.5.4
|
BGOFFSET,Unsupported,Unknown
|
||||||
EXAM,Unsupported,TJAPlayer3 v1.5.0
|
|
||||||
SCOREMODE,Unsupported,TaikoJiro v2.85
|
|
||||||
SCOREINIT,Unsupported,TaikoJiro v1.67
|
|
||||||
SCOREDIFF,Unsupported,TaikoJiro v1.67
|
|
||||||
HIDDENBRANCH,Unsupported,TJAPlayer2 for.PC
|
|
||||||
|
|
||||||
#BMSCROLL / #HBSCROLL / #NMSCROLL,Unsupported,TaikoJiro v1.91
|
|
||||||
#PAPAMAMA,Unsupported,TJAPlayer3-f v1.7.2.0
|
|
||||||
#DUMMYSTART / #DUMMYEND,Unsupported,TaikoManyGimmicks
|
|
||||||
#BARLINESCROLL,Unsupported,taiko-web (plugin Custom Barlines)
|
|
||||||
#HISPEED,Unsupported,TaikoManyGimmicks v0.6.1α
|
|
||||||
#DIRECTION,Unsupported,TJAPlayer2 for.PC
|
|
||||||
#BARLINE,Unsupported,taiko-web (plugin Custom Barlines)
|
|
||||||
#JUDGEDELAY,Unsupported,TaikoManyGimmicks
|
|
||||||
#NOTESPAWN,Unsupported,TaikoManyGimmicks
|
|
||||||
#ENABLEDORON / #DISABLEDORON,Unsupported,TJAPlayer3-Extended
|
|
||||||
#SENOTECHANGE,Unsupported,TJAPlayer3 v1.4.0
|
|
||||||
#NOTESCHANGE,Unsupported,C-Taiko
|
|
||||||
#LEVELHOLD,Unsupported,TaikoJiro v1.63
|
#LEVELHOLD,Unsupported,TaikoJiro v1.63
|
||||||
#NEXTSONG,Unsupported,TJAPlayer3 v1.5.0
|
#BMSCROLL / #HBSCROLL / #NMSCROLL,Unsupported,TaikoJiro v1.91
|
||||||
#GAMETYPE,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
#DIRECTION,Unsupported,TJAPlayer2 for.PC
|
||||||
#HIDDEN,Unsupported,TJAPlayer2 for.PC
|
#HIDDEN,Unsupported,TJAPlayer2 for.PC
|
||||||
NOTE / BARLINE,Unsupported,TaikoManyGimmicks
|
#SENOTECHANGE,Unsupported,TJAPlayer3 v1.4.0
|
||||||
#GRADATION,Unsupported,TaikoManyGimmicks v0.6α
|
#NEXTSONG,Unsupported,TJAPlayer3 v1.5.0
|
||||||
#INCLUDE,Unsupported,TaikoManyGimmicks v0.6.1α
|
#PAPAMAMA,Unsupported,TJAPlayer3-f v1.7.2.0
|
||||||
#SPLITLANE / #MERGELANE,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
#ENABLEDORON / #DISABLEDORON,Unsupported,TJAPlayer3-Extended
|
||||||
#OBJ / #CAM,Unsupported,TJAPlayer3-Extended
|
#OBJ / #CAM,Unsupported,TJAPlayer3-Extended
|
||||||
#BORDERCOLOR,Unsupported,TJAPlayer3-Extended
|
#BORDERCOLOR,Unsupported,TJAPlayer3-Extended
|
||||||
#CHANGETEXTURE / #RESETTEXTURE,Unsupported,TJAPlayer3-Extended
|
#CHANGETEXTURE / #RESETTEXTURE,Unsupported,TJAPlayer3-Extended
|
||||||
#SETCONFIG,Unsupported,TJAPlayer3-Extended
|
#SETCONFIG,Unsupported,TJAPlayer3-Extended
|
||||||
|
#BARLINE,Unsupported,taiko-web (plugin Custom Barlines)
|
||||||
|
#BARLINESCROLL,Unsupported,taiko-web (plugin Custom Barlines)
|
||||||
|
#GAMETYPE,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
||||||
|
#SPLITLANE / #MERGELANE,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
||||||
#BGAON / #BGAOFF,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
#BGAON / #BGAOFF,Unsupported,OpenTaiko (0auBSQ) v0.6.0
|
||||||
|
#JUDGEDELAY,Unsupported,TaikoManyGimmicks
|
||||||
|
#NOTESPAWN,Unsupported,TaikoManyGimmicks
|
||||||
|
NOTE / BARLINE,Unsupported,TaikoManyGimmicks
|
||||||
|
#DUMMYSTART / #DUMMYEND,Unsupported,TaikoManyGimmicks
|
||||||
|
#GRADATION,Unsupported,TaikoManyGimmicks v0.6α
|
||||||
|
#INCLUDE,Unsupported,TaikoManyGimmicks v0.6.1α
|
||||||
|
#HISPEED,Unsupported,TaikoManyGimmicks v0.6.1α
|
||||||
|
#NOTESCHANGE,Unsupported,C-Taiko
|
||||||
|
|||||||
|
@@ -213,10 +213,8 @@ static int port_audio_callback(const void *inputBuffer, void *outputBuffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct audio_buffer *audio_buffer = AUDIO.Buffer.first;
|
struct audio_buffer *audio_buffer = AUDIO.Buffer.first;
|
||||||
int active_buffers = 0;
|
|
||||||
while (audio_buffer != NULL) {
|
while (audio_buffer != NULL) {
|
||||||
if (audio_buffer->playing && !audio_buffer->paused && audio_buffer->data != NULL) {
|
if (audio_buffer->playing && !audio_buffer->paused && audio_buffer->data != NULL) {
|
||||||
active_buffers++;
|
|
||||||
unsigned int subBufferSizeFrames = audio_buffer->sizeInFrames / 2;
|
unsigned int subBufferSizeFrames = audio_buffer->sizeInFrames / 2;
|
||||||
unsigned long framesToMix = framesPerBuffer;
|
unsigned long framesToMix = framesPerBuffer;
|
||||||
float *buffer_data = (float *)audio_buffer->data;
|
float *buffer_data = (float *)audio_buffer->data;
|
||||||
|
|||||||
@@ -8,18 +8,17 @@ from libs.audio import audio
|
|||||||
from libs.animation import Animation, MoveAnimation
|
from libs.animation import Animation, MoveAnimation
|
||||||
from libs.global_data import Crown, Difficulty
|
from libs.global_data import Crown, Difficulty
|
||||||
from libs.tja import TJAParser, test_encodings
|
from libs.tja import TJAParser, test_encodings
|
||||||
from libs.texture import tex
|
from libs.texture import SCREEN_SCALE, SCREEN_WIDTH, tex
|
||||||
from libs.utils import OutlinedText, get_current_ms, global_data
|
from libs.utils import OutlinedText, get_current_ms, global_data
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import pyray as ray
|
import pyray as ray
|
||||||
|
|
||||||
BOX_CENTER = 444
|
BOX_CENTER = 594 * SCREEN_SCALE
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class SongBox:
|
class BaseBox():
|
||||||
"""A box for the song select screen."""
|
|
||||||
OUTLINE_MAP = {
|
OUTLINE_MAP = {
|
||||||
1: ray.Color(0, 77, 104, 255),
|
1: ray.Color(0, 77, 104, 255),
|
||||||
2: ray.Color(156, 64, 2, 255),
|
2: ray.Color(156, 64, 2, 255),
|
||||||
@@ -38,61 +37,118 @@ class SongBox:
|
|||||||
}
|
}
|
||||||
BACK_INDEX = 17
|
BACK_INDEX = 17
|
||||||
DEFAULT_INDEX = 9
|
DEFAULT_INDEX = 9
|
||||||
def __init__(self, name: str, texture_index: int, is_dir: bool, tja: Optional[TJAParser] = None,
|
"""Base class for all box types in the song select screen."""
|
||||||
tja_count: Optional[int] = None, box_texture: Optional[str] = None, name_texture_index: Optional[int] = None):
|
def __init__(self, name: str, texture_index: int):
|
||||||
self.text_name = name
|
self.text_name = name
|
||||||
self.texture_index = texture_index
|
self.texture_index = texture_index
|
||||||
|
self.position = float('inf')
|
||||||
|
self.start_position: float = -1
|
||||||
|
self.target_position: float = -1
|
||||||
|
self.open_anim = Animation.create_move(133, total_distance=150*SCREEN_SCALE, delay=83.33)
|
||||||
|
self.open_fade = Animation.create_fade(200, initial_opacity=0, final_opacity=1.0)
|
||||||
|
self.move = None
|
||||||
|
self.is_open = False
|
||||||
|
self.text_loaded = False
|
||||||
|
self.wait = 0
|
||||||
|
|
||||||
|
def load_text(self):
|
||||||
|
self.name = OutlinedText(self.text_name, 40, ray.WHITE, outline_thickness=5, vertical=True)
|
||||||
|
|
||||||
|
def move_box(self, current_time: float):
|
||||||
|
if self.position != self.target_position and self.move is None:
|
||||||
|
if self.position < self.target_position:
|
||||||
|
direction = 1
|
||||||
|
else:
|
||||||
|
direction = -1
|
||||||
|
if abs(self.target_position - self.position) > 250:
|
||||||
|
direction *= -1
|
||||||
|
self.move = Animation.create_move(83.3, total_distance=100 * direction * SCREEN_SCALE, ease_out='cubic')
|
||||||
|
self.move.start()
|
||||||
|
if self.is_open or self.target_position == BOX_CENTER:
|
||||||
|
self.move.total_distance = 250 * direction
|
||||||
|
self.start_position = self.position
|
||||||
|
if self.move is not None:
|
||||||
|
self.move.update(current_time)
|
||||||
|
self.position = self.start_position + int(self.move.attribute)
|
||||||
|
if self.move.is_finished:
|
||||||
|
self.position = self.target_position
|
||||||
|
self.move = None
|
||||||
|
|
||||||
|
def update(self, current_time: float, is_diff_select: bool):
|
||||||
|
self.is_diff_select = is_diff_select
|
||||||
|
self.open_anim.update(current_time)
|
||||||
|
self.open_fade.update(current_time)
|
||||||
|
|
||||||
|
def _draw_closed(self, x: float, y: float):
|
||||||
|
tex.draw_texture('box', 'folder_texture_left', frame=self.texture_index, x=x)
|
||||||
|
offset = 1 if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0
|
||||||
|
tex.draw_texture('box', 'folder_texture', frame=self.texture_index, x=x, x2=32, y=offset)
|
||||||
|
tex.draw_texture('box', 'folder_texture_right', frame=self.texture_index, x=x)
|
||||||
|
if self.texture_index == SongBox.DEFAULT_INDEX:
|
||||||
|
tex.draw_texture('box', 'genre_overlay', x=x, y=y)
|
||||||
|
elif self.texture_index == 14:
|
||||||
|
tex.draw_texture('box', 'diff_overlay', x=x, y=y)
|
||||||
|
|
||||||
|
def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def draw(self, x: float, y: float, is_ura: bool, fade_override: Optional[float] = None):
|
||||||
|
if self.is_open and get_current_ms() >= self.wait + 83.33:
|
||||||
|
self._draw_open(x, y, fade_override, is_ura)
|
||||||
|
else:
|
||||||
|
self._draw_closed(x, y)
|
||||||
|
|
||||||
|
class BackBox(BaseBox):
|
||||||
|
def __init__(self, name: str, texture_index: int):
|
||||||
|
super().__init__(name, texture_index)
|
||||||
|
self.yellow_box = None
|
||||||
|
|
||||||
|
def load_text(self):
|
||||||
|
super().load_text()
|
||||||
|
self.text_loaded = True
|
||||||
|
|
||||||
|
def update(self, current_time: float, is_diff_select: bool):
|
||||||
|
super().update(current_time, is_diff_select)
|
||||||
|
is_open_prev = self.is_open
|
||||||
|
self.move_box(current_time)
|
||||||
|
self.is_open = self.position == BOX_CENTER
|
||||||
|
|
||||||
|
if self.yellow_box is not None:
|
||||||
|
self.yellow_box.update(is_diff_select)
|
||||||
|
|
||||||
|
if not is_open_prev and self.is_open:
|
||||||
|
self.yellow_box = YellowBox(True)
|
||||||
|
self.yellow_box.create_anim()
|
||||||
|
self.wait = current_time
|
||||||
|
|
||||||
|
def _draw_closed(self, x: float, y: float):
|
||||||
|
super()._draw_closed(x, y)
|
||||||
|
tex.draw_texture('box', 'back_text', x=x, y=y)
|
||||||
|
|
||||||
|
def _draw_open(self, x: float, y: float, fade_override: Optional[float] = None, is_ura: bool = False):
|
||||||
|
if self.yellow_box is not None:
|
||||||
|
self.yellow_box.draw(self, fade_override, is_ura, self.name)
|
||||||
|
|
||||||
|
class SongBox(BaseBox):
|
||||||
|
def __init__(self, name: str, texture_index: int, tja: TJAParser, name_texture_index: Optional[int] = None):
|
||||||
|
super().__init__(name, texture_index)
|
||||||
if name_texture_index is None:
|
if name_texture_index is None:
|
||||||
self.name_texture_index = texture_index
|
self.name_texture_index = texture_index
|
||||||
else:
|
else:
|
||||||
self.name_texture_index = name_texture_index
|
self.name_texture_index = name_texture_index
|
||||||
self.box_texture_path = box_texture
|
|
||||||
self.box_texture = None
|
|
||||||
self.scores = dict()
|
self.scores = dict()
|
||||||
self.crown = dict()
|
self.hash = dict()
|
||||||
self.position = -11111
|
|
||||||
self.start_position = -1
|
|
||||||
self.target_position = -1
|
|
||||||
self.is_open = False
|
|
||||||
self.is_back = self.texture_index == SongBox.BACK_INDEX
|
|
||||||
if self.is_back:
|
|
||||||
for i in range(1, SongBox.BACK_INDEX-1):
|
|
||||||
if audio.is_sound_playing(f'genre_voice_{i}'):
|
|
||||||
audio.stop_sound(f'genre_voice_{i}')
|
|
||||||
self.name = None
|
|
||||||
self.hori_name = None
|
|
||||||
self.yellow_box = None
|
|
||||||
self.open_anim = Animation.create_move(133, start_position=0, total_distance=150, delay=83.33)
|
|
||||||
self.open_fade = Animation.create_fade(200, initial_opacity=0, final_opacity=1.0)
|
|
||||||
self.move = None
|
|
||||||
self.wait = 0
|
|
||||||
self.is_dir = is_dir
|
|
||||||
self.tja_count = tja_count
|
|
||||||
self.tja_count_text = None
|
|
||||||
self.score_history = None
|
self.score_history = None
|
||||||
self.history_wait = 0
|
self.history_wait = 0
|
||||||
self.tja = tja
|
self.tja = tja
|
||||||
self.hash = dict()
|
|
||||||
self.is_favorite = False
|
self.is_favorite = False
|
||||||
|
self.yellow_box = None
|
||||||
|
|
||||||
def reset(self):
|
def load_text(self):
|
||||||
if self.yellow_box is not None:
|
super().load_text()
|
||||||
self.yellow_box.reset()
|
self.text_loaded = True
|
||||||
self.yellow_box.create_anim()
|
|
||||||
if self.name is not None:
|
|
||||||
self.name.unload()
|
|
||||||
self.name = None
|
|
||||||
if self.box_texture is not None:
|
|
||||||
ray.unload_texture(self.box_texture)
|
|
||||||
self.box_texture = None
|
|
||||||
if self.hori_name is not None:
|
|
||||||
self.hori_name.unload()
|
|
||||||
self.hori_name = None
|
|
||||||
self.is_open = False
|
|
||||||
|
|
||||||
def get_scores(self):
|
def get_scores(self):
|
||||||
if self.tja is None:
|
|
||||||
return
|
|
||||||
with sqlite3.connect('scores.db') as con:
|
with sqlite3.connect('scores.db') as con:
|
||||||
cursor = con.cursor()
|
cursor = con.cursor()
|
||||||
# Batch database query for all diffs at once
|
# Batch database query for all diffs at once
|
||||||
@@ -116,37 +172,12 @@ class SongBox:
|
|||||||
self.scores[diff] = hash_to_score.get(diff_hash)
|
self.scores[diff] = hash_to_score.get(diff_hash)
|
||||||
self.score_history = None
|
self.score_history = None
|
||||||
|
|
||||||
def move_box(self):
|
def update(self, current_time: float, is_diff_select: bool):
|
||||||
if self.position != self.target_position and self.move is None:
|
super().update(current_time, is_diff_select)
|
||||||
if self.position < self.target_position:
|
|
||||||
direction = 1
|
|
||||||
else:
|
|
||||||
direction = -1
|
|
||||||
if abs(self.target_position - self.position) > 250:
|
|
||||||
direction *= -1
|
|
||||||
self.move = Animation.create_move(83.3, start_position=0, total_distance=100 * direction, ease_out='cubic')
|
|
||||||
self.move.start()
|
|
||||||
if self.is_open or self.target_position == BOX_CENTER + 150:
|
|
||||||
self.move.total_distance = 250 * direction
|
|
||||||
self.start_position = self.position
|
|
||||||
if self.move is not None:
|
|
||||||
self.move.update(get_current_ms())
|
|
||||||
self.position = self.start_position + int(self.move.attribute)
|
|
||||||
if self.move.is_finished:
|
|
||||||
self.position = self.target_position
|
|
||||||
self.move = None
|
|
||||||
if not (-56 <= self.position <= 1280):
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def update(self, is_diff_select: bool):
|
|
||||||
current_time = get_current_ms()
|
|
||||||
self.is_diff_select = is_diff_select
|
|
||||||
is_open_prev = self.is_open
|
is_open_prev = self.is_open
|
||||||
self.move_box()
|
self.move_box(current_time)
|
||||||
self.is_open = self.position == BOX_CENTER + 150
|
self.is_open = self.position == BOX_CENTER
|
||||||
|
|
||||||
if not (-56 <= self.position <= 1280):
|
|
||||||
return
|
|
||||||
if self.yellow_box is not None:
|
if self.yellow_box is not None:
|
||||||
self.yellow_box.update(is_diff_select)
|
self.yellow_box.update(is_diff_select)
|
||||||
|
|
||||||
@@ -157,54 +188,21 @@ class SongBox:
|
|||||||
self.score_history = ScoreHistory(self.scores, current_time)
|
self.score_history = ScoreHistory(self.scores, current_time)
|
||||||
|
|
||||||
if not is_open_prev and self.is_open:
|
if not is_open_prev and self.is_open:
|
||||||
if self.tja is not None or self.is_back:
|
self.yellow_box = YellowBox(False, tja=self.tja)
|
||||||
self.yellow_box = YellowBox(self.name, self.is_back, tja=self.tja)
|
self.yellow_box.create_anim()
|
||||||
self.yellow_box.create_anim()
|
|
||||||
else:
|
|
||||||
self.hori_name = OutlinedText(self.text_name, 40, ray.WHITE, outline_thickness=5)
|
|
||||||
self.open_anim.start()
|
|
||||||
self.open_fade.start()
|
|
||||||
self.wait = current_time
|
self.wait = current_time
|
||||||
if current_time >= self.history_wait + 3000:
|
if current_time >= self.history_wait + 3000:
|
||||||
self.history_wait = current_time
|
self.history_wait = current_time
|
||||||
if self.tja is None and self.texture_index != 17 and not audio.is_sound_playing('voice_enter'):
|
|
||||||
audio.play_sound(f'genre_voice_{self.texture_index}', 'voice')
|
|
||||||
elif not self.is_open and is_open_prev and self.texture_index != 17 and audio.is_sound_playing(f'genre_voice_{self.texture_index}'):
|
|
||||||
audio.stop_sound(f'genre_voice_{self.texture_index}')
|
|
||||||
if self.tja_count is not None and self.tja_count > 0 and self.tja_count_text is None:
|
|
||||||
self.tja_count_text = OutlinedText(str(self.tja_count), 35, ray.WHITE, outline_thickness=5)#, horizontal_spacing=1.2)
|
|
||||||
if self.box_texture is None and self.box_texture_path is not None:
|
|
||||||
self.box_texture = ray.load_texture(self.box_texture_path)
|
|
||||||
|
|
||||||
self.open_anim.update(current_time)
|
|
||||||
self.open_fade.update(current_time)
|
|
||||||
|
|
||||||
if self.name is None:
|
|
||||||
self.name = OutlinedText(self.text_name, 40, ray.WHITE, outline_thickness=5, vertical=True)
|
|
||||||
|
|
||||||
if self.score_history is not None:
|
if self.score_history is not None:
|
||||||
self.score_history.update(current_time)
|
self.score_history.update(current_time)
|
||||||
|
|
||||||
|
def _draw_closed(self, x: float, y: float):
|
||||||
|
super()._draw_closed(x, y)
|
||||||
|
|
||||||
def _draw_closed(self, x: int, y: int):
|
self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.name_texture_index, ray.Color(101, 0, 82, 255)), x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height)
|
||||||
tex.draw_texture('box', 'folder_texture_left', frame=self.texture_index, x=x)
|
|
||||||
offset = 1 if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0
|
|
||||||
tex.draw_texture('box', 'folder_texture', frame=self.texture_index, x=x, x2=32, y=offset)
|
|
||||||
tex.draw_texture('box', 'folder_texture_right', frame=self.texture_index, x=x)
|
|
||||||
if self.texture_index == SongBox.DEFAULT_INDEX:
|
|
||||||
tex.draw_texture('box', 'genre_overlay', x=x, y=y)
|
|
||||||
elif self.texture_index == 14:
|
|
||||||
tex.draw_texture('box', 'diff_overlay', x=x, y=y)
|
|
||||||
if not self.is_back and self.is_dir:
|
|
||||||
tex.draw_texture('box', 'folder_clip', frame=self.texture_index, x=x - (1 - offset), y=y)
|
|
||||||
|
|
||||||
if self.is_back:
|
if self.tja.ex_data.new:
|
||||||
tex.draw_texture('box', 'back_text', x=x, y=y)
|
|
||||||
return
|
|
||||||
elif self.name is not None:
|
|
||||||
self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.name_texture_index, ray.Color(101, 0, 82, 255)), x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height)
|
|
||||||
|
|
||||||
if self.tja is not None and self.tja.ex_data.new:
|
|
||||||
tex.draw_texture('yellow_box', 'ex_data_new_song_balloon', x=x, y=y)
|
tex.draw_texture('yellow_box', 'ex_data_new_song_balloon', x=x, y=y)
|
||||||
valid_scores = {k: v for k, v in self.scores.items() if v is not None}
|
valid_scores = {k: v for k, v in self.scores.items() if v is not None}
|
||||||
if valid_scores:
|
if valid_scores:
|
||||||
@@ -216,6 +214,58 @@ class SongBox:
|
|||||||
tex.draw_texture('yellow_box', 'crown_fc', x=x, y=y, frame=min(Difficulty.URA, highest_key))
|
tex.draw_texture('yellow_box', 'crown_fc', x=x, y=y, frame=min(Difficulty.URA, highest_key))
|
||||||
elif score and score[5] >= Crown.CLEAR:
|
elif score and score[5] >= Crown.CLEAR:
|
||||||
tex.draw_texture('yellow_box', 'crown_clear', x=x, y=y, frame=min(Difficulty.URA, highest_key))
|
tex.draw_texture('yellow_box', 'crown_clear', x=x, y=y, frame=min(Difficulty.URA, highest_key))
|
||||||
|
|
||||||
|
def _draw_open(self, x: float, y: float, fade_override=None, is_ura=False):
|
||||||
|
if self.yellow_box is not None:
|
||||||
|
self.yellow_box.draw(self, fade_override, is_ura, self.name)
|
||||||
|
|
||||||
|
def draw_score_history(self):
|
||||||
|
if self.is_open and get_current_ms() >= self.wait + 83.33:
|
||||||
|
if self.score_history is not None and get_current_ms() >= self.history_wait + 3000:
|
||||||
|
self.score_history.draw()
|
||||||
|
|
||||||
|
class FolderBox(BaseBox):
|
||||||
|
def __init__(self, name: str, texture_index: int, tja_count: int = 0,
|
||||||
|
box_texture: Optional[str] = None):
|
||||||
|
super().__init__(name, texture_index)
|
||||||
|
self.box_texture_path = Path(box_texture) if box_texture else None
|
||||||
|
self.is_back = self.texture_index == SongBox.BACK_INDEX
|
||||||
|
if self.is_back:
|
||||||
|
for i in range(1, SongBox.BACK_INDEX-1):
|
||||||
|
if audio.is_sound_playing(f'genre_voice_{i}'):
|
||||||
|
audio.stop_sound(f'genre_voice_{i}')
|
||||||
|
self.tja_count = tja_count
|
||||||
|
self.crown = dict()
|
||||||
|
|
||||||
|
def load_text(self):
|
||||||
|
super().load_text()
|
||||||
|
self.hori_name = OutlinedText(self.text_name, 40, ray.WHITE, outline_thickness=5)
|
||||||
|
self.box_texture = ray.load_texture(str(self.box_texture_path)) if self.box_texture_path and self.box_texture_path.exists() else None
|
||||||
|
self.tja_count_text = OutlinedText(str(self.tja_count), 35, ray.WHITE, outline_thickness=5)
|
||||||
|
self.text_loaded = True
|
||||||
|
|
||||||
|
def update(self, current_time: float, is_diff_select: bool):
|
||||||
|
super().update(current_time, is_diff_select)
|
||||||
|
is_open_prev = self.is_open
|
||||||
|
self.move_box(current_time)
|
||||||
|
self.is_open = self.position == BOX_CENTER
|
||||||
|
|
||||||
|
if not is_open_prev and self.is_open:
|
||||||
|
self.open_anim.start()
|
||||||
|
self.open_fade.start()
|
||||||
|
self.wait = current_time
|
||||||
|
if self.texture_index != SongBox.BACK_INDEX and not audio.is_sound_playing('voice_enter'):
|
||||||
|
audio.play_sound(f'genre_voice_{self.texture_index}', 'voice')
|
||||||
|
elif not self.is_open and is_open_prev and self.texture_index != 17 and audio.is_sound_playing(f'genre_voice_{self.texture_index}'):
|
||||||
|
audio.stop_sound(f'genre_voice_{self.texture_index}')
|
||||||
|
|
||||||
|
def _draw_closed(self, x: float, y: float):
|
||||||
|
super()._draw_closed(x, y)
|
||||||
|
offset = 1 if self.texture_index == 3 or self.texture_index >= 9 and self.texture_index not in {10,11,12} else 0
|
||||||
|
tex.draw_texture('box', 'folder_clip', frame=self.texture_index, x=x - (1 - offset), y=y)
|
||||||
|
|
||||||
|
self.name.draw(outline_color=SongBox.OUTLINE_MAP.get(self.texture_index, ray.Color(101, 0, 82, 255)), x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height)
|
||||||
|
|
||||||
if self.crown: #Folder lamp
|
if self.crown: #Folder lamp
|
||||||
highest_crown = max(self.crown)
|
highest_crown = max(self.crown)
|
||||||
if self.crown[highest_crown] == 'DFC':
|
if self.crown[highest_crown] == 'DFC':
|
||||||
@@ -225,11 +275,11 @@ class SongBox:
|
|||||||
else:
|
else:
|
||||||
tex.draw_texture('yellow_box', 'crown_clear', x=x, y=y, frame=min(Difficulty.URA, highest_crown))
|
tex.draw_texture('yellow_box', 'crown_clear', x=x, y=y, frame=min(Difficulty.URA, highest_crown))
|
||||||
|
|
||||||
def _draw_open(self, x: int, y: int, fade_override: Optional[float]):
|
def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool):
|
||||||
color = ray.WHITE
|
color = ray.WHITE
|
||||||
if fade_override is not None:
|
if fade_override is not None:
|
||||||
color = ray.fade(ray.WHITE, fade_override)
|
color = ray.fade(ray.WHITE, fade_override)
|
||||||
if self.hori_name is not None and self.open_anim.attribute >= 100:
|
if not self.is_back and self.open_anim.attribute >= 100:
|
||||||
tex.draw_texture('box', 'folder_top_edge', x=x, y=y - self.open_anim.attribute, color=color, mirror='horizontal', frame=self.texture_index)
|
tex.draw_texture('box', 'folder_top_edge', x=x, y=y - self.open_anim.attribute, color=color, mirror='horizontal', frame=self.texture_index)
|
||||||
tex.draw_texture('box', 'folder_top', x=x, y=y - self.open_anim.attribute, color=color, frame=self.texture_index)
|
tex.draw_texture('box', 'folder_top', x=x, y=y - self.open_anim.attribute, color=color, frame=self.texture_index)
|
||||||
tex.draw_texture('box', 'folder_top_edge', x=x+268, y=y - self.open_anim.attribute, color=color, frame=self.texture_index)
|
tex.draw_texture('box', 'folder_top_edge', x=x+268, y=y - self.open_anim.attribute, color=color, frame=self.texture_index)
|
||||||
@@ -249,45 +299,30 @@ class SongBox:
|
|||||||
color = ray.WHITE
|
color = ray.WHITE
|
||||||
if fade_override is not None:
|
if fade_override is not None:
|
||||||
color = ray.fade(ray.WHITE, fade_override)
|
color = ray.fade(ray.WHITE, fade_override)
|
||||||
if self.tja_count_text is not None and self.texture_index != 14:
|
if self.texture_index != 14:
|
||||||
tex.draw_texture('yellow_box', 'song_count_back', color=color, fade=0.5)
|
tex.draw_texture('yellow_box', 'song_count_back', color=color, fade=0.5)
|
||||||
tex.draw_texture('yellow_box', 'song_count_num', color=color)
|
tex.draw_texture('yellow_box', 'song_count_num', color=color)
|
||||||
tex.draw_texture('yellow_box', 'song_count_songs', color=color)
|
tex.draw_texture('yellow_box', 'song_count_songs', color=color)
|
||||||
dest_width = min(124, self.tja_count_text.texture.width)
|
dest_width = min(124, self.tja_count_text.texture.width)
|
||||||
self.tja_count_text.draw(outline_color=ray.BLACK, x=560 - (dest_width//2), y=126, x2=dest_width-self.tja_count_text.texture.width, color=color)
|
self.tja_count_text.draw(outline_color=ray.BLACK, x=560 - (dest_width//2), y=126, x2=dest_width-self.tja_count_text.texture.width, color=color)
|
||||||
if self.texture_index != 9:
|
if self.texture_index != SongBox.DEFAULT_INDEX:
|
||||||
tex.draw_texture('box', 'folder_graphic', color=color, frame=self.texture_index)
|
tex.draw_texture('box', 'folder_graphic', color=color, frame=self.texture_index)
|
||||||
tex.draw_texture('box', 'folder_text', color=color, frame=self.texture_index)
|
tex.draw_texture('box', 'folder_text', color=color, frame=self.texture_index)
|
||||||
elif self.box_texture is not None:
|
elif self.box_texture is not None:
|
||||||
ray.draw_texture(self.box_texture, (x+48) - (self.box_texture.width//2), (y+240) - (self.box_texture.height//2), color)
|
ray.draw_texture(self.box_texture, int((x+48) - (self.box_texture.width//2)), int((y+240) - (self.box_texture.height//2)), color)
|
||||||
|
|
||||||
def draw_score_history(self):
|
|
||||||
if self.is_open and get_current_ms() >= self.wait + 83.33:
|
|
||||||
if self.score_history is not None and get_current_ms() >= self.history_wait + 3000:
|
|
||||||
self.score_history.draw()
|
|
||||||
|
|
||||||
def draw(self, x: int, y: int, is_ura: bool, fade_override=None):
|
|
||||||
if self.is_open and get_current_ms() >= self.wait + 83.33:
|
|
||||||
if self.yellow_box is not None:
|
|
||||||
self.yellow_box.draw(self, fade_override, is_ura)
|
|
||||||
else:
|
|
||||||
self._draw_open(x, y, self.open_fade.attribute)
|
|
||||||
else:
|
|
||||||
self._draw_closed(x, y)
|
|
||||||
|
|
||||||
class YellowBox:
|
class YellowBox:
|
||||||
"""A song box when it is opened."""
|
"""A song box when it is opened."""
|
||||||
def __init__(self, name: Optional[OutlinedText], is_back: bool, tja: Optional[TJAParser] = None, is_dan: bool = False):
|
def __init__(self, is_back: bool, tja: Optional[TJAParser] = None, is_dan: bool = False):
|
||||||
self.is_diff_select = False
|
self.is_diff_select = False
|
||||||
self.name = name
|
|
||||||
self.is_back = is_back
|
self.is_back = is_back
|
||||||
self.tja = tja
|
self.tja = tja
|
||||||
self.is_dan = is_dan
|
|
||||||
self.subtitle = None
|
|
||||||
if self.tja is not None:
|
if self.tja is not None:
|
||||||
subtitle_text = self.tja.metadata.subtitle.get(global_data.config['general']['language'], '')
|
subtitle_text = self.tja.metadata.subtitle.get(global_data.config['general']['language'], '')
|
||||||
font_size = 30 if len(subtitle_text) < 30 else 20
|
font_size = 30 if len(subtitle_text) < 30 else 20
|
||||||
self.subtitle = OutlinedText(subtitle_text, font_size, ray.WHITE, outline_thickness=5, vertical=True)
|
self.subtitle = OutlinedText(subtitle_text, font_size, ray.WHITE, outline_thickness=5, vertical=True)
|
||||||
|
self.is_dan = is_dan
|
||||||
|
self.subtitle = None
|
||||||
|
|
||||||
self.left_out = tex.get_animation(9)
|
self.left_out = tex.get_animation(9)
|
||||||
self.right_out = tex.get_animation(10)
|
self.right_out = tex.get_animation(10)
|
||||||
@@ -318,11 +353,6 @@ class YellowBox:
|
|||||||
self.bottom_y = tex.textures['yellow_box']['yellow_box_bottom_right'].y[0]
|
self.bottom_y = tex.textures['yellow_box']['yellow_box_bottom_right'].y[0]
|
||||||
self.edge_height = tex.textures['yellow_box']['yellow_box_bottom_right'].height
|
self.edge_height = tex.textures['yellow_box']['yellow_box_bottom_right'].height
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
if self.subtitle is not None:
|
|
||||||
self.subtitle.unload()
|
|
||||||
self.subtitle = None
|
|
||||||
|
|
||||||
def create_anim(self):
|
def create_anim(self):
|
||||||
self.right_out_2.reset()
|
self.right_out_2.reset()
|
||||||
self.top_y_out.reset()
|
self.top_y_out.reset()
|
||||||
@@ -368,8 +398,8 @@ class YellowBox:
|
|||||||
self.center_height = self.center_h_out.attribute
|
self.center_height = self.center_h_out.attribute
|
||||||
self.is_diff_select = is_diff_select
|
self.is_diff_select = is_diff_select
|
||||||
|
|
||||||
def _draw_tja_data(self, song_box, color, fade):
|
def _draw_tja_data(self, song_box: SongBox, color: ray.Color, fade: float):
|
||||||
if self.tja is None:
|
if not self.tja:
|
||||||
return
|
return
|
||||||
for diff in self.tja.metadata.course_data:
|
for diff in self.tja.metadata.course_data:
|
||||||
if diff >= Difficulty.URA:
|
if diff >= Difficulty.URA:
|
||||||
@@ -406,16 +436,14 @@ class YellowBox:
|
|||||||
if self.tja.metadata.course_data[diff].is_branching and (get_current_ms() // 1000) % 2 == 0:
|
if self.tja.metadata.course_data[diff].is_branching and (get_current_ms() // 1000) % 2 == 0:
|
||||||
tex.draw_texture('yellow_box', 'branch_indicator', x=(diff*60), color=color)
|
tex.draw_texture('yellow_box', 'branch_indicator', x=(diff*60), color=color)
|
||||||
|
|
||||||
def _draw_tja_data_diff(self, is_ura: bool, song_box: Optional[SongBox] = None):
|
def _draw_tja_data_diff(self, is_ura: bool, song_box: SongBox):
|
||||||
if self.tja is None:
|
if not self.tja:
|
||||||
return
|
return
|
||||||
tex.draw_texture('diff_select', 'back', fade=self.fade_in.attribute)
|
tex.draw_texture('diff_select', 'back', fade=self.fade_in.attribute)
|
||||||
tex.draw_texture('diff_select', 'option', fade=self.fade_in.attribute)
|
tex.draw_texture('diff_select', 'option', fade=self.fade_in.attribute)
|
||||||
tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute)
|
tex.draw_texture('diff_select', 'neiro', fade=self.fade_in.attribute)
|
||||||
|
|
||||||
for diff in self.tja.metadata.course_data:
|
for diff in self.tja.metadata.course_data:
|
||||||
if song_box is None:
|
|
||||||
continue
|
|
||||||
if diff >= Difficulty.URA:
|
if diff >= Difficulty.URA:
|
||||||
continue
|
continue
|
||||||
elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] is not None and song_box.scores[diff][4] == 2 and song_box.scores[diff][2] == 0) or (song_box.scores[diff][2] == 0 and song_box.scores[diff][3] == 0)):
|
elif diff in song_box.scores and song_box.scores[diff] is not None and ((song_box.scores[diff][4] is not None and song_box.scores[diff][4] == 2 and song_box.scores[diff][2] == 0) or (song_box.scores[diff][2] == 0 and song_box.scores[diff][3] == 0)):
|
||||||
@@ -447,7 +475,7 @@ class YellowBox:
|
|||||||
name = 'branch_indicator_diff'
|
name = 'branch_indicator_diff'
|
||||||
tex.draw_texture('yellow_box', name, x=min(course, Difficulty.ONI)*115, fade=self.fade_in.attribute)
|
tex.draw_texture('yellow_box', name, x=min(course, Difficulty.ONI)*115, fade=self.fade_in.attribute)
|
||||||
|
|
||||||
def _draw_text(self, song_box):
|
def _draw_text(self, song_box, name: OutlinedText):
|
||||||
if not isinstance(self.right_out, MoveAnimation):
|
if not isinstance(self.right_out, MoveAnimation):
|
||||||
return
|
return
|
||||||
if not isinstance(self.right_out_2, MoveAnimation):
|
if not isinstance(self.right_out_2, MoveAnimation):
|
||||||
@@ -457,9 +485,9 @@ class YellowBox:
|
|||||||
x = song_box.position + (self.right_out.attribute*0.85 - (self.right_out.start_position*0.85)) + self.right_out_2.attribute - self.right_out_2.start_position
|
x = song_box.position + (self.right_out.attribute*0.85 - (self.right_out.start_position*0.85)) + self.right_out_2.attribute - self.right_out_2.start_position
|
||||||
if self.is_back:
|
if self.is_back:
|
||||||
tex.draw_texture('box', 'back_text_highlight', x=x)
|
tex.draw_texture('box', 'back_text_highlight', x=x)
|
||||||
elif self.name is not None:
|
else:
|
||||||
texture = self.name.texture
|
texture = name.texture
|
||||||
self.name.draw(outline_color=ray.BLACK, x=x + 30, y=35 + self.top_y_out.attribute, y2=min(texture.height, 417)-texture.height, color=ray.WHITE)
|
name.draw(outline_color=ray.BLACK, x=x + 30, y=35 + self.top_y_out.attribute, y2=min(texture.height, 417)-texture.height, color=ray.WHITE)
|
||||||
if self.subtitle is not None:
|
if self.subtitle is not None:
|
||||||
texture = self.subtitle.texture
|
texture = self.subtitle.texture
|
||||||
y = self.bottom_y - min(texture.height, 410) + 10 + self.top_y_out.attribute - self.top_y_out.start_position
|
y = self.bottom_y - min(texture.height, 410) + 10 + self.top_y_out.attribute - self.top_y_out.start_position
|
||||||
@@ -476,36 +504,31 @@ class YellowBox:
|
|||||||
tex.draw_texture('yellow_box', 'yellow_box_top', x=self.left_x + self.edge_height, y=self.top_y, x2=self.center_width)
|
tex.draw_texture('yellow_box', 'yellow_box_top', x=self.left_x + self.edge_height, y=self.top_y, x2=self.center_width)
|
||||||
tex.draw_texture('yellow_box', 'yellow_box_center', x=self.left_x + self.edge_height, y=self.top_y + self.edge_height, x2=self.center_width, y2=self.center_height)
|
tex.draw_texture('yellow_box', 'yellow_box_center', x=self.left_x + self.edge_height, y=self.top_y + self.edge_height, x2=self.center_width, y2=self.center_height)
|
||||||
|
|
||||||
def draw(self, song_box: Optional[SongBox], fade_override: Optional[float], is_ura: bool):
|
def draw(self, song_box: Optional[SongBox | BackBox], fade_override: Optional[float], is_ura: bool, name: OutlinedText):
|
||||||
self._draw_yellow_box()
|
self._draw_yellow_box()
|
||||||
|
fade = self.fade.attribute
|
||||||
|
if fade_override is not None:
|
||||||
|
fade = min(self.fade.attribute, fade_override)
|
||||||
if self.is_dan:
|
if self.is_dan:
|
||||||
return
|
return
|
||||||
if self.is_diff_select and self.tja is not None:
|
if self.is_back:
|
||||||
|
tex.draw_texture('box', 'back_graphic', fade=fade)
|
||||||
|
return
|
||||||
|
if self.is_diff_select and isinstance(song_box, SongBox):
|
||||||
self._draw_tja_data_diff(is_ura, song_box)
|
self._draw_tja_data_diff(is_ura, song_box)
|
||||||
else:
|
elif isinstance(song_box, SongBox):
|
||||||
fade = self.fade.attribute
|
|
||||||
if fade_override is not None:
|
|
||||||
fade = min(self.fade.attribute, fade_override)
|
|
||||||
if self.is_back:
|
|
||||||
tex.draw_texture('box', 'back_graphic', fade=fade)
|
|
||||||
self._draw_tja_data(song_box, ray.fade(ray.WHITE, fade), fade)
|
self._draw_tja_data(song_box, ray.fade(ray.WHITE, fade), fade)
|
||||||
|
|
||||||
self._draw_text(song_box)
|
self._draw_text(song_box, name)
|
||||||
|
|
||||||
class DanBox:
|
class DanBox(BaseBox):
|
||||||
def __init__(self, title: str, color: int, songs: list[tuple[TJAParser, int, int, int]], exams: list['Exam']):
|
def __init__(self, name, color: int, songs: list[tuple[TJAParser, int, int, int]], exams: list['Exam']):
|
||||||
self.position = -11111
|
super().__init__(name, color)
|
||||||
self.start_position = -1
|
|
||||||
self.target_position = -1
|
|
||||||
self.move = None
|
|
||||||
self.is_open = False
|
|
||||||
self.is_back = False
|
|
||||||
self.title = title
|
|
||||||
self.color = color
|
|
||||||
self.songs = songs
|
self.songs = songs
|
||||||
self.exams = exams
|
self.exams = exams
|
||||||
self.song_text: list[tuple[OutlinedText, OutlinedText]] = []
|
self.song_text: list[tuple[OutlinedText, OutlinedText]] = []
|
||||||
self.total_notes = 0
|
self.total_notes = 0
|
||||||
|
self.yellow_box = None
|
||||||
for song, genre_index, difficulty, level in self.songs:
|
for song, genre_index, difficulty, level in self.songs:
|
||||||
notes, branch_m, branch_e, branch_n = song.notes_to_position(difficulty)
|
notes, branch_m, branch_e, branch_n = song.notes_to_position(difficulty)
|
||||||
self.total_notes += sum(1 for note in notes.play_notes if note.type < 5)
|
self.total_notes += sum(1 for note in notes.play_notes if note.type < 5)
|
||||||
@@ -515,57 +538,26 @@ class DanBox:
|
|||||||
self.total_notes += sum(1 for note in branch.play_notes if note.type < 5)
|
self.total_notes += sum(1 for note in branch.play_notes if note.type < 5)
|
||||||
for branch in branch_n:
|
for branch in branch_n:
|
||||||
self.total_notes += sum(1 for note in branch.play_notes if note.type < 5)
|
self.total_notes += sum(1 for note in branch.play_notes if note.type < 5)
|
||||||
self.name = None
|
|
||||||
self.hori_name = None
|
|
||||||
self.yellow_box = None
|
|
||||||
|
|
||||||
def move_box(self):
|
def load_text(self):
|
||||||
if self.position != self.target_position and self.move is None:
|
super().load_text()
|
||||||
if self.position < self.target_position:
|
self.hori_name = OutlinedText(self.text_name, 40, ray.WHITE)
|
||||||
direction = 1
|
for song, genre, difficulty, level in self.songs:
|
||||||
else:
|
title = song.metadata.title.get(global_data.config["general"]["language"], song.metadata.title["en"])
|
||||||
direction = -1
|
subtitle = song.metadata.subtitle.get(global_data.config["general"]["language"], "")
|
||||||
if abs(self.target_position - self.position) > 250:
|
title_text = OutlinedText(title, 40, ray.WHITE, vertical=True)
|
||||||
direction *= -1
|
font_size = 30 if len(subtitle) < 30 else 20
|
||||||
self.move = Animation.create_move(83.3*2, start_position=0, total_distance=300 * direction, ease_out='cubic')
|
subtitle_text = OutlinedText(subtitle, font_size, ray.WHITE, vertical=True)
|
||||||
self.move.start()
|
self.song_text.append((title_text, subtitle_text))
|
||||||
if self.is_open or self.target_position == BOX_CENTER + 150:
|
self.text_loaded = True
|
||||||
self.move.total_distance = 450 * direction * -1
|
|
||||||
self.start_position = self.position
|
|
||||||
if self.move is not None:
|
|
||||||
self.move.update(get_current_ms())
|
|
||||||
self.position = self.start_position + int(self.move.attribute)
|
|
||||||
if self.move.is_finished:
|
|
||||||
self.position = self.target_position
|
|
||||||
self.move = None
|
|
||||||
if not (-56 <= self.position <= 1280):
|
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def reset(self):
|
def update(self, current_time: float, is_diff_select: bool):
|
||||||
if self.name is not None:
|
super().update(current_time, is_diff_select)
|
||||||
self.name.unload()
|
|
||||||
self.name = None
|
|
||||||
|
|
||||||
def get_text(self):
|
|
||||||
if self.name is None:
|
|
||||||
self.name = OutlinedText(self.title, 40, ray.WHITE, vertical=True)
|
|
||||||
self.hori_name = OutlinedText(self.title, 40, ray.WHITE)
|
|
||||||
if self.is_open and not self.song_text:
|
|
||||||
for song, genre, difficulty, level in self.songs:
|
|
||||||
title = song.metadata.title.get(global_data.config["general"]["language"], song.metadata.title["en"])
|
|
||||||
subtitle = song.metadata.subtitle.get(global_data.config["general"]["language"], "")
|
|
||||||
title_text = OutlinedText(title, 40, ray.WHITE, vertical=True)
|
|
||||||
font_size = 30 if len(subtitle) < 30 else 20
|
|
||||||
subtitle_text = OutlinedText(subtitle, font_size, ray.WHITE, vertical=True)
|
|
||||||
self.song_text.append((title_text, subtitle_text))
|
|
||||||
|
|
||||||
def update(self, is_diff_select: bool):
|
|
||||||
self.move_box()
|
|
||||||
self.get_text()
|
|
||||||
is_open_prev = self.is_open
|
is_open_prev = self.is_open
|
||||||
self.is_open = self.position == BOX_CENTER + 150
|
self.move_box(current_time)
|
||||||
|
self.is_open = self.position == BOX_CENTER
|
||||||
if not is_open_prev and self.is_open:
|
if not is_open_prev and self.is_open:
|
||||||
self.yellow_box = YellowBox(self.name, self.is_back, is_dan=True)
|
self.yellow_box = YellowBox(False, is_dan=True)
|
||||||
self.yellow_box.create_anim()
|
self.yellow_box.create_anim()
|
||||||
|
|
||||||
if self.yellow_box is not None:
|
if self.yellow_box is not None:
|
||||||
@@ -601,51 +593,49 @@ class DanBox:
|
|||||||
elif self.exams[i].range == 'less':
|
elif self.exams[i].range == 'less':
|
||||||
tex.draw_texture('yellow_box', 'exam_less', x=(offset*-1.7), y=(i*83))
|
tex.draw_texture('yellow_box', 'exam_less', x=(offset*-1.7), y=(i*83))
|
||||||
|
|
||||||
def _draw_closed(self, x: int, y: int):
|
def _draw_closed(self, x: float, y: float):
|
||||||
tex.draw_texture('box', 'folder', frame=self.color, x=x)
|
tex.draw_texture('box', 'folder', frame=self.texture_index, x=x)
|
||||||
if self.name is not None:
|
if self.name is not None:
|
||||||
self.name.draw(outline_color=ray.BLACK, x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height)
|
self.name.draw(outline_color=ray.BLACK, x=x + 47 - int(self.name.texture.width / 2), y=y+35, y2=min(self.name.texture.height, 417)-self.name.texture.height)
|
||||||
|
|
||||||
def _draw_open(self, x: int, y: int, is_ura: bool):
|
def _draw_open(self, x: float, y: float, fade_override: Optional[float], is_ura: bool):
|
||||||
|
if fade_override is not None:
|
||||||
|
fade = fade_override
|
||||||
|
else:
|
||||||
|
fade = 1.0
|
||||||
if self.yellow_box is not None:
|
if self.yellow_box is not None:
|
||||||
self.yellow_box.draw(None, None, False)
|
self.yellow_box.draw(None, None, False, self.name)
|
||||||
for i, song in enumerate(self.song_text):
|
for i, song in enumerate(self.song_text):
|
||||||
title, subtitle = song
|
title, subtitle = song
|
||||||
x = i * 140
|
x = i * 140
|
||||||
tex.draw_texture('yellow_box', 'genre_banner', x=x, frame=self.songs[i][1])
|
tex.draw_texture('yellow_box', 'genre_banner', x=x, frame=self.songs[i][1], fade=fade)
|
||||||
tex.draw_texture('yellow_box', 'difficulty', x=x, frame=self.songs[i][2])
|
tex.draw_texture('yellow_box', 'difficulty', x=x, frame=self.songs[i][2], fade=fade)
|
||||||
tex.draw_texture('yellow_box', 'difficulty_x', x=x)
|
tex.draw_texture('yellow_box', 'difficulty_x', x=x, fade=fade)
|
||||||
tex.draw_texture('yellow_box', 'difficulty_star', x=x)
|
tex.draw_texture('yellow_box', 'difficulty_star', x=x, fade=fade)
|
||||||
level = self.songs[i][0].metadata.course_data[self.songs[i][2]].level
|
level = self.songs[i][0].metadata.course_data[self.songs[i][2]].level
|
||||||
counter = str(level)
|
counter = str(level)
|
||||||
total_width = len(counter) * 10
|
total_width = len(counter) * 10
|
||||||
for i in range(len(counter)):
|
for i in range(len(counter)):
|
||||||
tex.draw_texture('yellow_box', 'difficulty_num', frame=int(counter[i]), x=x-(total_width // 2) + (i * 10))
|
tex.draw_texture('yellow_box', 'difficulty_num', frame=int(counter[i]), x=x-(total_width // 2) + (i * 10), fade=fade)
|
||||||
|
|
||||||
title.draw(outline_color=ray.BLACK, x=665+x, y=127, y2=min(title.texture.height, 400)-title.texture.height)
|
title.draw(outline_color=ray.BLACK, x=665+x, y=127, y2=min(title.texture.height, 400)-title.texture.height, fade=fade)
|
||||||
subtitle.draw(outline_color=ray.BLACK, x=620+x, y=525-min(subtitle.texture.height, 400), y2=min(subtitle.texture.height, 400)-subtitle.texture.height)
|
subtitle.draw(outline_color=ray.BLACK, x=620+x, y=525-min(subtitle.texture.height, 400), y2=min(subtitle.texture.height, 400)-subtitle.texture.height, fade=fade)
|
||||||
|
|
||||||
tex.draw_texture('yellow_box', 'total_notes_bg')
|
tex.draw_texture('yellow_box', 'total_notes_bg', fade=fade)
|
||||||
tex.draw_texture('yellow_box', 'total_notes')
|
tex.draw_texture('yellow_box', 'total_notes', fade=fade)
|
||||||
counter = str(self.total_notes)
|
counter = str(self.total_notes)
|
||||||
for i in range(len(counter)):
|
for i in range(len(counter)):
|
||||||
tex.draw_texture('yellow_box', 'total_notes_counter', frame=int(counter[i]), x=(i * 25))
|
tex.draw_texture('yellow_box', 'total_notes_counter', frame=int(counter[i]), x=(i * 25), fade=fade)
|
||||||
|
|
||||||
tex.draw_texture('yellow_box', 'frame', frame=self.color)
|
tex.draw_texture('yellow_box', 'frame', frame=self.texture_index, fade=fade)
|
||||||
if self.hori_name is not None:
|
if self.hori_name is not None:
|
||||||
self.hori_name.draw(outline_color=ray.BLACK, x=434 - (self.hori_name.texture.width//2), y=84, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width)
|
self.hori_name.draw(outline_color=ray.BLACK, x=434 - (self.hori_name.texture.width//2), y=84, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width, fade=fade)
|
||||||
|
|
||||||
self._draw_exam_box()
|
self._draw_exam_box()
|
||||||
|
|
||||||
def draw(self, x: int, y: int, is_ura: bool):
|
|
||||||
if self.is_open:
|
|
||||||
self._draw_open(x, y, is_ura)
|
|
||||||
else:
|
|
||||||
self._draw_closed(x, y)
|
|
||||||
|
|
||||||
class GenreBG:
|
class GenreBG:
|
||||||
"""The background for a genre box."""
|
"""The background for a genre box."""
|
||||||
def __init__(self, start_box: SongBox, end_box: SongBox, title: OutlinedText, diff_sort: Optional[int]):
|
def __init__(self, start_box: BaseBox, end_box: BaseBox, title: OutlinedText, diff_sort: Optional[int]):
|
||||||
self.start_box = start_box
|
self.start_box = start_box
|
||||||
self.end_box = end_box
|
self.end_box = end_box
|
||||||
self.start_position = start_box.position
|
self.start_position = start_box.position
|
||||||
@@ -694,7 +684,7 @@ class GenreBG:
|
|||||||
tex.draw_texture('box', 'folder_background_folder_edge', x=((offset+dest_width)//2)+20, y=y-2, fade=self.fade_in.attribute, frame=self.end_box.texture_index)
|
tex.draw_texture('box', 'folder_background_folder_edge', x=((offset+dest_width)//2)+20, y=y-2, fade=self.fade_in.attribute, frame=self.end_box.texture_index)
|
||||||
if self.diff_num is not None:
|
if self.diff_num is not None:
|
||||||
tex.draw_texture('diff_sort', 'star_num', frame=self.diff_num, x=-150 + (dest_width//2), y=-143)
|
tex.draw_texture('diff_sort', 'star_num', frame=self.diff_num, x=-150 + (dest_width//2), y=-143)
|
||||||
self.title.draw(outline_color=ray.BLACK, x=(1280//2) - (dest_width//2)-(offset//2), y=y-60, x2=dest_width - self.title.texture.width, color=ray.fade(ray.WHITE, self.fade_in.attribute))
|
self.title.draw(outline_color=ray.BLACK, x=(SCREEN_WIDTH//2) - (dest_width//2)-(offset//2), y=y-60, x2=dest_width - self.title.texture.width, color=ray.fade(ray.WHITE, self.fade_in.attribute))
|
||||||
|
|
||||||
class ScoreHistory:
|
class ScoreHistory:
|
||||||
"""The score information that appears while hovering over a song"""
|
"""The score information that appears while hovering over a song"""
|
||||||
@@ -872,7 +862,10 @@ class Directory(FileSystemItem):
|
|||||||
elif self.to_root or self.back:
|
elif self.to_root or self.back:
|
||||||
texture_index = SongBox.BACK_INDEX
|
texture_index = SongBox.BACK_INDEX
|
||||||
|
|
||||||
self.box = SongBox(name, texture_index, True, tja_count=tja_count, box_texture=box_texture)
|
if self.back:
|
||||||
|
self.box = BackBox(name, texture_index)
|
||||||
|
else:
|
||||||
|
self.box = FolderBox(name, texture_index, tja_count=tja_count, box_texture=box_texture)
|
||||||
|
|
||||||
class SongFile(FileSystemItem):
|
class SongFile(FileSystemItem):
|
||||||
"""Represents a song file (TJA) in the navigation system"""
|
"""Represents a song file (TJA) in the navigation system"""
|
||||||
@@ -884,7 +877,7 @@ class SongFile(FileSystemItem):
|
|||||||
self.tja.ex_data.new = True
|
self.tja.ex_data.new = True
|
||||||
title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
|
title = self.tja.metadata.title.get(global_data.config['general']['language'].lower(), self.tja.metadata.title['en'])
|
||||||
self.hash = global_data.song_paths[path]
|
self.hash = global_data.song_paths[path]
|
||||||
self.box = SongBox(title, texture_index, False, tja=self.tja, name_texture_index=name_texture_index if name_texture_index is not None else texture_index)
|
self.box = SongBox(title, texture_index, self.tja, name_texture_index=name_texture_index if name_texture_index is not None else texture_index)
|
||||||
self.box.hash = global_data.song_hashes[self.hash][0]["diff_hashes"]
|
self.box.hash = global_data.song_hashes[self.hash][0]["diff_hashes"]
|
||||||
self.box.get_scores()
|
self.box.get_scores()
|
||||||
|
|
||||||
@@ -904,7 +897,7 @@ class DanCourse(FileSystemItem):
|
|||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
self.title = data["title"]
|
self.title = data["title"]
|
||||||
self.color = data["color"]
|
self.color = data["color"]
|
||||||
self.charts = []
|
self.charts: list[tuple[TJAParser, int, int, int]] = []
|
||||||
for chart in data["charts"]:
|
for chart in data["charts"]:
|
||||||
hash = chart["hash"]
|
hash = chart["hash"]
|
||||||
#chart_title = chart["title"]
|
#chart_title = chart["title"]
|
||||||
@@ -1203,8 +1196,8 @@ class FileNavigator:
|
|||||||
if self.recent_folder is None:
|
if self.recent_folder is None:
|
||||||
raise Exception("tried to enter recent folder without recents")
|
raise Exception("tried to enter recent folder without recents")
|
||||||
self._generate_objects_recursive(self.recent_folder.path)
|
self._generate_objects_recursive(self.recent_folder.path)
|
||||||
selected_item.box.tja_count_text = None
|
if not isinstance(selected_item.box, BackBox):
|
||||||
selected_item.box.tja_count = self._count_tja_files(self.recent_folder.path)
|
selected_item.box.tja_count = self._count_tja_files(self.recent_folder.path)
|
||||||
content_items = self.directory_contents[dir_key]
|
content_items = self.directory_contents[dir_key]
|
||||||
elif selected_item.collection == Directory.COLLECTIONS[2]:
|
elif selected_item.collection == Directory.COLLECTIONS[2]:
|
||||||
if self.favorite_folder is None:
|
if self.favorite_folder is None:
|
||||||
@@ -1212,8 +1205,8 @@ class FileNavigator:
|
|||||||
self._generate_objects_recursive(self.favorite_folder.path)
|
self._generate_objects_recursive(self.favorite_folder.path)
|
||||||
tja_files = self._get_tja_files_for_directory(self.favorite_folder.path)
|
tja_files = self._get_tja_files_for_directory(self.favorite_folder.path)
|
||||||
self._calculate_directory_crowns(dir_key, tja_files)
|
self._calculate_directory_crowns(dir_key, tja_files)
|
||||||
selected_item.box.tja_count_text = None
|
if not isinstance(selected_item.box, BackBox):
|
||||||
selected_item.box.tja_count = self._count_tja_files(self.favorite_folder.path)
|
selected_item.box.tja_count = self._count_tja_files(self.favorite_folder.path)
|
||||||
content_items = self.directory_contents[dir_key]
|
content_items = self.directory_contents[dir_key]
|
||||||
self.in_favorites = True
|
self.in_favorites = True
|
||||||
elif selected_item.collection == Directory.COLLECTIONS[3]:
|
elif selected_item.collection == Directory.COLLECTIONS[3]:
|
||||||
@@ -1245,7 +1238,7 @@ class FileNavigator:
|
|||||||
return
|
return
|
||||||
i = 1
|
i = 1
|
||||||
for item in content_items:
|
for item in content_items:
|
||||||
if isinstance(item, SongFile):
|
if isinstance(item, SongFile) and not has_children:
|
||||||
if i % 10 == 0 and i != 0:
|
if i % 10 == 0 and i != 0:
|
||||||
back_dir = Directory(self.current_dir.parent, "", SongBox.BACK_INDEX, back=True)
|
back_dir = Directory(self.current_dir.parent, "", SongBox.BACK_INDEX, back=True)
|
||||||
self.items.insert(self.selected_index+i, back_dir)
|
self.items.insert(self.selected_index+i, back_dir)
|
||||||
@@ -1268,24 +1261,22 @@ class FileNavigator:
|
|||||||
for item in self.items:
|
for item in self.items:
|
||||||
if isinstance(item, Directory):
|
if isinstance(item, Directory):
|
||||||
item_key = str(item.path)
|
item_key = str(item.path)
|
||||||
if item_key in self.directory_contents: # Only for real directories
|
if isinstance(item.box, FolderBox):
|
||||||
item.box.crown = self._get_directory_crowns_cached(item_key)
|
item.box.crown = self._get_directory_crowns_cached(item_key)
|
||||||
else:
|
|
||||||
# Navigation items (back/to_root)
|
|
||||||
item.box.crown = dict()
|
|
||||||
|
|
||||||
self.calculate_box_positions()
|
self.calculate_box_positions()
|
||||||
|
|
||||||
if (not has_children and start_box is not None
|
if selected_item and isinstance(selected_item.box, FolderBox):
|
||||||
and end_box is not None and selected_item is not None
|
if (not has_children and start_box is not None
|
||||||
and selected_item.box.hori_name is not None):
|
and end_box is not None and selected_item is not None
|
||||||
hori_name = selected_item.box.hori_name
|
and selected_item.box.hori_name is not None):
|
||||||
diff_sort = None
|
hori_name = selected_item.box.hori_name
|
||||||
if selected_item.collection == Directory.COLLECTIONS[3]:
|
diff_sort = None
|
||||||
diff_sort = self.diff_sort_level
|
if selected_item.collection == Directory.COLLECTIONS[3]:
|
||||||
diffs = ['かんたん', 'ふつう', 'むずかしい', 'おに']
|
diff_sort = self.diff_sort_level
|
||||||
hori_name = OutlinedText(diffs[min(Difficulty.ONI, self.diff_sort_diff)], 40, ray.WHITE, outline_thickness=5)
|
diffs = ['かんたん', 'ふつう', 'むずかしい', 'おに']
|
||||||
self.genre_bg = GenreBG(start_box, end_box, hori_name, diff_sort)
|
hori_name = OutlinedText(diffs[min(Difficulty.ONI, self.diff_sort_diff)], 40, ray.WHITE, outline_thickness=5)
|
||||||
|
self.genre_bg = GenreBG(start_box, end_box, hori_name, diff_sort)
|
||||||
|
|
||||||
def select_current_item(self):
|
def select_current_item(self):
|
||||||
"""Select the currently highlighted item"""
|
"""Select the currently highlighted item"""
|
||||||
@@ -1488,15 +1479,18 @@ class FileNavigator:
|
|||||||
side_offset_l = 200
|
side_offset_l = 200
|
||||||
side_offset_r = 500
|
side_offset_r = 500
|
||||||
|
|
||||||
position = BOX_CENTER + (base_spacing * offset)
|
position = (BOX_CENTER - 150) + (base_spacing * offset)
|
||||||
if position == BOX_CENTER:
|
if position == BOX_CENTER - 150:
|
||||||
|
#item.box.is_open = True
|
||||||
position += center_offset
|
position += center_offset
|
||||||
elif position > BOX_CENTER:
|
elif position > BOX_CENTER - 150:
|
||||||
|
#item.box.is_open = False
|
||||||
position += side_offset_r
|
position += side_offset_r
|
||||||
else:
|
else:
|
||||||
position -= side_offset_l
|
position -= side_offset_l
|
||||||
|
#item.box.is_open = False
|
||||||
|
|
||||||
if item.box.position == -11111:
|
if item.box.position == float('inf'):
|
||||||
item.box.position = position
|
item.box.position = position
|
||||||
item.box.target_position = position
|
item.box.target_position = position
|
||||||
else:
|
else:
|
||||||
@@ -1535,8 +1529,10 @@ class FileNavigator:
|
|||||||
|
|
||||||
def reset_items(self):
|
def reset_items(self):
|
||||||
"""Reset the items in the song select scene"""
|
"""Reset the items in the song select scene"""
|
||||||
for item in self.items:
|
song = self.get_current_item()
|
||||||
item.box.reset()
|
if isinstance(song.box, SongBox):
|
||||||
|
if song.box.yellow_box is not None:
|
||||||
|
song.box.yellow_box.create_anim()
|
||||||
|
|
||||||
def add_recent(self):
|
def add_recent(self):
|
||||||
"""Add the current song to the recent list"""
|
"""Add the current song to the recent list"""
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from typing import Callable
|
||||||
import pyray as ray
|
import pyray as ray
|
||||||
|
|
||||||
from libs.global_data import PlayerNum
|
from libs.global_data import PlayerNum
|
||||||
@@ -20,8 +21,8 @@ class Nameplate:
|
|||||||
is_rainbow (bool): Whether the player's nameplate background is rainbow.
|
is_rainbow (bool): Whether the player's nameplate background is rainbow.
|
||||||
title_bg (int): The player's non-rainbow nameplate background.
|
title_bg (int): The player's non-rainbow nameplate background.
|
||||||
"""
|
"""
|
||||||
self.name = OutlinedText(name, 22, ray.WHITE, outline_thickness=3.0)
|
self.name = OutlinedText(name, global_tex.skin_config["nameplate_text_name"].font_size, ray.WHITE, outline_thickness=3.0)
|
||||||
self.title = OutlinedText(title, 20, ray.BLACK, outline_thickness=0)
|
self.title = OutlinedText(title, global_tex.skin_config["nameplate_text_title"].font_size, ray.BLACK, outline_thickness=0)
|
||||||
self.dan_index = dan
|
self.dan_index = dan
|
||||||
self.player_num = player_num
|
self.player_num = player_num
|
||||||
self.is_gold = is_gold
|
self.is_gold = is_gold
|
||||||
@@ -60,7 +61,7 @@ class Nameplate:
|
|||||||
title_offset = 0
|
title_offset = 0
|
||||||
else:
|
else:
|
||||||
frame = self.title_bg
|
frame = self.title_bg
|
||||||
title_offset = 14
|
title_offset = tex.skin_config["nameplate_title_offset"].x
|
||||||
if self.is_rainbow:
|
if self.is_rainbow:
|
||||||
if 0 < self.rainbow_animation.attribute < 6:
|
if 0 < self.rainbow_animation.attribute < 6:
|
||||||
tex.draw_texture('nameplate', 'frame_top_rainbow', frame=self.rainbow_animation.attribute-1, x=x, y=y, fade=fade)
|
tex.draw_texture('nameplate', 'frame_top_rainbow', frame=self.rainbow_animation.attribute-1, x=x, y=y, fade=fade)
|
||||||
@@ -75,12 +76,12 @@ class Nameplate:
|
|||||||
tex.draw_texture('nameplate', 'dan_emblem_gold', x=x, y=y, frame=self.dan_index, fade=fade)
|
tex.draw_texture('nameplate', 'dan_emblem_gold', x=x, y=y, frame=self.dan_index, fade=fade)
|
||||||
else:
|
else:
|
||||||
tex.draw_texture('nameplate', 'dan_emblem', x=x, y=y, frame=self.dan_index, fade=fade)
|
tex.draw_texture('nameplate', 'dan_emblem', x=x, y=y, frame=self.dan_index, fade=fade)
|
||||||
offset = 34
|
offset = tex.skin_config["nameplate_dan_offset"].x
|
||||||
if self.player_num != 0:
|
if self.player_num != 0:
|
||||||
tex.draw_texture('nameplate', f'{self.player_num}p', x=x, y=y, fade=fade)
|
tex.draw_texture('nameplate', f'{self.player_num}p', x=x, y=y, fade=fade)
|
||||||
|
|
||||||
self.name.draw(outline_color=ray.BLACK, x=x+136 - (min(255 - offset*4, self.name.texture.width)//2) + offset, y=y+24, x2=min(255 - offset*4, self.name.texture.width)-self.name.texture.width, color=ray.fade(ray.WHITE, fade))
|
self.name.draw(outline_color=ray.BLACK, x=x+tex.skin_config["nameplate_text_name"].x - (min(tex.skin_config["nameplate_text_name"].width - offset*4, self.name.texture.width)//2) + offset, y=y+tex.skin_config["nameplate_text_name"].y, x2=min(tex.skin_config["nameplate_text_name"].width - offset*4, self.name.texture.width)-self.name.texture.width, color=ray.fade(ray.WHITE, fade))
|
||||||
self.title.draw(x=x+136 - (min(255 - offset*2, self.title.texture.width)//2) + title_offset, y=y-3, x2=min(255 - offset*2, self.title.texture.width)-self.title.texture.width, color=ray.fade(ray.WHITE, fade))
|
self.title.draw(x=x+tex.skin_config["nameplate_text_title"].x - (min(tex.skin_config["nameplate_text_title"].width - offset*2, self.title.texture.width)//2) + title_offset, y=y+tex.skin_config["nameplate_text_title"].y, x2=min(tex.skin_config["nameplate_text_title"].width - offset*2, self.title.texture.width)-self.title.texture.width, color=ray.fade(ray.WHITE, fade))
|
||||||
|
|
||||||
class Indicator:
|
class Indicator:
|
||||||
"""Indicator class for displaying drum navigation."""
|
"""Indicator class for displaying drum navigation."""
|
||||||
@@ -112,10 +113,10 @@ class Indicator:
|
|||||||
if self.state == Indicator.State.SELECT:
|
if self.state == Indicator.State.SELECT:
|
||||||
tex.draw_texture('indicator', 'drum_kat', fade=min(fade, self.don_fade.attribute), x=x, y=y)
|
tex.draw_texture('indicator', 'drum_kat', fade=min(fade, self.don_fade.attribute), x=x, y=y)
|
||||||
|
|
||||||
tex.draw_texture('indicator', 'drum_kat', fade=min(fade, self.don_fade.attribute), x=x+23, y=y, mirror='horizontal')
|
tex.draw_texture('indicator', 'drum_kat', fade=min(fade, self.don_fade.attribute), x=x+tex.skin_config["indicator_kat_offset"].x, y=y, mirror='horizontal')
|
||||||
tex.draw_texture('indicator', 'drum_face', x=x+175, y=y, fade=fade)
|
tex.draw_texture('indicator', 'drum_face', x=x+tex.skin_config["indicator_face_offset"].x, y=y, fade=fade)
|
||||||
|
|
||||||
tex.draw_texture('indicator', 'drum_don', fade=min(fade, self.don_fade.attribute), index=self.state.value, x=x+214, y=y)
|
tex.draw_texture('indicator', 'drum_don', fade=min(fade, self.don_fade.attribute), index=self.state.value, x=x+tex.skin_config["indicator_don_offset"].x, y=y)
|
||||||
tex.draw_texture('indicator', 'blue_arrow', x=x-self.blue_arrow_move.attribute, y=y, fade=min(fade, self.blue_arrow_fade.attribute))
|
tex.draw_texture('indicator', 'blue_arrow', x=x-self.blue_arrow_move.attribute, y=y, fade=min(fade, self.blue_arrow_fade.attribute))
|
||||||
tex.draw_texture('indicator', 'blue_arrow', index=1, x=x+self.blue_arrow_move.attribute, y=y, mirror='horizontal', fade=min(fade, self.blue_arrow_fade.attribute))
|
tex.draw_texture('indicator', 'blue_arrow', index=1, x=x+self.blue_arrow_move.attribute, y=y, mirror='horizontal', fade=min(fade, self.blue_arrow_fade.attribute))
|
||||||
else:
|
else:
|
||||||
@@ -169,7 +170,7 @@ class EntryOverlay:
|
|||||||
|
|
||||||
class Timer:
|
class Timer:
|
||||||
"""Timer class for displaying countdown timers."""
|
"""Timer class for displaying countdown timers."""
|
||||||
def __init__(self, time: int, current_time_ms: float, confirm_func):
|
def __init__(self, time: int, current_time_ms: float, confirm_func: Callable):
|
||||||
"""
|
"""
|
||||||
Initialize a Timer object.
|
Initialize a Timer object.
|
||||||
|
|
||||||
@@ -222,7 +223,7 @@ class Timer:
|
|||||||
else:
|
else:
|
||||||
tex.draw_texture('timer', 'bg')
|
tex.draw_texture('timer', 'bg')
|
||||||
counter_name = 'counter_black'
|
counter_name = 'counter_black'
|
||||||
margin = 40
|
margin = tex.skin_config["timer_text_margin"].x
|
||||||
total_width = len(self.counter) * margin
|
total_width = len(self.counter) * margin
|
||||||
for i, digit in enumerate(self.counter):
|
for i, digit in enumerate(self.counter):
|
||||||
tex.draw_texture('timer', counter_name, frame=int(digit), x=-(total_width//2)+(i*margin), scale=self.num_resize.attribute, center=True)
|
tex.draw_texture('timer', counter_name, frame=int(digit), x=-(total_width//2)+(i*margin), scale=self.num_resize.attribute, center=True)
|
||||||
|
|||||||
@@ -14,13 +14,17 @@ from libs.animation import BaseAnimation, parse_animations
|
|||||||
|
|
||||||
SCREEN_WIDTH = 1280
|
SCREEN_WIDTH = 1280
|
||||||
SCREEN_HEIGHT = 720
|
SCREEN_HEIGHT = 720
|
||||||
|
SCREEN_SCALE = SCREEN_WIDTH / 1280
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class Coordinates:
|
class SkinInfo:
|
||||||
def __init__(self, x: float, y: float):
|
def __init__(self, x: float, y: float, font_size: int, width: float, height: float):
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.font_size = font_size
|
||||||
|
|
||||||
class Texture:
|
class Texture:
|
||||||
"""Texture class for managing textures and animations."""
|
"""Texture class for managing textures and animations."""
|
||||||
@@ -47,12 +51,12 @@ class TextureWrapper:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.textures: dict[str, dict[str, Texture]] = dict()
|
self.textures: dict[str, dict[str, Texture]] = dict()
|
||||||
self.animations: dict[int, BaseAnimation] = dict()
|
self.animations: dict[int, BaseAnimation] = dict()
|
||||||
self.skin_config: dict[str, Coordinates] = dict()
|
self.skin_config: dict[str, SkinInfo] = dict()
|
||||||
self.graphics_path = Path("Graphics")
|
self.graphics_path = Path("Graphics")
|
||||||
if (self.graphics_path / "skin_config.json").exists():
|
if (self.graphics_path / "skin_config.json").exists():
|
||||||
data = json.loads((self.graphics_path / "skin_config.json").read_text())
|
data = json.loads((self.graphics_path / "skin_config.json").read_text())
|
||||||
self.skin_config: dict[str, Coordinates] = {
|
self.skin_config: dict[str, SkinInfo] = {
|
||||||
k: Coordinates(v['x'], v['y']) for k, v in data.items()
|
k: SkinInfo(v.get('x', 0), v.get('y', 0), v.get('font_size', 0), v.get('width', 0), v.get('height', 0)) for k, v in data.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
def unload_textures(self):
|
def unload_textures(self):
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from raylib import (
|
|||||||
SHADER_UNIFORM_VEC4,
|
SHADER_UNIFORM_VEC4,
|
||||||
)
|
)
|
||||||
|
|
||||||
from libs.texture import TextureWrapper
|
from libs.texture import SCREEN_WIDTH, TextureWrapper
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ class OutlinedText:
|
|||||||
"""
|
"""
|
||||||
self.text = text
|
self.text = text
|
||||||
self.hash = self._hash_text(text, font_size, color, vertical)
|
self.hash = self._hash_text(text, font_size, color, vertical)
|
||||||
self.outline_thickness = outline_thickness
|
self.outline_thickness = outline_thickness * (SCREEN_WIDTH/1280)
|
||||||
if self.hash in text_cache:
|
if self.hash in text_cache:
|
||||||
self.texture = ray.load_texture(f'cache/image/{self.hash}.png')
|
self.texture = ray.load_texture(f'cache/image/{self.hash}.png')
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from moviepy import VideoFileClip
|
|||||||
|
|
||||||
from libs.audio import audio
|
from libs.audio import audio
|
||||||
from libs.utils import get_current_ms
|
from libs.utils import get_current_ms
|
||||||
|
from libs.texture import SCREEN_WIDTH, SCREEN_HEIGHT
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ class VideoPlayer:
|
|||||||
def draw(self):
|
def draw(self):
|
||||||
"""Draw video frames to the raylib canvas"""
|
"""Draw video frames to the raylib canvas"""
|
||||||
if self.texture is not None:
|
if self.texture is not None:
|
||||||
ray.DrawTexture(self.texture, 0, 0, ray.WHITE)
|
ray.DrawTexturePro(self.texture, (0, 0, self.texture.width, self.texture.height), (0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), (0, 0), 0, ray.WHITE)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stops the video, audio, and clears its buffer"""
|
"""Stops the video, audio, and clears its buffer"""
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import pyray as ray
|
|||||||
|
|
||||||
from libs.audio import audio
|
from libs.audio import audio
|
||||||
from libs.global_data import PlayerNum, global_data
|
from libs.global_data import PlayerNum, global_data
|
||||||
from libs.texture import tex
|
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex
|
||||||
from libs.chara_2d import Chara2D
|
from libs.chara_2d import Chara2D
|
||||||
from libs.global_objects import AllNetIcon, CoinOverlay, Indicator, Nameplate, Timer
|
from libs.global_objects import AllNetIcon, CoinOverlay, Indicator, Nameplate, Timer
|
||||||
from libs.screen import Screen
|
from libs.screen import Screen
|
||||||
from libs.file_navigator import DanCourse, navigator
|
from libs.file_navigator import BackBox, DanCourse, navigator
|
||||||
from libs.transition import Transition
|
from libs.transition import Transition
|
||||||
from libs.utils import get_current_ms, is_l_don_pressed, is_l_kat_pressed, is_r_don_pressed, is_r_kat_pressed
|
from libs.utils import get_current_ms, is_l_don_pressed, is_l_kat_pressed, is_r_don_pressed, is_r_kat_pressed
|
||||||
from scenes.song_select import SongSelectScreen, State
|
from scenes.song_select import State
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ class DanSelectScreen(Screen):
|
|||||||
session_data = global_data.session_data[global_data.player_num]
|
session_data = global_data.session_data[global_data.player_num]
|
||||||
current_item = self.navigator.get_current_item()
|
current_item = self.navigator.get_current_item()
|
||||||
if isinstance(current_item, DanCourse):
|
if isinstance(current_item, DanCourse):
|
||||||
session_data.selected_song = current_item.charts[0]
|
session_data.selected_song = current_item.charts[0][0].file_path
|
||||||
session_data.selected_dan = current_item.charts
|
session_data.selected_dan = current_item.charts
|
||||||
session_data.selected_dan_exam = current_item.exams
|
session_data.selected_dan_exam = current_item.exams
|
||||||
session_data.song_title = current_item.title
|
session_data.song_title = current_item.title
|
||||||
@@ -88,8 +88,9 @@ class DanSelectScreen(Screen):
|
|||||||
if self.transition.is_finished:
|
if self.transition.is_finished:
|
||||||
return self.on_screen_end("GAME_DAN")
|
return self.on_screen_end("GAME_DAN")
|
||||||
for song in self.navigator.items:
|
for song in self.navigator.items:
|
||||||
song.box.update(False)
|
if not song.box.text_loaded:
|
||||||
song.box.is_open = song.box.position == SongSelectScreen.BOX_CENTER + 150
|
song.box.load_text()
|
||||||
|
song.box.update(current_time, False)
|
||||||
self.player.update(current_time)
|
self.player.update(current_time)
|
||||||
res = self.handle_input(self.state, self)
|
res = self.handle_input(self.state, self)
|
||||||
if res == 'go_back':
|
if res == 'go_back':
|
||||||
@@ -102,13 +103,13 @@ class DanSelectScreen(Screen):
|
|||||||
tex.draw_texture('global', 'footer')
|
tex.draw_texture('global', 'footer')
|
||||||
for item in self.navigator.items:
|
for item in self.navigator.items:
|
||||||
box = item.box
|
box = item.box
|
||||||
if -156 <= box.position <= 1280 + 144:
|
if -156 <= box.position <= SCREEN_WIDTH + 144:
|
||||||
if box.position <= 500:
|
if box.position <= 500:
|
||||||
box.draw(box.position, 95, False)
|
box.draw(box.position, 95, False)
|
||||||
else:
|
else:
|
||||||
box.draw(box.position, 95, False)
|
box.draw(box.position, 95, False)
|
||||||
if self.state == State.SONG_SELECTED:
|
if self.state == State.SONG_SELECTED:
|
||||||
ray.draw_rectangle(0, 0, 1280, 720, ray.fade(ray.BLACK, min(0.5, self.player.confirmation_window.fade_in.attribute)))
|
ray.draw_rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ray.fade(ray.BLACK, min(0.5, self.player.confirmation_window.fade_in.attribute)))
|
||||||
self.player.draw()
|
self.player.draw()
|
||||||
self.indicator.draw(410, 575)
|
self.indicator.draw(410, 575)
|
||||||
self.timer.draw()
|
self.timer.draw()
|
||||||
@@ -169,7 +170,7 @@ class DanSelectPlayer:
|
|||||||
|
|
||||||
# Select/Enter
|
# Select/Enter
|
||||||
if is_l_don_pressed(self.player_num) or is_r_don_pressed(self.player_num):
|
if is_l_don_pressed(self.player_num) or is_r_don_pressed(self.player_num):
|
||||||
if selected_item is not None and selected_item.box.is_back:
|
if selected_item is not None and isinstance(selected_item.box, BackBox):
|
||||||
audio.play_sound('cancel', 'sound')
|
audio.play_sound('cancel', 'sound')
|
||||||
return "go_back"
|
return "go_back"
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -185,7 +185,10 @@ class DanGameScreen(GameScreen):
|
|||||||
self.transition.update(current_time)
|
self.transition.update(current_time)
|
||||||
self.current_ms = current_time - self.start_ms
|
self.current_ms = current_time - self.start_ms
|
||||||
self.dan_transition.update(current_time)
|
self.dan_transition.update(current_time)
|
||||||
self.start_song(current_time)
|
if self.transition.is_finished and self.dan_transition.is_finished:
|
||||||
|
self.start_song(self.current_ms)
|
||||||
|
else:
|
||||||
|
self.start_ms = current_time - self.tja.metadata.offset*1000
|
||||||
self.update_background(current_time)
|
self.update_background(current_time)
|
||||||
|
|
||||||
if self.song_music is not None:
|
if self.song_music is not None:
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ class EntryScreen(Screen):
|
|||||||
self.state = State.SELECT_SIDE
|
self.state = State.SELECT_SIDE
|
||||||
plate_info = global_data.config['nameplate_2p']
|
plate_info = global_data.config['nameplate_2p']
|
||||||
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], PlayerNum.ALL, -1, False, False, 1)
|
self.nameplate = Nameplate(plate_info['name'], plate_info['title'], PlayerNum.ALL, -1, False, False, 1)
|
||||||
self.chara = Chara2D(1, 100)
|
self.chara = Chara2D(1)
|
||||||
self.side_select_fade.restart()
|
self.side_select_fade.restart()
|
||||||
self.side = 1
|
self.side = 1
|
||||||
elif self.players[0] and self.players[0].player_num == PlayerNum.P2 and is_l_don_pressed(PlayerNum.P1) or is_r_don_pressed(PlayerNum.P1):
|
elif self.players[0] and self.players[0].player_num == PlayerNum.P2 and is_l_don_pressed(PlayerNum.P1) or is_r_don_pressed(PlayerNum.P1):
|
||||||
@@ -291,19 +291,19 @@ class EntryPlayer:
|
|||||||
move_y = self.drum_move_1.attribute + self.drum_move_2.attribute
|
move_y = self.drum_move_1.attribute + self.drum_move_2.attribute
|
||||||
|
|
||||||
if self.side == 0: # Left side (1P/red)
|
if self.side == 0: # Left side (1P/red)
|
||||||
offset = 0
|
offset = tex.skin_config["entry_drum_offset"].x
|
||||||
tex.draw_texture('side_select', 'red_drum', x=move_x, y=move_y)
|
tex.draw_texture('side_select', 'red_drum', x=move_x, y=move_y)
|
||||||
chara_x = move_x + offset + 170
|
chara_x = move_x + offset + tex.skin_config["entry_chara_offset_l"].x
|
||||||
chara_mirror = False
|
chara_mirror = False
|
||||||
else: # Right side (2P/blue)
|
else: # Right side (2P/blue)
|
||||||
move_x *= -1
|
move_x *= -1
|
||||||
offset = 620
|
offset = tex.skin_config["entry_drum_offset"].y # bad practice to use y value as x value
|
||||||
tex.draw_texture('side_select', 'blue_drum', x=move_x, y=move_y)
|
tex.draw_texture('side_select', 'blue_drum', x=move_x, y=move_y)
|
||||||
chara_x = move_x + offset + 130
|
chara_x = move_x + offset + tex.skin_config["entry_chara_offset_r"].x
|
||||||
chara_mirror = True
|
chara_mirror = True
|
||||||
|
|
||||||
# Draw character
|
# Draw character
|
||||||
chara_y = 570 + move_y
|
chara_y = tex.skin_config["entry_chara_offset_r"].y + move_y
|
||||||
self.chara.draw(chara_x, chara_y, mirror=chara_mirror)
|
self.chara.draw(chara_x, chara_y, mirror=chara_mirror)
|
||||||
|
|
||||||
# Draw cloud
|
# Draw cloud
|
||||||
@@ -414,7 +414,7 @@ class Box:
|
|||||||
texture_left = tex.textures['mode_select']['box_highlight_left'].texture
|
texture_left = tex.textures['mode_select']['box_highlight_left'].texture
|
||||||
if isinstance(texture_left, list):
|
if isinstance(texture_left, list):
|
||||||
raise Exception("highlight textures cannot be iterable")
|
raise Exception("highlight textures cannot be iterable")
|
||||||
tex.draw_texture('mode_select', 'box_highlight_center', x=self.left_x + texture_left.width, y=self.y, x2=self.right_x - self.left_x -15, color=color)
|
tex.draw_texture('mode_select', 'box_highlight_center', x=self.left_x + texture_left.width, y=self.y, x2=self.right_x - self.left_x + tex.skin_config["entry_box_highlight_offset"].x, color=color)
|
||||||
tex.draw_texture('mode_select', 'box_highlight_left', x=self.left_x, y=self.y, color=color)
|
tex.draw_texture('mode_select', 'box_highlight_left', x=self.left_x, y=self.y, color=color)
|
||||||
tex.draw_texture('mode_select', 'box_highlight_right', x=self.right_x, y=self.y, color=color)
|
tex.draw_texture('mode_select', 'box_highlight_right', x=self.right_x, y=self.y, color=color)
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ class Box:
|
|||||||
text_x = self.x + (self.texture.width//2) - (self.text.texture.width//2)
|
text_x = self.x + (self.texture.width//2) - (self.text.texture.width//2)
|
||||||
if self.is_selected:
|
if self.is_selected:
|
||||||
text_x += self.open.attribute
|
text_x += self.open.attribute
|
||||||
text_y = self.y + 20
|
text_y = self.y + tex.skin_config["entry_box_text_offset"].y
|
||||||
if self.is_selected:
|
if self.is_selected:
|
||||||
self.text.draw(outline_color=ray.BLACK, x=text_x, y=text_y, color=color)
|
self.text.draw(outline_color=ray.BLACK, x=text_x, y=text_y, color=color)
|
||||||
else:
|
else:
|
||||||
@@ -430,7 +430,7 @@ class Box:
|
|||||||
|
|
||||||
def draw(self, fade: float):
|
def draw(self, fade: float):
|
||||||
color = ray.fade(ray.WHITE, fade)
|
color = ray.fade(ray.WHITE, fade)
|
||||||
ray.draw_texture(self.texture, self.x, self.y, color)
|
ray.draw_texture(self.texture, int(self.x), int(self.y), color)
|
||||||
if self.is_selected and self.move.is_finished:
|
if self.is_selected and self.move.is_finished:
|
||||||
self._draw_highlighted(color)
|
self._draw_highlighted(color)
|
||||||
self._draw_text(color)
|
self._draw_text(color)
|
||||||
@@ -439,9 +439,9 @@ class BoxManager:
|
|||||||
"""BoxManager class for the entry screen"""
|
"""BoxManager class for the entry screen"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.box_titles: list[OutlinedText] = [
|
self.box_titles: list[OutlinedText] = [
|
||||||
OutlinedText('演奏ゲーム', 50, ray.WHITE, outline_thickness=5, vertical=True),
|
OutlinedText('演奏ゲーム', tex.skin_config["entry_box_text"].font_size, ray.WHITE, outline_thickness=5, vertical=True),
|
||||||
OutlinedText('特訓モード', 50, ray.WHITE, outline_thickness=5, vertical=True),
|
OutlinedText('特訓モード', tex.skin_config["entry_box_text"].font_size, ray.WHITE, outline_thickness=5, vertical=True),
|
||||||
OutlinedText('ゲーム設定', 50, ray.WHITE, outline_thickness=5, vertical=True)]
|
OutlinedText('ゲーム設定', tex.skin_config["entry_box_text"].font_size, ray.WHITE, outline_thickness=5, vertical=True)]
|
||||||
self.box_locations = ["SONG_SELECT", "PRACTICE_SELECT", "SETTINGS"]
|
self.box_locations = ["SONG_SELECT", "PRACTICE_SELECT", "SETTINGS"]
|
||||||
self.num_boxes = len(self.box_titles)
|
self.num_boxes = len(self.box_titles)
|
||||||
self.boxes = [Box(self.box_titles[i], self.box_locations[i]) for i in range(len(self.box_titles))]
|
self.boxes = [Box(self.box_titles[i], self.box_locations[i]) for i in range(len(self.box_titles))]
|
||||||
@@ -449,7 +449,7 @@ class BoxManager:
|
|||||||
self.fade_out = tex.get_animation(9)
|
self.fade_out = tex.get_animation(9)
|
||||||
self.is_2p = False
|
self.is_2p = False
|
||||||
|
|
||||||
spacing = 80
|
spacing = tex.skin_config["entry_box_spacing"].x
|
||||||
box_width = self.boxes[0].texture.width
|
box_width = self.boxes[0].texture.width
|
||||||
total_width = self.num_boxes * box_width + (self.num_boxes - 1) * spacing
|
total_width = self.num_boxes * box_width + (self.num_boxes - 1) * spacing
|
||||||
start_x = SCREEN_WIDTH//2 - total_width//2
|
start_x = SCREEN_WIDTH//2 - total_width//2
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from libs.animation import Animation
|
|||||||
from libs.global_objects import AllNetIcon
|
from libs.global_objects import AllNetIcon
|
||||||
from libs.screen import Screen
|
from libs.screen import Screen
|
||||||
from libs.song_hash import build_song_hashes
|
from libs.song_hash import build_song_hashes
|
||||||
from libs.texture import tex
|
from libs.texture import SCREEN_HEIGHT, SCREEN_WIDTH, tex
|
||||||
from libs.utils import get_current_ms, global_data
|
from libs.utils import get_current_ms, global_data
|
||||||
from libs.file_navigator import navigator
|
from libs.file_navigator import navigator
|
||||||
|
|
||||||
@@ -17,8 +17,8 @@ logger = logging.getLogger(__name__)
|
|||||||
class LoadScreen(Screen):
|
class LoadScreen(Screen):
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
super().__init__(name)
|
super().__init__(name)
|
||||||
self.width = 1280
|
self.width = SCREEN_WIDTH
|
||||||
self.height = 720
|
self.height = SCREEN_HEIGHT
|
||||||
self.songs_loaded = False
|
self.songs_loaded = False
|
||||||
self.navigator_started = False
|
self.navigator_started = False
|
||||||
self.loading_complete = False
|
self.loading_complete = False
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
import pyray as ray
|
import pyray as ray
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from libs.file_navigator import DanCourse, navigator
|
from libs.file_navigator import BackBox, DanCourse, navigator
|
||||||
from libs.audio import audio
|
from libs.audio import audio
|
||||||
from libs.chara_2d import Chara2D
|
from libs.chara_2d import Chara2D
|
||||||
from libs.file_navigator import Directory, SongBox, SongFile
|
from libs.file_navigator import Directory, SongBox, SongFile
|
||||||
@@ -79,21 +79,23 @@ class SongSelectScreen(Screen):
|
|||||||
self.navigator.mark_crowns_dirty_for_song(selected_song)
|
self.navigator.mark_crowns_dirty_for_song(selected_song)
|
||||||
|
|
||||||
curr_item = self.navigator.get_current_item()
|
curr_item = self.navigator.get_current_item()
|
||||||
curr_item.box.get_scores()
|
if isinstance(curr_item, SongFile):
|
||||||
|
curr_item.box.get_scores()
|
||||||
self.navigator.add_recent()
|
self.navigator.add_recent()
|
||||||
|
|
||||||
def finalize_song(self):
|
def finalize_song(self, current_item: SongFile):
|
||||||
global_data.session_data[global_data.player_num].selected_song = self.navigator.get_current_item().path
|
global_data.session_data[global_data.player_num].selected_song = current_item.path
|
||||||
global_data.session_data[global_data.player_num].selected_difficulty = self.player_1.selected_difficulty
|
global_data.session_data[global_data.player_num].selected_difficulty = self.player_1.selected_difficulty
|
||||||
global_data.session_data[global_data.player_num].genre_index = self.navigator.get_current_item().box.name_texture_index
|
global_data.session_data[global_data.player_num].genre_index = current_item.box.name_texture_index
|
||||||
|
|
||||||
def on_screen_end(self, next_screen):
|
def on_screen_end(self, next_screen):
|
||||||
self.screen_init = False
|
self.screen_init = False
|
||||||
self.reset_demo_music()
|
self.reset_demo_music()
|
||||||
self.finalize_song()
|
|
||||||
self.player_1.nameplate.unload()
|
|
||||||
current_item = self.navigator.get_current_item()
|
current_item = self.navigator.get_current_item()
|
||||||
if current_item.box.yellow_box is not None:
|
if isinstance(current_item, SongFile):
|
||||||
|
self.finalize_song(current_item)
|
||||||
|
self.player_1.nameplate.unload()
|
||||||
|
if isinstance(current_item.box, SongBox) and current_item.box.yellow_box is not None:
|
||||||
current_item.box.yellow_box.create_anim()
|
current_item.box.yellow_box.create_anim()
|
||||||
return super().on_screen_end(next_screen)
|
return super().on_screen_end(next_screen)
|
||||||
|
|
||||||
@@ -156,6 +158,8 @@ class SongSelectScreen(Screen):
|
|||||||
elif action == "add_favorite":
|
elif action == "add_favorite":
|
||||||
self.navigator.add_favorite()
|
self.navigator.add_favorite()
|
||||||
current_box = self.navigator.get_current_item().box
|
current_box = self.navigator.get_current_item().box
|
||||||
|
if not isinstance(current_box, SongBox):
|
||||||
|
return
|
||||||
current_box.is_favorite = not current_box.is_favorite
|
current_box.is_favorite = not current_box.is_favorite
|
||||||
|
|
||||||
def handle_input_selected(self):
|
def handle_input_selected(self):
|
||||||
@@ -281,18 +285,19 @@ class SongSelectScreen(Screen):
|
|||||||
audio.update_music_stream(self.demo_song)
|
audio.update_music_stream(self.demo_song)
|
||||||
|
|
||||||
if self.navigator.genre_bg is not None:
|
if self.navigator.genre_bg is not None:
|
||||||
self.navigator.genre_bg.update(get_current_ms())
|
self.navigator.genre_bg.update(current_time)
|
||||||
|
|
||||||
if self.diff_sort_selector is not None:
|
if self.diff_sort_selector is not None:
|
||||||
self.diff_sort_selector.update(get_current_ms())
|
self.diff_sort_selector.update(current_time)
|
||||||
|
|
||||||
self.check_for_selection()
|
self.check_for_selection()
|
||||||
|
|
||||||
for song in self.navigator.items:
|
for song in self.navigator.items:
|
||||||
song.box.update(self.state == State.SONG_SELECTED)
|
song.box.update(current_time, self.state == State.SONG_SELECTED)
|
||||||
song.box.is_open = song.box.position == SongSelectScreen.BOX_CENTER + 150
|
if not song.box.text_loaded:
|
||||||
|
song.box.load_text()
|
||||||
if not isinstance(song, Directory) and song.box.is_open:
|
if not isinstance(song, Directory) and song.box.is_open:
|
||||||
if self.demo_song is None and get_current_ms() >= song.box.wait + (83.33*3):
|
if self.demo_song is None and current_time >= song.box.wait + (83.33*3):
|
||||||
song.box.get_scores()
|
song.box.get_scores()
|
||||||
if song.tja.metadata.wave.exists() and song.tja.metadata.wave.is_file():
|
if song.tja.metadata.wave.exists() and song.tja.metadata.wave.is_file():
|
||||||
self.demo_song = audio.load_music_stream(song.tja.metadata.wave, 'demo_song')
|
self.demo_song = audio.load_music_stream(song.tja.metadata.wave, 'demo_song')
|
||||||
@@ -302,7 +307,7 @@ class SongSelectScreen(Screen):
|
|||||||
logger.info(f"Demo song loaded and playing for {song.tja.metadata.title}")
|
logger.info(f"Demo song loaded and playing for {song.tja.metadata.title}")
|
||||||
if song.box.is_open:
|
if song.box.is_open:
|
||||||
current_box = song.box
|
current_box = song.box
|
||||||
if not current_box.is_back and get_current_ms() >= song.box.wait + (83.33*3):
|
if not isinstance(current_box, BackBox) and current_time >= song.box.wait + (83.33*3):
|
||||||
self.texture_index = current_box.texture_index
|
self.texture_index = current_box.texture_index
|
||||||
|
|
||||||
if ray.is_key_pressed(global_data.config["keys"]["back_key"]):
|
if ray.is_key_pressed(global_data.config["keys"]["back_key"]):
|
||||||
@@ -326,7 +331,7 @@ class SongSelectScreen(Screen):
|
|||||||
if self.navigator.genre_bg is not None and self.state == State.BROWSING:
|
if self.navigator.genre_bg is not None and self.state == State.BROWSING:
|
||||||
self.navigator.genre_bg.draw(95)
|
self.navigator.genre_bg.draw(95)
|
||||||
|
|
||||||
for item in self.navigator.items:
|
for i, item in enumerate(self.navigator.items):
|
||||||
box = item.box
|
box = item.box
|
||||||
if -156 <= box.position <= SCREEN_WIDTH + 144:
|
if -156 <= box.position <= SCREEN_WIDTH + 144:
|
||||||
if box.position <= 500:
|
if box.position <= 500:
|
||||||
@@ -354,7 +359,9 @@ class SongSelectScreen(Screen):
|
|||||||
self.draw_players()
|
self.draw_players()
|
||||||
|
|
||||||
if self.state == State.BROWSING and self.navigator.items != []:
|
if self.state == State.BROWSING and self.navigator.items != []:
|
||||||
self.navigator.get_current_item().box.draw_score_history()
|
curr_item = self.navigator.get_current_item()
|
||||||
|
if isinstance(curr_item, SongFile):
|
||||||
|
curr_item.box.draw_score_history()
|
||||||
|
|
||||||
self.indicator.draw(410, 575)
|
self.indicator.draw(410, 575)
|
||||||
|
|
||||||
@@ -461,7 +468,7 @@ class SongSelectPlayer:
|
|||||||
|
|
||||||
# Select/Enter
|
# Select/Enter
|
||||||
if is_l_don_pressed(self.player_num) or is_r_don_pressed(self.player_num):
|
if is_l_don_pressed(self.player_num) or is_r_don_pressed(self.player_num):
|
||||||
if selected_item is not None and selected_item.box.is_back:
|
if selected_item is not None and isinstance(selected_item.box, BackBox):
|
||||||
audio.play_sound('cancel', 'sound')
|
audio.play_sound('cancel', 'sound')
|
||||||
return "go_back"
|
return "go_back"
|
||||||
elif isinstance(selected_item, Directory) and selected_item.collection == Directory.COLLECTIONS[3]:
|
elif isinstance(selected_item, Directory) and selected_item.collection == Directory.COLLECTIONS[3]:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import logging
|
import logging
|
||||||
from libs.file_navigator import SongFile
|
from libs.file_navigator import SongBox, SongFile
|
||||||
from libs.global_data import PlayerNum
|
from libs.global_data import PlayerNum
|
||||||
from libs.transition import Transition
|
from libs.transition import Transition
|
||||||
from scenes.song_select import DiffSortSelect, SongSelectPlayer, SongSelectScreen, State
|
from scenes.song_select import DiffSortSelect, SongSelectPlayer, SongSelectScreen, State
|
||||||
@@ -14,9 +14,9 @@ class TwoPlayerSongSelectScreen(SongSelectScreen):
|
|||||||
self.player_1 = SongSelectPlayer(PlayerNum.P1, self.text_fade_in)
|
self.player_1 = SongSelectPlayer(PlayerNum.P1, self.text_fade_in)
|
||||||
self.player_2 = SongSelectPlayer(PlayerNum.P2, self.text_fade_in)
|
self.player_2 = SongSelectPlayer(PlayerNum.P2, self.text_fade_in)
|
||||||
|
|
||||||
def finalize_song(self):
|
def finalize_song(self, current_item):
|
||||||
global_data.session_data[PlayerNum.P1].selected_song = self.navigator.get_current_item().path
|
global_data.session_data[PlayerNum.P1].selected_song = current_item.path
|
||||||
global_data.session_data[PlayerNum.P1].genre_index = self.navigator.get_current_item().box.name_texture_index
|
global_data.session_data[PlayerNum.P1].genre_index = current_item.box.name_texture_index
|
||||||
logger.info(f"Finalized song selection: {global_data.session_data[PlayerNum.P1].selected_song}")
|
logger.info(f"Finalized song selection: {global_data.session_data[PlayerNum.P1].selected_song}")
|
||||||
|
|
||||||
def handle_input(self):
|
def handle_input(self):
|
||||||
@@ -81,6 +81,8 @@ class TwoPlayerSongSelectScreen(SongSelectScreen):
|
|||||||
elif action == "add_favorite":
|
elif action == "add_favorite":
|
||||||
self.navigator.add_favorite()
|
self.navigator.add_favorite()
|
||||||
current_box = self.navigator.get_current_item().box
|
current_box = self.navigator.get_current_item().box
|
||||||
|
if not isinstance(current_box, SongBox):
|
||||||
|
return
|
||||||
current_box.is_favorite = not current_box.is_favorite
|
current_box.is_favorite = not current_box.is_favorite
|
||||||
|
|
||||||
def handle_input_selected(self):
|
def handle_input_selected(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user