Skip to content

Commit a36ebff

Browse files
authored
Merge pull request #6 from MrrDevils/designant-support
Add support for parsing and rendering Designant.'s "red" arcs and arctaps
2 parents fc5acda + f1a6c1c commit a36ebff

File tree

5 files changed

+29
-12
lines changed

5 files changed

+29
-12
lines changed

ArcaeaChartRender/aff/token.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class Value(object):
2929
class SkyLine(object):
3030
true = 'true'
3131
false = 'false'
32-
all = [true, false]
32+
designant = 'designant'
33+
all = [true, false, designant]
3334

3435
class HitSound(object):
3536
none = 'none'

ArcaeaChartRender/element.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
from abc import ABC, abstractmethod
1919
from itertools import chain
20-
from typing import Union, Optional, Type, TypeVar, Iterator, Iterable
20+
from typing import Union, Optional, Type, TypeVar, Iterator, Iterable, Literal
2121

2222
from .aff.token import AffToken, Color
2323
from .utils import len_iter
@@ -320,15 +320,17 @@ def __init__(
320320
self.hit_sound = hit_sound
321321
# Regardless of the value of is_skyline,
322322
# as long as arctap_list exists, then it must be skyline.
323-
self.is_skyline = {
323+
self.is_skyline: bool | Literal['Designant'] = {
324324
AffToken.Value.SkyLine.true: True,
325-
AffToken.Value.SkyLine.false: False
325+
AffToken.Value.SkyLine.false: False,
326+
AffToken.Value.SkyLine.designant: 'Designant'
326327
}[is_skyline] or bool(arctap_list)
327328
self.arctap_list = arctap_list
328329

329330
def __repr__(self):
330331
pos = f'from ({self.x1}, {self.y1}) to ({self.x2}, {self.y2})'
331-
if self.is_skyline:
332+
color: Color | Literal['Designant'] = self.color
333+
if self.is_skyline is True:
332334
if self.arctap_list:
333335
literal_arctap_list = ', with arctap: ' + ' '.join(map(lambda _: str(_.tn), self.arctap_list))
334336
else:
@@ -337,7 +339,9 @@ def __repr__(self):
337339
f'[{self.t1} -> {self.t2} Skyline] {pos}'
338340
f'{literal_arctap_list}'
339341
)
340-
return f'[{self.t1} -> {self.t2} {self.color} Arc] {pos}'
342+
elif self.is_skyline == 'Designant':
343+
color = 'Designant'
344+
return f'[{self.t1} -> {self.t2} {color} Arc] {pos}'
341345

342346
def __eq__(self, other):
343347
return all([
@@ -607,7 +611,7 @@ def get_combo_of(self, type_: Type['Note']):
607611
Return 0 if 'type_list' contains 'noinput'.
608612
"""
609613
return 0 if 'noinput' in self.type_list else super().get_combo_of(type_)
610-
614+
611615
def get_total_combo_before(self, t: int) -> int:
612616
"""
613617
Return the total combo before given time.

ArcaeaChartRender/render.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def __init__(self, aff_path: str, cover_path: str, song: Song, difficulty: int,
162162
self._render()
163163

164164
def _render(self):
165-
self.theme = LightTheme if self._song.side == 0 else ConflictTheme
165+
self.theme = ConflictTheme if self._song.side == 1 else LightTheme # for Colorless and Lephon
166166
self.im = Image.new('RGBA', (width_track + additional_canvas_width, self.h), self.theme.transparent_color)
167167

168168
self._draw_track_tile()
@@ -277,18 +277,25 @@ def _draw_note_hold(self):
277277
t = hold.t1 // resize
278278
self.im.alpha_composite(im_stretched_hold, (int(x), Coordinate.from_cartesian(self.h, t, stretched_height_hold)))
279279

280+
280281
def _draw_arc_tap(self):
281282
"""Draw all ArcTaps on skyline."""
282283
im_arctap = Image.open(self.theme.arctap_path).convert('RGBA').resize((width_arctap, height_arctap))
283284
im_arctap_sfx = Image.open(self.theme.arctap_sfx_path).convert('RGBA')
284285
im_arctap_sfx = im_arctap_sfx.resize((width_arctap, height_arctap))
286+
im_arctap_designant = Image.open(self.theme.arctap_designant_path).convert(
287+
'RGBA').resize((width_arctap, height_arctap))
288+
289+
def skyline_or_designant(arc: Arc) -> Image.Image:
290+
return im_arctap if arc.is_skyline is True else im_arctap_designant
291+
285292
for arc in self._chart.get_command_list_for_type(Arc, search_in_timing_group=True, exclude_noinput=False):
286293
sample = Sample(arc)
287294
which_im_arctap = {
288295
AffToken.Value.HitSound.glass_wav: im_arctap_sfx,
289296
AffToken.Value.HitSound.voice_wav: im_arctap_sfx,
290297
AffToken.Value.HitSound.kick_wav: im_arctap_sfx,
291-
}.get(arc.hit_sound, im_arctap)
298+
}.get(arc.hit_sound, skyline_or_designant(arc))
292299
for arctap in arc.arctap_list: # An Arc with an empty arctap_list will be automatically skipped.
293300
x, z = Coordinate.from_normalized(sample.get_coordinate_tuple(arctap.tn))
294301
t = arctap.tn // resize
@@ -321,8 +328,10 @@ def _draw_arc(self):
321328
Color.Green: (im_arc_green, self.theme.arc_green_color),
322329
}.get(arc.color)
323330
thickness = self.theme.thickness_arc
324-
elif arc.is_skyline:
331+
elif arc.is_skyline is True:
325332
im, color, thickness = im_arc_skyline, self.theme.arc_skyline_color, self.theme.thickness_skyline
333+
elif arc.is_skyline == 'Designant':
334+
im, color, thickness = im_arc_skyline, self.theme.arc_designant_color, self.theme.thickness_skyline
326335
else:
327336
raise TypeError(f'Unsupported arc type: {arc}')
328337
# draw arc or skyline

ArcaeaChartRender/theme.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ class BaseTheme(ABC):
6464
arc_green_color = (35, 255, 108)
6565
arc_alpha = (0, 0, 0) # for arc whose color is Color.Alpha (like PRAGMATISM BYD)
6666
arc_skyline_color = (144, 138, 144)
67+
arc_designant_color = (201, 46, 22)
6768
text_song_title_color = (222, 222, 222, 255) # color for song title at text area
6869
text_song_title_stroke_color = (70, 70, 70, 255)
70+
arctap_designant_path = './assets/models/tap_tomato.png'
6971

7072
thickness_arc = 10
7173
thickness_skyline = 2

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,18 @@ Before using, you need to copy and rename [`theme.py`](./ArcaeaChartRender/theme
2525
If a property of `BaseTheme` is inherited by one of its subclasses (e.g. `LightTheme`), you should modify the property on its subclass. If the property is not inherited, then you should modify it directly on `BaseTheme`.
2626

2727
| name | file |
28-
|-----------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
28+
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
2929
| `font_Exo_SemiBold_XX` | `Exo-SemiBold.ttf` |
3030
| `font_Kazesawa_Regular_XX` | `Kazesawa-Regular.ttf` |
3131
| `font_SourceHanMonoSC_Regular_XX` | [`SourceHanMonoSC-Regular.otf`](https://github.com/adobe-fonts/source-han-mono/blob/master/Regular/OTC/SourceHanMonoSC-Regular.otf) |
3232
| `tile_path` | `track.png` and `track_dark.png` |
3333
| `tap_path` | `note.png` and `note_dark.png` |
3434
| `hold_path` | `note_hold.png` and `note_hold_dark.png` |
3535
| `arctap_path` | `tap_l.png` and `tap_d.png` |
36+
| `arctap_designant_path` | `tap_tomato.png` |
3637
| `arctap_sfx_path` | `sfx_l_note.jpg` and `sfx_d_note.jpg` |
3738
| `default_bg_path` | `base_light.jpg` and `base_conflict.jpg` |
38-
| `custom_bg_dir_path ` | put your custom background here if `bg` field has been defined in songlist |
39+
| `custom_bg_dir_path` | put your custom background here if `bg` field has been defined in songlist |
3940

4041
> ⚠ Note: <br> This repo does **NOT** provide these assets files, you need to obtain them by yourself. It is recommended to get them at [Arcaea-Infinity/OpenArcaeaArts](https://github.com/Arcaea-Infinity/OpenArcaeaArts) (Licensed under `CC BY-NC`).
4142

0 commit comments

Comments
 (0)