Resources & Declarations¶
Global Variables¶
Level Memory¶
Level memory is defined with the @level_memory
class decorator:
from sonolus.script.globals import level_memory
@level_memory
class LevelMemory:
value: int
Alternatively, it may be called as a function as well by passing the type as an argument:
from sonolus.script.globals import level_memory
from sonolus.script.vec import Vec2
level_memory_value = level_memory(Vec2)
Level memory may be modified in sequential callbacks:
preprocess
update_sequential
touch
and may be read in any callback.
Level Data¶
Level data is defined with the @level_data
class decorator:
from sonolus.script.globals import level_data
@level_data
class LevelData:
value: int
Alternatively, it may be called as a function as well by passing the type as an argument:
from sonolus.script.globals import level_data
from sonolus.script.vec import Vec2
level_data_value = level_data(Vec2)
Level data may only be modified in the preprocess
callback and may be read in any callback.
Archetype Variables¶
Imported¶
Imported fields are declared with imported()
:
from sonolus.script.archetype import PlayArchetype, imported
class MyArchetype(PlayArchetype):
field: int = imported()
field_with_explicit_name: int = imported(name="field_name")
Imported fields may be loaded from the level data. In watch mode, data may also be loaded from a corresponding exported field in play mode.
Imported fields may only be updated in the preprocess
callback, and are read-only in other callbacks.
Exported¶
Exported fields are declared with exported()
:
from sonolus.script.archetype import PlayArchetype, exported
class MyArchetype(PlayArchetype):
field: int = exported()
field_with_explicit_name: int = exported(name="#FIELD")
This is only usable in play mode to export data to be loaded in watch mode. Exported fields are write-only.
Entity Data¶
Entity data fields are declared with entity_data()
:
from sonolus.script.archetype import PlayArchetype, entity_data
class MyArchetype(PlayArchetype):
field: int = entity_data()
Entity data is accessible from other entities, but may only be updated in the preprocess
callback and is read-only in other callbacks.
It functions like imported()
and shares the same underlying storage, except that it is not loaded from a level.
Entity Memory¶
Entity memory fields are declared with entity_memory()
:
from sonolus.script.archetype import PlayArchetype, entity_memory
class MyArchetype(PlayArchetype):
field: int = entity_memory()
Entity memory is private to the entity and is not accessible from other entities. It may be read or updated in any callback associated with the entity.
Entity memory fields may also be set when an entity is spawned using the spawn()
method.
Shared Memory¶
Shared memory fields are declared with shared_memory()
:
from sonolus.script.archetype import PlayArchetype, shared_memory
class MyArchetype(PlayArchetype):
field: int = shared_memory()
Shared memory is accessible from other entities.
Shared memory may be read in any callback, but may only be updated by sequential callbacks (preprocess
, update_sequential
, and touch
).
Streams¶
Streams are defined with the @streams
decorator:
from sonolus.script.stream import streams, Stream, StreamGroup
from sonolus.script.num import Num
from sonolus.script.vec import Vec2
@streams
class Streams:
stream_1: Stream[Num] # A stream of Num values
stream_2: Stream[Vec2] # A stream of Vec2 values
group_1: StreamGroup[Num, 10] # A group of 10 Num streams
group_2: StreamGroup[Vec2, 5] # A group of 5 Vec2 streams
data_field_1: Num # A data field of type Num
data_field_2: Vec2 # A data field of type Vec2
Streams and stream groups are declared by annotating class attributes with Stream
or StreamGroup
.
Other types are also supported in the form of data fields. They may be used to store additional data to export from Play to Watch mode.
In either case, data is write-only in Play mode and read-only in Watch mode.
This should only be used once in most projects, as multiple decorated classes will overlap with each other and interfere when both are used at the same time.
For backwards compatibility, new streams and stream groups should be added to the end of existing ones, and lengths and element types of existing streams and stream groups should not be changed. Otherwise, old replays may not work on new versions of the engine.
Skins¶
Skins are defined with the @skin
decorator:
from sonolus.script.sprite import skin, StandardSprite, sprite, Sprite, RenderMode
@skin
class Skin:
render_mode: RenderMode = RenderMode.DEFAULT
note: StandardSprite.NOTE_HEAD_RED
other: Sprite = sprite("other")
Standard sprites are defined by annotating the field with the corresponding value from StandardSprite
.
Custom sprites are defined by annotating the field with Sprite
and calling sprite
with the sprite name.
To set the render mode for the skin, set the render_mode
field to the desired value from RenderMode
.
Sound Effects¶
Sound effects are defined with the @effects
decorator:
from sonolus.script.effect import effects, StandardEffect, Effect, effect
@effects
class Effects:
tap_perfect: StandardEffect.PERFECT
other: Effect = effect("other")
Standard sound effects are defined by annotating the field with the corresponding value from StandardEffect
.
Custom sound effects are defined by annotating the field with Effect
and calling effect
with the effect name.
Particles¶
Particles are defined with the @particles
decorator:
from sonolus.script.particle import particles, StandardParticle, Particle, particle
@particles
class Particles:
tap: StandardParticle.NOTE_CIRCULAR_TAP_RED
other: Particle = particle("other")
Standard particles are defined by annotating the field with the corresponding value from StandardParticle
.
Custom particles are defined by annotating the field with Particle
and calling particle
with the particle name.
Buckets¶
Buckets are defined with the @buckets
decorator:
from sonolus.script.bucket import buckets, bucket_sprite, bucket, Bucket
from sonolus.script.text import StandardText
from my_engine.common.skin import Skin
@buckets
class Buckets:
note: Bucket = bucket(
sprites=[
bucket_sprite(
sprite=Skin.note,
x=0,
y=0,
w=2,
h=2,
)
],
unit=StandardText.MILLISECOND_UNIT,
)
Buckets are defined by annotating the field with Bucket
and calling bucket
with the bucket name.
Tutorial Instructions¶
Tutorial instructions are defined with the @instructions
decorator:
from sonolus.script.instruction import instructions, StandardInstruction, Instruction, instruction
@instructions
class Instructions:
tap: StandardInstruction.TAP
other: Instruction = instruction("other")
Standard instructions are defined by annotating the field with the corresponding value from StandardInstruction
.
Custom instructions are defined by annotating the field with Instruction
and calling instruction
with the instruction name.
Tutorial Instruction Icons¶
Tutorial instruction icons are defined with the @instruction_icons
decorator:
from sonolus.script.instruction import instruction_icons, StandardInstructionIcon, InstructionIcon, instruction_icon
@instruction_icons
class InstructionIcons:
hand: StandardInstructionIcon.HAND
other: InstructionIcon = instruction_icon("other")
Standard instruction icons are defined by annotating the field with the corresponding value from StandardInstructionIcon
.
Custom instruction icons are defined by annotating the field with InstructionIcon
and calling instruction_icon
with the icon name.
Options¶
Engine options are defined with the @options
decorator:
from sonolus.script.options import options, select_option, slider_option, toggle_option
@options
class Options:
slider_option: float = slider_option(
name="Slider Option",
standard=True,
advanced=False,
default=0.5,
min=0,
max=1,
step=0.1,
unit="unit",
scope="scope",
)
toggle_option: bool = toggle_option(
name="Toggle Option",
standard=True,
advanced=False,
default=True,
scope="scope",
)
select_option: int = select_option(
name="Select Option",
standard=True,
advanced=False,
default="value",
values=["value"],
scope="scope",
)
There are three types of options available:
slider_option
: A slider control for numeric valuestoggle_option
: A toggle switch for boolean valuesselect_option
: A dropdown menu for selecting from predefined values
UI¶
Ui configuration is defined with the UiConfig
class:
from sonolus.script.ui import (
EaseType,
UiAnimation,
UiAnimationTween,
UiConfig,
UiJudgmentErrorPlacement,
UiJudgmentErrorStyle,
UiMetric,
UiVisibility,
)
ui_config = UiConfig(
scope="my_engine",
primary_metric=UiMetric.ARCADE,
secondary_metric=UiMetric.LIFE,
menu_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
judgment_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
combo_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
primary_metric_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
secondary_metric_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
progress_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
tutorial_navigation_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
tutorial_instruction_visibility=UiVisibility(
scale=1.0,
alpha=1.0,
),
judgment_animation=UiAnimation(
scale=UiAnimationTween(
start=1.0,
end=1.0,
duration=0.0,
ease=EaseType.NONE,
),
alpha=UiAnimationTween(
start=1.0,
end=1.0,
duration=0.0,
ease=EaseType.NONE,
),
),
combo_animation=UiAnimation(
scale=UiAnimationTween(
start=1.2,
end=1.0,
duration=0.2,
ease=EaseType.IN_CUBIC,
),
alpha=UiAnimationTween(
start=1.0,
end=1.0,
duration=0.0,
ease=EaseType.NONE,
),
),
judgment_error_style=UiJudgmentErrorStyle.LATE,
judgment_error_placement=UiJudgmentErrorPlacement.TOP,
judgment_error_min=0.0,
)