diff --git a/setup.py b/setup.py index 9900e68d..ebd27239 100644 --- a/setup.py +++ b/setup.py @@ -51,6 +51,9 @@ "Source Code": 'https://github.com/kaaengine/kaa/', }, cmake_source_dir=KAA_SETUP_CMAKE_SOURCE, + package_data={ + 'kaa': ['*.pyi', 'py.typed'], + }, include_package_data=True, cmake_args=[ '-DKAA_INSTALL_KAACORE:BOOL=OFF', diff --git a/src/kaa/audio.pyi b/src/kaa/audio.pyi new file mode 100644 index 00000000..d220ac06 --- /dev/null +++ b/src/kaa/audio.pyi @@ -0,0 +1,116 @@ +from __future__ import annotations + +from typing import final + +import enum + + +class AudioStatus(enum.IntEnum): + paused: AudioStatus + playing: AudioStatus + stopped: AudioStatus + + +@final +class Sound: + def __init__(self, sound_filepath: str, volume: float = ...) -> None: + ... + + @property + def volume(self) -> float: + ... + + def play(self, volume: float = 1.) -> None: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... + + +@final +class SoundPlayback: + def __init__(self, sound: Sound, volume: float = ...) -> None: + ... + + @property + def is_paused(self) -> bool: + ... + + @property + def is_playing(self) -> bool: + ... + + @property + def sound(self) -> Sound: + ... + + @property + def status(self) -> AudioStatus: + ... + + @property + def volume(self) -> float: + ... + + @volume.setter + def volume(self, value: float) -> None: + ... + + def pause(self) -> None: + ... + + def play(self, loops: int = 1) -> None: + ... + + def resume(self) -> None: + ... + + def stop(self) -> None: + ... + + +@final +class Music: + def __init__(self, music_filepath: str, volume: float = ...) -> None: + ... + + @staticmethod + def get_current() -> Music: + ... + + @property + def is_paused(self) -> bool: + ... + + @property + def is_playing(self) -> bool: + ... + + @property + def status(self) -> AudioStatus: + ... + + @property + def volume(self) -> float: + ... + + def pause(self) -> None: + ... + + def play(self, volume: float = 1.) -> None: + ... + + def resume(self) -> None: + ... + + def stop(self) -> None: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... diff --git a/src/kaa/colors.pyi b/src/kaa/colors.pyi new file mode 100644 index 00000000..43238082 --- /dev/null +++ b/src/kaa/colors.pyi @@ -0,0 +1,35 @@ +from __future__ import annotations + +from typing import final + + +@final +class Color: + def __init__( + self, r: float = 0., g: float = 0., + b: float = 0., a: float = 1., + ) -> None: + ... + + @classmethod + def from_int( + self, r: int = 0, g: int = 0, + b: int = 0, a: int = 255, + ) -> Color: + ... + + @property + def r(self) -> float: + ... + + @property + def g(self) -> float: + ... + + @property + def b(self) -> float: + ... + + @property + def a(self) -> float: + ... diff --git a/src/kaa/easings.pyi b/src/kaa/easings.pyi new file mode 100644 index 00000000..9cd1463f --- /dev/null +++ b/src/kaa/easings.pyi @@ -0,0 +1,54 @@ +from __future__ import annotations + +import enum +from typing import overload + +from .geometry import Vector + + +class Easing(enum.IntEnum): + none: Easing + back_in: Easing + back_in_out: Easing + back_out: Easing + bounce_in: Easing + bounce_in_out: Easing + bounce_out: Easing + circular_in: Easing + circular_in_out: Easing + circular_out: Easing + cubic_in: Easing + cubic_in_out: Easing + cubic_out: Easing + elastic_in: Easing + elastic_in_out: Easing + elastic_out: Easing + exponential_in: Easing + exponential_in_out: Easing + exponential_out: Easing + quadratic_in: Easing + quadratic_in_out: Easing + quadratic_out: Easing + quartic_in: Easing + quartic_in_out: Easing + quartic_out: Easing + quintic_in: Easing + quintic_in_out: Easing + quintic_out: Easing + sine_in: Easing + sine_in_out: Easing + sine_out: Easing + + +def ease(easing: Easing, progress: float) -> float: + ... + + +@overload +def ease_between(easing: Easing, progress: float, a: float, b: float) -> float: + ... + + +@overload +def ease_between(easing: Easing, progress: float, a: Vector, b: Vector) -> Vector: + ... diff --git a/src/kaa/engine.pyi b/src/kaa/engine.pyi new file mode 100644 index 00000000..1bc19761 --- /dev/null +++ b/src/kaa/engine.pyi @@ -0,0 +1,346 @@ +from __future__ import annotations + +import enum +from typing import type_check_only, Optional, Iterable, List, TypeVar + +from .colors import Color +from .geometry import Vector, BoundingBox +from .input import InputManager +from .nodes import Node + + +class VirtualResolutionMode(enum.IntEnum): + adaptive_stretch: VirtualResolutionMode + aggresive_stretch: VirtualResolutionMode + no_stretch: VirtualResolutionMode + + +@type_check_only +class EngineInstance: + @property + def audio(self) -> AudioManager: + ... + + @property + def current_scene(self) -> Scene: + ... + + @property + def virtual_resolution(self) -> Vector: + ... + + @virtual_resolution.setter + def virtual_resolution(self, new_resolution: Vector) -> None: + ... + + @property + def virtual_resolution_mode(self) -> VirtualResolutionMode: + ... + + @virtual_resolution_mode.setter + def virtual_resolution_mode(self, new_mode: VirtualResolutionMode) -> None: + ... + + @property + def window(self) -> Window: + ... + + def change_scene(self, scene: Scene) -> None: + ... + + def get_displays(self) -> List[Display]: + ... + + def get_fps(self) -> float: + ... + + def quit(self) -> None: + ... + + def run(self, scene: Scene) -> None: + ... + + def stop(self) -> None: + ... + + def __enter__(self) -> EngineInstance: + ... + + def __exit__(self, exc_type, exc_value, traceback) -> None: + ... + + +def Engine( + virtual_resolution: Vector, + virtual_resolution_mode: Optional[VirtualResolutionMode] + = VirtualResolutionMode.adaptive_stretch, +) -> EngineInstance: + ... + + +def get_engine() -> Optional[EngineInstance]: + ... + + +@type_check_only +class Display: + @property + def index(self) -> int: + ... + + @property + def name(self) -> str: + ... + + @property + def position(self) -> Vector: + ... + + @property + def size(self) -> Vector: + ... + + +@type_check_only +class Window: + @property + def fullscreen(self) -> bool: + ... + + @fullscreen.setter + def fullscreen(self, fullscreen_state: bool) -> None: + ... + + @property + def position(self) -> Vector: + ... + + @position.setter + def position(self, new_position: Vector) -> None: + ... + + @property + def size(self) -> Vector: + ... + + @size.setter + def size(self, new_size: Vector) -> None: + ... + + @property + def title(self) -> str: + ... + + @title.setter + def title(self, new_title: str) -> None: + ... + + def center(self) -> None: + ... + + def hide(self) -> None: + ... + + def maximize(self) -> None: + ... + + def minimize(self) -> None: + ... + + def restore(self) -> None: + ... + + def show(self) -> None: + ... + + +class Scene: + @property + def camera(self) -> Camera: + ... + + @property + def clear_color(self) -> Color: + ... + + @clear_color.setter + def clear_color(self, color: Color) -> None: + ... + + @property + def engine(self) -> Optional[EngineInstance]: + ... + + @property + def input(self) -> InputManager: + ... + + @property + def root(self) -> Node: + ... + + @property + def spatial_index(self) -> SpatialIndexManager: + ... + + @property + def time_scale(self) -> float: + ... + + @time_scale.setter + def time_scale(self, scale: float) -> None: + ... + + @property + def views(self) -> ViewsManager: + ... + + def __init__(self) -> None: + ... + + def on_enter(self) -> None: + ... + + def on_exit(self) -> None: + ... + + def update(self, dt: float) -> None: + ... + + +AnyScene = TypeVar('AnyScene', bound=Scene) + + +@type_check_only +class Camera: + @property + def position(self) -> Vector: + ... + + @position.setter + def position(self, vector: Vector) -> None: + ... + + @property + def rotation(self) -> float: + ... + + @rotation.setter + def rotation(self, value: float) -> None: + ... + + @property + def rotation_degrees(self) -> float: + ... + + @rotation_degrees.setter + def rotation_degrees(self, value: float) -> None: + ... + + @property + def scale(self) -> Vector: + ... + + @scale.setter + def scale(self, vector: Vector) -> None: + ... + + @property + def visible_area_bounding_box(self) -> BoundingBox: + ... + + def unproject_position(self, position: Vector) -> Vector: + ... + + +@type_check_only +class View: + @property + def camera(self) -> Camera: + ... + + @property + def clear_color(self) -> Color: + ... + + @clear_color.setter + def clear_color(self, color: Color) -> None: + ... + + @property + def dimensions(self) -> Vector: + ... + + @dimensions.setter + def dimensions(self, dimensions: Vector) -> None: + ... + + @property + def origin(self) -> Vector: + ... + + @origin.setter + def origin(self, origin: Vector) -> None: + ... + + @property + def z_index(self) -> int: + ... + + +@type_check_only +class ViewsManager: + def __getitem__(self, index: int) -> View: + ... + + def __iter__(self) -> Iterable[View]: + ... + + def __len__(self) -> int: + ... + + +@type_check_only +class SpatialIndexManager: + def query_bounding_box( + self, bbox: BoundingBox, include_shapeless: bool = True + ) -> List[Node]: + ... + + def query_point(self, point: Vector) -> List[Node]: + ... + + +@type_check_only +class AudioManager: + @property + def master_music_volume(self) -> float: + ... + + @master_music_volume.setter + def master_music_volume(self, vol: float) -> None: + ... + + @property + def master_sound_volume(self) -> float: + ... + + @master_sound_volume.setter + def master_sound_volume(self, vol: float) -> None: + ... + + @property + def master_volume(self) -> float: + ... + + @master_volume.setter + def master_volume(self, vol: float) -> None: + ... + + @property + def mixing_channels(self) -> int: + ... + + @mixing_channels.setter + def mixing_channels(self, ch: int) -> None: + ... diff --git a/src/kaa/fonts.pyi b/src/kaa/fonts.pyi new file mode 100644 index 00000000..c74ff3d0 --- /dev/null +++ b/src/kaa/fonts.pyi @@ -0,0 +1,126 @@ +from __future__ import annotations + +from typing import final, Optional, Set + +from .colors import Color +from .geometry import AnyShape, Alignment, Transformation, Vector +from .nodes import AnyNode, NodeBase +from .transitions import AnyTransitionArgument +from .sprites import Sprite + + +@final +class Font: + def __init__(self, font_path: str) -> None: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... + + +class TextNode(NodeBase): + def __init__( + self, *, + position: Vector = Vector(0, 0), + rotation: float = 0, + rotation_degrees: float = 0, + scale: Vector = Vector(1, 1), + z_index: Optional[int] = None, + color: Color = Color(0, 0, 0, 0), + sprite: Optional[Sprite] = None, + shape: Optional[AnyShape] = None, + origin_alignment: Alignment = Alignment.center, + lifetime: float = 0., + transition: AnyTransitionArgument = None, + transformation: Transformation = Transformation(), + visible: bool = True, + views: Optional[Set[int]] = None, + indexable: bool = True, + font: Font = ..., + text: str = "", + font_size: float = 28., + line_width: float = float('inf'), + interline_spacing: float = 1., + first_line_indent: float = 0., + ) -> None: + ... + + def setup( + self, *, + position: Vector = ..., + rotation: float = ..., + rotation_degrees: float = ..., + scale: Vector = ..., + z_index: Optional[int] = ..., + color: Color = ..., + sprite: Optional[Sprite] = ..., + shape: Optional[AnyShape] = ..., + origin_alignment: Alignment = ..., + lifetime: float = ..., + transition: AnyTransitionArgument = ..., + transformation: Transformation = ..., + visible: bool = ..., + views: Optional[Set[int]] = ..., + indexable: bool = ..., + font: Font = ..., + text: str = ..., + font_size: float = ..., + line_width: float = ..., + interline_spacing: float = ..., + first_line_indent: float = ..., + ) -> None: + ... + + def add_child(self, node: AnyNode) -> AnyNode: + ... + + @property + def first_line_indent(self) -> float: + ... + + @first_line_indent.setter + def first_line_indent(self, value: float) -> None: + ... + + @property + def font(self) -> Font: + ... + + @font.setter + def font(self, value: Font) -> None: + ... + + @property + def font_size(self) -> float: + ... + + @font_size.setter + def font_size(self, value: float) -> None: + ... + + @property + def interline_spacing(self) -> float: + ... + + @interline_spacing.setter + def interline_spacing(self, value: float) -> None: + ... + + @property + def line_width(self) -> float: + ... + + @line_width.setter + def line_width(self, value: float) -> None: + ... + + @property + def text(self) -> str: + ... + + @text.setter + def text(self, value: str) -> None: + ... diff --git a/src/kaa/geometry.pyi b/src/kaa/geometry.pyi new file mode 100644 index 00000000..9cb0b1e1 --- /dev/null +++ b/src/kaa/geometry.pyi @@ -0,0 +1,324 @@ +from __future__ import annotations + +import enum +from typing import ( + final, overload, type_check_only, List, Optional, Sequence, Union, +) + + +@final +class Vector: + def __init__(self, x: float, y: float) -> None: + ... + + @staticmethod + def xy(xy: float) -> Vector: + ... + + @classmethod + def from_angle(cls, angle_rad: float) -> Vector: + ... + + @classmethod + def from_angle_degrees(cls, angle_deg: float) -> Vector: + ... + + @property + def x(self) -> float: + ... + + @property + def y(self) -> float: + ... + + def add(self, other: Vector) -> Vector: + ... + + def angle_between(self, other: Vector) -> float: + ... + + def angle_between_degrees(self, other: Vector) -> float: + ... + + def distance(self, other: Vector) -> float: + ... + + def dot(self, other: Vector) -> float: + ... + + def is_zero(self) -> bool: + ... + + def length(self) -> float: + ... + + def mul(self, value: float) -> Vector: + ... + + def normalize(self) -> Vector: + ... + + def rotate_angle(self, angle_rad: float) -> Vector: + ... + + def rotate_angle_degrees(self, angle_deg: float) -> Vector: + ... + + def sub(self, other: Vector) -> Vector: + ... + + def to_angle(self) -> float: + ... + + def to_angle_degrees(self) -> float: + ... + + def transform(self, transformation: Transformation) -> Vector: + ... + + def __add__(self, other: Vector) -> Vector: + ... + + def __bool__(self) -> bool: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... + + def __mul__(self, other: float) -> Vector: + ... + + def __rmul__(self, other: float) -> Vector: + ... + + def __neg__(self) -> Vector: + ... + + def __or__(self, other: Transformation) -> Vector: + ... + + def __sub__(self, other: Vector) -> Vector: + ... + + def __truediv__(self, other: float) -> Vector: + ... + + +@type_check_only +class ShapeBase: + @property + def bounding_box(self) -> BoundingBox: + ... + + def transform(self, transformation: Transformation) -> ShapeBase: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... + + def __or__(self, other: Transformation) -> ShapeBase: + ... + + +@final +class Segment(ShapeBase): + def __init__(self, a: Vector, b: Vector) -> None: + ... + + @property + def point_a(self) -> Vector: + ... + + @property + def point_b(self) -> Vector: + ... + + +@final +class Circle(ShapeBase): + def __init__(self, radius: float, center: Vector = Vector(0, 0)) -> None: + ... + + @property + def radius(self) -> float: + ... + + @property + def center(self) -> Vector: + ... + + + +@final +class Polygon(ShapeBase): + def __init__(self, points: Sequence[Vector]) -> None: + ... + + @staticmethod + def from_box(size: Vector) -> Polygon: + ... + + @property + def points(self) -> List[Vector]: + ... + + +AnyShape = Union[Segment, Circle, Polygon] + + +class PolygonType(enum.IntEnum): + convex_ccw: PolygonType + convex_cw: PolygonType + not_convex: PolygonType + + +def classify_polygon(points: Sequence[Vector]) -> PolygonType: + ... + + +class Alignment(enum.IntEnum): + bottom: Alignment + bottom_left: Alignment + bottom_right: Alignment + center: Alignment + left: Alignment + none: Alignment + right: Alignment + top: Alignment + top_left: Alignment + top_right: Alignment + + +@final +class Transformation: + @overload + def __init__( + self, *, translate: Optional[Vector] = None, + rotate: Optional[float] = None, + scale: Optional[Vector] = None + ) -> None: + ... + + @overload + def __init__( + self, *, translate: Optional[Vector] = None, + rotate_degrees: Optional[float] = None, + scale: Optional[Vector] = None + ) -> None: + ... + def decompose(self) -> DecomposedTransformation: + ... + + def inverse(self) -> Transformation: + ... + + def __eq__(self, other) -> bool: + ... + + @overload + def __matmul__(self, other_transformation: Transformation) -> Transformation: + ... + + @overload + def __matmul__(self, vector: Vector) -> Vector: + ... + + @overload + def __matmul__(self, shape: ShapeBase) -> ShapeBase: + ... + + def __or__(self, other: Transformation) -> Transformation: + ... + + +@type_check_only +class DecomposedTransformation: + @property + def rotation(self) -> float: + ... + + @property + def rotation_degrees(self) -> float: + ... + + @property + def scale(self) -> Vector: + ... + + @property + def translation(self) -> Vector: + ... + + +@final +class BoundingBox: + def __init__(self, min_x: float, min_y: float, max_x: float, max_y: float) -> None: + ... + + @staticmethod + def single_point(point: Vector) -> BoundingBox: + ... + + @staticmethod + def from_points(points: Sequence[Vector]) -> BoundingBox: + ... + + @property + def max_x(self) -> float: + ... + + @property + def max_y(self) -> float: + ... + + @property + def min_x(self) -> float: + ... + + @property + def min_y(self) -> float: + ... + + @property + def center(self) -> Vector: + ... + + @property + def dimensions(self) -> Vector: + ... + + @property + def is_nan(self) -> bool: + ... + + @overload + def contains(self, point: Vector) -> bool: + ... + + @overload + def contains(self, bounding_box: BoundingBox) -> bool: + ... + + def grow(self, vector: Vector) -> BoundingBox: + ... + + def intersection(self, bounding_box: BoundingBox) -> BoundingBox: + ... + + def intersects(self, bounding_box: BoundingBox) -> BoundingBox: + ... + + def merge(self, bounding_box: BoundingBox) -> BoundingBox: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... diff --git a/src/kaa/input.pyi b/src/kaa/input.pyi new file mode 100644 index 00000000..caa2e37a --- /dev/null +++ b/src/kaa/input.pyi @@ -0,0 +1,673 @@ +from __future__ import annotations + +import enum +from typing import Callable, Iterable, Optional, overload, type_check_only + +from .geometry import Vector + + +class ControllerAxis(enum.IntEnum): + left_x: ControllerAxis + left_y: ControllerAxis + right_x: ControllerAxis + right_y: ControllerAxis + trigger_left: ControllerAxis + trigger_right: ControllerAxis + + +class CompoundControllerAxis(enum.IntEnum): + left_stick: CompoundControllerAxis + right_stick: CompoundControllerAxis + + +class ControllerButton(enum.IntEnum): + a: ControllerButton + b: ControllerButton + back: ControllerButton + dpad_down: ControllerButton + dpad_left: ControllerButton + dpad_right: ControllerButton + dpad_up: ControllerButton + guide: ControllerButton + left_shoulder: ControllerButton + left_stick: ControllerButton + right_shoulder: ControllerButton + right_stick: ControllerButton + start: ControllerButton + x: ControllerButton + y: ControllerButton + + +class Keycode(enum.IntEnum): + A: Keycode + B: Keycode + C: Keycode + D: Keycode + E: Keycode + F: Keycode + F1: Keycode + F10: Keycode + F11: Keycode + F12: Keycode + F13: Keycode + F14: Keycode + F15: Keycode + F16: Keycode + F17: Keycode + F18: Keycode + F19: Keycode + F2: Keycode + F20: Keycode + F21: Keycode + F22: Keycode + F23: Keycode + F24: Keycode + F3: Keycode + F4: Keycode + F5: Keycode + F6: Keycode + F7: Keycode + F8: Keycode + F9: Keycode + G: Keycode + H: Keycode + I: Keycode + J: Keycode + K: Keycode + L: Keycode + M: Keycode + N: Keycode + O: Keycode + P: Keycode + Q: Keycode + R: Keycode + S: Keycode + T: Keycode + U: Keycode + V: Keycode + W: Keycode + X: Keycode + Y: Keycode + Z: Keycode + a: Keycode + ac_back: Keycode + ac_bookmarks: Keycode + ac_forward: Keycode + ac_home: Keycode + ac_refresh: Keycode + ac_search: Keycode + ac_stop: Keycode + again: Keycode + alterase: Keycode + ampersand: Keycode + application: Keycode + asterisk: Keycode + at: Keycode + audiomute: Keycode + audionext: Keycode + audioplay: Keycode + audioprev: Keycode + audiostop: Keycode + b: Keycode + backquote: Keycode + backslash: Keycode + backspace: Keycode + brightnessdown: Keycode + brightnessup: Keycode + c: Keycode + calculator: Keycode + cancel: Keycode + capslock: Keycode + caret: Keycode + clear: Keycode + clearagain: Keycode + colon: Keycode + comma: Keycode + computer: Keycode + copy: Keycode + crsel: Keycode + currencysubunit: Keycode + currencyunit: Keycode + cut: Keycode + d: Keycode + decimalseparator: Keycode + delete: Keycode + displayswitch: Keycode + dollar: Keycode + down: Keycode + e: Keycode + eject: Keycode + end: Keycode + equals: Keycode + escape: Keycode + exclaim: Keycode + execute: Keycode + exsel: Keycode + f: Keycode + find: Keycode + g: Keycode + greater: Keycode + h: Keycode + hash: Keycode + help: Keycode + home: Keycode + i: Keycode + insert: Keycode + j: Keycode + k: Keycode + kbdillumdown: Keycode + kbdillumtoggle: Keycode + kbdillumup: Keycode + kp_0: Keycode + kp_00: Keycode + kp_000: Keycode + kp_1: Keycode + kp_2: Keycode + kp_3: Keycode + kp_4: Keycode + kp_5: Keycode + kp_6: Keycode + kp_7: Keycode + kp_8: Keycode + kp_9: Keycode + kp_a: Keycode + kp_ampersand: Keycode + kp_at: Keycode + kp_b: Keycode + kp_backspace: Keycode + kp_binary: Keycode + kp_c: Keycode + kp_clear: Keycode + kp_clearentry: Keycode + kp_colon: Keycode + kp_comma: Keycode + kp_d: Keycode + kp_dblampersand: Keycode + kp_dblverticalbar: Keycode + kp_decimal: Keycode + kp_divide: Keycode + kp_e: Keycode + kp_enter: Keycode + kp_equals: Keycode + kp_equalsas400: Keycode + kp_exclam: Keycode + kp_f: Keycode + kp_greater: Keycode + kp_hash: Keycode + kp_hexadecimal: Keycode + kp_leftbrace: Keycode + kp_leftparen: Keycode + kp_less: Keycode + kp_memadd: Keycode + kp_memclear: Keycode + kp_memdivide: Keycode + kp_memmultiply: Keycode + kp_memrecall: Keycode + kp_memstore: Keycode + kp_memsubtract: Keycode + kp_minus: Keycode + kp_multiply: Keycode + kp_octal: Keycode + kp_percent: Keycode + kp_period: Keycode + kp_plus: Keycode + kp_plusminus: Keycode + kp_power: Keycode + kp_rightbrace: Keycode + kp_rightparen: Keycode + kp_space: Keycode + kp_tab: Keycode + kp_verticalbar: Keycode + kp_xor: Keycode + l: Keycode + lalt: Keycode + lctrl: Keycode + left: Keycode + leftbracket: Keycode + leftparen: Keycode + less: Keycode + lgui: Keycode + lshift: Keycode + m: Keycode + mail: Keycode + mediaselect: Keycode + menu: Keycode + minus: Keycode + mode: Keycode + mute: Keycode + n: Keycode + num_0: Keycode + num_1: Keycode + num_2: Keycode + num_3: Keycode + num_4: Keycode + num_5: Keycode + num_6: Keycode + num_7: Keycode + num_8: Keycode + num_9: Keycode + numlockclear: Keycode + o: Keycode + oper: Keycode + out: Keycode + p: Keycode + pagedown: Keycode + pageup: Keycode + paste: Keycode + pause: Keycode + percent: Keycode + period: Keycode + plus: Keycode + power: Keycode + printscreen: Keycode + prior: Keycode + q: Keycode + question: Keycode + quote: Keycode + quotedbl: Keycode + r: Keycode + ralt: Keycode + rctrl: Keycode + return2: Keycode + return_: Keycode + rgui: Keycode + right: Keycode + rightbracket: Keycode + rightparen: Keycode + rshift: Keycode + s: Keycode + scrolllock: Keycode + select: Keycode + semicolon: Keycode + separator: Keycode + slash: Keycode + sleep: Keycode + space: Keycode + stop: Keycode + sysreq: Keycode + t: Keycode + tab: Keycode + thousandsseparator: Keycode + u: Keycode + underscore: Keycode + undo: Keycode + unknown: Keycode + up: Keycode + v: Keycode + volumedown: Keycode + volumeup: Keycode + w: Keycode + www: Keycode + x: Keycode + y: Keycode + z: Keycode + + +class MouseButton(enum.IntEnum): + left: MouseButton + middle: MouseButton + right: MouseButton + x1: MouseButton + x2: MouseButton + + +class EventType(enum.IntEnum): + channel_finished: EventType + clipboard_updated: EventType + controller_added: EventType + controller_axis_motion: EventType + controller_button_down: EventType + controller_button_up: EventType + controller_remapped: EventType + controller_removed: EventType + key_down: EventType + key_up: EventType + mouse_button_down: EventType + mouse_button_up: EventType + mouse_motion: EventType + mouse_wheel: EventType + music_finished: EventType + quit: EventType + text_input: EventType + window_close: EventType + window_enter: EventType + window_exposed: EventType + window_focus_gained: EventType + window_focus_lost: EventType + window_hidden: EventType + window_leave: EventType + window_maximized: EventType + window_minimized: EventType + window_moved: EventType + window_resized: EventType + window_restored: EventType + window_shown: EventType + + +@type_check_only +class _BaseEvent: + @property + def timestamp(self) -> int: + ... + + +class ControllerAxisEvent(_BaseEvent): + @property + def axis(self) -> ControllerAxis: + ... + + @property + def id(self) -> int: + ... + + @property + def motion(self) -> float: + ... + + +class ControllerButtonEvent(_BaseEvent): + @property + def id(self) -> int: + ... + + @property + def button(self) -> ControllerButton: + ... + + @property + def is_button_down(self) -> bool: + ... + + @property + def is_button_up(self) -> bool: + ... + + +class ControllerDeviceEvent(_BaseEvent): + @property + def id(self) -> int: + ... + + @property + def is_added(self) -> bool: + ... + + @property + def is_removed(self) -> bool: + ... + + +class KeyboardKeyEvent(_BaseEvent): + @property + def key(self) -> Keycode: + ... + + @property + def key_down(self) -> Optional[Keycode]: + ... + + @property + def repeat(self) -> bool: + ... + + @property + def is_key_down(self) -> bool: + ... + + @property + def is_key_up(self) -> bool: + ... + + +class KeyboardTextEvent(_BaseEvent): + @property + def text(self) -> str: + ... + + +class MouseButtonEvent(_BaseEvent): + @property + def position(self) -> Vector: + ... + + @property + def button(self) -> MouseButton: ... + + @property + def is_button_down(self) -> bool: ... + + @property + def is_button_up(self) -> bool: + ... + + +class MouseMotionEvent(_BaseEvent): + @property + def motion(self) -> Vector: + ... + + @property + def position(self) -> Vector: + ... + + +class MouseWheelEvent(_BaseEvent): + @property + def scroll(self) -> Vector: + ... + + +class MusicFinishedEvent(_BaseEvent): + ... + + +class SystemEvent(_BaseEvent): + @property + def clipboard_updated(self) -> bool: + ... + + @property + def quit(self) -> bool: + ... + + +class WindowEvent(_BaseEvent): + @property + def is_close(self) -> bool: + ... + + @property + def is_enter(self) -> bool: + ... + + @property + def is_exposed(self) -> bool: + ... + + @property + def is_focus_gained(self) -> bool: + ... + + @property + def is_focus_lost(self) -> bool: + ... + + @property + def is_leave(self) -> bool: + ... + + @property + def is_maximized(self) -> bool: + ... + + @property + def is_minimized(self) -> bool: + ... + + @property + def is_moved(self) -> bool: + ... + + @property + def is_resized(self) -> bool: + ... + + @property + def is_restored(self) -> bool: + ... + + @property + def is_shown(self) -> bool: + ... + + +class Event(_BaseEvent): + @property + def controller_axis(self) -> Optional[ControllerAxisEvent]: + ... + + @property + def controller_button(self) -> Optional[ControllerButtonEvent]: + ... + + @property + def controller_device(self) -> Optional[ControllerDeviceEvent]: + ... + + @property + def keyboard_key(self) -> Optional[KeyboardKeyEvent]: + ... + + @property + def keyboard_text(self) -> Optional[KeyboardTextEvent]: + ... + + @property + def mouse_button(self) -> Optional[MouseButtonEvent]: + ... + + @property + def mouse_motion(self) -> Optional[MouseMotionEvent]: + ... + + @property + def mouse_wheel(self) -> Optional[MouseWheelEvent]: + ... + + @property + def music_finished(self) -> Optional[MusicFinishedEvent]: + ... + + @property + def system(self) -> Optional[SystemEvent]: + ... + + @property + def window(self) -> Optional[WindowEvent]: + ... + + +@type_check_only +class SystemManager: + def get_clipboard_text(self) -> str: + ... + + def set_clipboard_text(self, text: str) -> None: + ... + + +@type_check_only +class KeyboardManager: + def is_pressed(self, kc: Keycode) -> bool: + ... + + def is_released(self, kc: Keycode) -> bool: + ... + + +@type_check_only +class MouseManager: + @property + def cursor_visible(self) -> bool: + ... + + @cursor_visible.setter + def cursor_visible(self, visible: bool) -> None: + ... + + @property + def relative_mode(self) -> bool: + ... + + @relative_mode.setter + def relative_mode(self, rel: bool) -> None: + ... + + def get_position(self) -> Vector: ... + def is_pressed(self, mc: MouseButton) -> bool: ... + def is_released(self, mc: MouseButton) -> bool: ... + + +@type_check_only +class ControllerManager: + def get_axis_motion(self, axis: ControllerAxis, controller_id: int) -> float: + ... + + def get_name(self, controller_id: int) -> str: + ... + + def get_sticks(self, compound_axis: CompoundControllerAxis, controller_id: int) -> Vector: + ... + + def get_triggers(self, controller_id: int) -> Vector: + ... + + def is_axis_pressed(self, axis: ControllerAxis, controller_id: int) -> bool: + ... + + def is_axis_released(self, axis: ControllerAxis, controller_id: int) -> bool: + ... + + def is_connected(self, controller_id: int) -> bool: + ... + + def is_pressed(self, cb: ControllerButton, controller_id: int) -> bool: + ... + + def is_released(self, cb: ControllerButton, controller_id: int) -> bool: + ... + + +@type_check_only +class InputManager: + @property + def controller(self) -> ControllerManager: + ... + + @property + def keyboard(self) -> KeyboardManager: + ... + + @property + def mouse(self) -> MouseManager: + ... + + @property + def system(self) -> SystemManager: + ... + + def events(self) -> Iterable[Event]: + ... + + @overload + def register_callback( + self, event_type: EventType, callback: Optional[Callable[[Event], bool]], + ) -> None: + ... + + @overload + def register_callback( + self, event_type: Iterable[EventType], + callback: Optional[Callable[[Event], bool]], + ) -> None: + ... diff --git a/src/kaa/log.pyi b/src/kaa/log.pyi new file mode 100644 index 00000000..c27a3112 --- /dev/null +++ b/src/kaa/log.pyi @@ -0,0 +1,26 @@ +from __future__ import annotations + +import enum +import logging + + +class CoreLogLevel(enum.IntEnum): + critical: CoreLogLevel + debug: CoreLogLevel + error: CoreLogLevel + info: CoreLogLevel + off: CoreLogLevel + trace: CoreLogLevel + warn: CoreLogLevel + + +class CoreHandler(logging.Handler): + ... + + +def get_core_logging_level(core_category: str) -> CoreLogLevel: + ... + + +def set_core_logging_level(core_category: str, level: CoreLogLevel) -> None: + ... diff --git a/src/kaa/nodes.pyi b/src/kaa/nodes.pyi new file mode 100644 index 00000000..03eda129 --- /dev/null +++ b/src/kaa/nodes.pyi @@ -0,0 +1,248 @@ +from __future__ import annotations + +from typing import Iterable, Optional, Set, TypeVar + +from .colors import Color +from .engine import AnyScene +from .fonts import TextNode +from .geometry import AnyShape, Alignment, BoundingBox, Transformation, Vector +from .physics import SpaceNode, BodyNode, HitboxNode +from .transitions import AnyTransition, AnyTransitionArgument, NodeTransitionsManager +from .sprites import Sprite + + +class NodeBase: + @property + def absolute_position(self) -> Vector: + ... + + @property + def absolute_rotation(self) -> float: + ... + + @property + def absolute_rotation_degrees(self) -> float: + ... + + @property + def absolute_scale(self) -> Vector: + ... + + @property + def absolute_transformation(self) -> Transformation: + ... + + @property + def bounding_box(self) -> BoundingBox: + ... + + @property + def children(self) -> Iterable[AnyNode]: + ... + + @property + def color(self) -> Color: + ... + + @color.setter + def color(self, value: Color) -> None: + ... + + @property + def effective_views(self) -> Set[int]: + ... + + @property + def effective_z_index(self) -> int: + ... + + @property + def indexable(self) -> bool: + ... + + @indexable.setter + def indexable(self, value: bool) -> None: + ... + + @property + def lifetime(self) -> float: + ... + + @lifetime.setter + def lifetime(self, value: float) -> None: + ... + + @property + def origin_alignment(self) -> Alignment: + ... + + @origin_alignment.setter + def origin_alignment(self, value: Alignment) -> None: + ... + + @property + def parent(self) -> Optional[AnyNode]: + ... + + @property + def position(self) -> Vector: + ... + + @position.setter + def position(self, value: Vector) -> None: + ... + + @property + def root_distance(self) -> int: + ... + + @property + def rotation(self) -> float: + ... + + @rotation.setter + def rotation(self, value: float) -> None: + ... + + @property + def rotation_degrees(self) -> float: + ... + + @rotation_degrees.setter + def rotation_degrees(self, value: float) -> None: + ... + + @property + def scale(self) -> Vector: + ... + + @scale.setter + def scale(self, value: Vector) -> None: + ... + + @property + def scene(self) -> Optional[AnyScene]: + ... + + @property + def shape(self) -> Optional[AnyShape]: + ... + + @shape.setter + def shape(self, value: Optional[AnyShape]) -> None: + ... + + @property + def sprite(self) -> Optional[Sprite]: + ... + + @sprite.setter + def sprite(self, value: Optional[Sprite]) -> None: + ... + + @property + def transformation(self) -> Transformation: + ... + + @transformation.setter + def transformation(self, value: Transformation) -> None: + ... + + @property + def transition(self) -> Optional[AnyTransition]: + ... + + @transition.setter + def transition(self, value: AnyTransitionArgument) -> None: + ... + + @property + def transitions_manager(self) -> NodeTransitionsManager: + ... + + @property + def type(self) -> int: + ... + + @property + def views(self) -> Optional[Set[int]]: + ... + + @views.setter + def views(self, value: Optional[Set[int]]) -> None: + ... + + @property + def visible(self) -> bool: + ... + + @visible.setter + def visible(self, value: bool) -> None: + ... + + @property + def z_index(self) -> Optional[int]: + ... + + @z_index.setter + def z_index(self, value: Optional[int]) -> None: + ... + + def delete(self) -> None: + ... + + def get_relative_position(self, ancestor: NodeBase) -> Vector: + ... + + def get_relative_transformation(self, ancestor: NodeBase) -> Transformation: + ... + + def __bool__(self) -> bool: + ... + + +class Node(NodeBase): + def __init__( + self, *, + position: Vector = Vector(0, 0), + rotation: float = 0, + rotation_degrees: float = 0, + scale: Vector = Vector(1, 1), + z_index: Optional[int] = None, + color: Color = Color(0, 0, 0, 0), + sprite: Optional[Sprite] = None, + shape: Optional[AnyShape] = None, + origin_alignment: Alignment = Alignment.center, + lifetime: float = 0., + transition: AnyTransitionArgument = None, + transformation: Transformation = Transformation(), + visible: bool = True, + views: Optional[Set[int]] = None, + indexable: bool = True, + ) -> None: + ... + def setup( + self, *, + position: Vector = ..., + rotation: float = ..., + rotation_degrees: float = ..., + scale: Vector = ..., + z_index: Optional[int] = ..., + color: Color = ..., + sprite: Optional[Sprite] = ..., + shape: Optional[AnyShape] = ..., + origin_alignment: Alignment = ..., + lifetime: float = ..., + transition: AnyTransitionArgument = ..., + transformation: Transformation = ..., + visible: bool = ..., + views: Optional[Set[int]] = ..., + indexable: bool = ..., + ) -> None: + ... + + def add_child(self, node: AnyNode) -> AnyNode: + ... + + +AnyNode = TypeVar('AnyNode', bound=NodeBase) diff --git a/src/kaa/physics.pyi b/src/kaa/physics.pyi new file mode 100644 index 00000000..39da09e5 --- /dev/null +++ b/src/kaa/physics.pyi @@ -0,0 +1,564 @@ +from __future__ import annotations + +import enum +from typing import final, type_check_only, Callable, List, Optional, Set + +from .colors import Color +from .geometry import AnyShape, Alignment, Transformation, Vector +from .nodes import NodeBase, AnyNode +from .sprites import Sprite +from .transitions import AnyTransitionArgument + + +COLLISION_BITMASK_ALL: int = ... +COLLISION_BITMASK_NONE: int = ... +COLLISION_GROUP_NONE: int = ... + + +class CollisionPhase(enum.IntFlag): + begin: CollisionPhase + post_solve: CollisionPhase + pre_solve: CollisionPhase + separate: CollisionPhase + + +class BodyNodeType(enum.IntEnum): + dynamic: BodyNodeType + kinematic: BodyNodeType + static: BodyNodeType + + +@final +class CollisionPair: + @property + def body(self) -> Optional[BodyNode]: + ... + + @property + def hitbox(self) -> Optional[HitboxNode]: + ... + + +@final +class CollisionContactPoint: + @property + def distance(self) -> float: + ... + + @property + def point_a(self) -> Vector: + ... + + @property + def point_b(self) -> Vector: + ... + + +@type_check_only +class SpatialQueryResultBase: + @property + def body(self) -> Optional[BodyNode]: + ... + + @property + def hitbox(self) -> Optional[HitboxNode]: + ... + + +@final +class ShapeQueryResult(SpatialQueryResultBase): + @property + def contact_points(self) -> List[CollisionContactPoint]: + ... + + +@final +class RayQueryResult(SpatialQueryResultBase): + @property + def alpha(self) -> float: + ... + + @property + def normal(self) -> Vector: + ... + + @property + def point(self) -> Vector: + ... + + +@final +class PointQueryResult(SpatialQueryResultBase): + @property + def distance(self) -> float: + ... + + @property + def point(self) -> Vector: + ... + + +@final +class Arbiter: + @property + def phase(self) -> CollisionPhase: + ... + + @property + def space(self) -> SpaceNode: + ... + + +class HitboxNode(NodeBase): + def __init__( + self, *, + position: Vector = Vector(0, 0), + rotation: float = 0, + rotation_degrees: float = 0, + scale: Vector = Vector(1, 1), + z_index: Optional[int] = None, + color: Color = Color(0, 0, 0, 0), + sprite: Optional[Sprite] = None, + shape: Optional[AnyShape] = None, + origin_alignment: Alignment = Alignment.center, + lifetime: float = 0., + transition: AnyTransitionArgument = None, + transformation: Transformation = Transformation(), + visible: bool = True, + views: Optional[Set[int]] = None, + indexable: bool = True, + trigger_id: int = 0, + group: int = COLLISION_GROUP_NONE, + mask: int = COLLISION_BITMASK_ALL, + collision_mask: int = COLLISION_BITMASK_ALL, + elasticity: float = 0.95, + friction: float = 0, + surface_velocity: Vector = Vector(0., 0.), + sensor: bool = False, + ) -> None: + ... + + def setup( + self, *, + position: Vector = ..., + rotation: float = ..., + rotation_degrees: float = ..., + scale: Vector = ..., + z_index: Optional[int] = ..., + color: Color = ..., + sprite: Optional[Sprite] = ..., + shape: Optional[AnyShape] = ..., + origin_alignment: Alignment = ..., + lifetime: float = ..., + transition: AnyTransitionArgument = ..., + transformation: Transformation = ..., + visible: bool = ..., + views: Optional[Set[int]] = ..., + indexable: bool = ..., + trigger_id: int = ..., + group: int = ..., + mask: int = ..., + collision_mask: int = ..., + elasticity: float = ..., + friction: float = ..., + surface_velocity: Vector = ..., + sensor: bool = ..., + ) -> None: + ... + + def add_child(self, node: AnyNode) -> AnyNode: + ... + + @property + def collision_mask(self) -> int: + ... + + @collision_mask.setter + def collision_mask(self, value: int) -> None: + ... + + @property + def elasticity(self) -> float: + ... + + @elasticity.setter + def elasticity(self, value: float) -> None: + ... + + @property + def friction(self) -> float: + ... + + @friction.setter + def friction(self, value: float) -> None: + ... + + @property + def group(self) -> int: + ... + + @group.setter + def group(self, value: int) -> None: + ... + + @property + def mask(self) -> int: + ... + + @mask.setter + def mask(self, value: int) -> None: + ... + + @property + def sensor(self) -> bool: + ... + + @sensor.setter + def sensor(self, value: bool) -> None: + ... + + @property + def surface_velocity(self) -> Vector: + ... + + @surface_velocity.setter + def surface_velocity(self, value: Vector) -> None: + ... + + @property + def trigger_id(self) -> int: + ... + + @trigger_id.setter + def trigger_id(self, value: int) -> None: + ... + + +class BodyNode(NodeBase): + def __init__( + self, *, + position: Vector = Vector(0, 0), + rotation: float = 0, + rotation_degrees: float = 0, + scale: Vector = Vector(1, 1), + z_index: Optional[int] = None, + color: Color = Color(0, 0, 0, 0), + sprite: Optional[Sprite] = None, + shape: Optional[AnyShape] = None, + origin_alignment: Alignment = Alignment.center, + lifetime: float = 0., + transition: AnyTransitionArgument = None, + transformation: Transformation = Transformation(), + visible: bool = True, + views: Optional[Set[int]] = None, + indexable: bool = True, + body_type: BodyNodeType = BodyNodeType.dynamic, + force: Vector = Vector(0, 0), + velocity: Vector = Vector(0, 0), + mass: float = 20.0, + moment: float = 10000.0, + torque: float = 0, + torque_degrees: float = 0, + angular_velocity: float = 0, + angular_velocity_degrees: float = 0, + ) -> None: + ... + + def setup( + self, *, + position: Vector = ..., + rotation: float = ..., + rotation_degrees: float = ..., + scale: Vector = ..., + z_index: Optional[int] = ..., + color: Color = ..., + sprite: Optional[Sprite] = ..., + shape: Optional[AnyShape] = ..., + origin_alignment: Alignment = ..., + lifetime: float = ..., + transition: AnyTransitionArgument = ..., + transformation: Transformation = ..., + visible: bool = ..., + views: Optional[Set[int]] = ..., + indexable: bool = ..., + body_type: BodyNodeType = ..., + force: Vector = ..., + velocity: Vector = ..., + mass: float = ..., + moment: float = ..., + torque: float = ..., + torque_degrees: float = ..., + angular_velocity: float = ..., + angular_velocity_degrees: float = ..., + ) -> None: + ... + + def add_child(self, node: AnyNode) -> AnyNode: + ... + + @property + def angular_velocity(self) -> float: + ... + + @angular_velocity.setter + def angular_velocity(self, value: float) -> None: + ... + + @property + def angular_velocity_degrees(self) -> float: + ... + + @angular_velocity_degrees.setter + def angular_velocity_degrees(self, value: float) -> None: + ... + + @property + def body_type(self) -> BodyNodeType: + ... + + @body_type.setter + def body_type(self, value: BodyNodeType) -> None: + ... + + @property + def center_of_gravity(self) -> Vector: + ... + + @center_of_gravity.setter + def center_of_gravity(self, value: Vector) -> None: + ... + + @property + def damping(self) -> float: + ... + + @damping.setter + def damping(self, value: float) -> None: + ... + + @property + def force(self) -> Vector: + ... + + @force.setter + def force(self, value: Vector) -> None: + ... + + @property + def gravity(self) -> Vector: + ... + + @gravity.setter + def gravity(self, value: Vector) -> None: + ... + + @property + def local_force(self) -> Vector: + ... + + @local_force.setter + def local_force(self, value: Vector) -> None: + ... + + @property + def mass(self) -> float: + ... + + @mass.setter + def mass(self, value: float) -> None: + ... + + @property + def mass_inverse(self) -> float: + ... + + @property + def moment(self) -> float: + ... + + @moment.setter + def moment(self, value: float) -> None: + ... + + @property + def moment_inverse(self) -> float: + ... + + @property + def sleeping(self) -> bool: + ... + + @sleeping.setter + def sleeping(self, value: bool) -> None: + ... + + @property + def torque(self) -> float: + ... + + @torque.setter + def torque(self, value: float) -> None: + ... + + @property + def torque_degrees(self) -> float: + ... + + @torque_degrees.setter + def torque_degrees(self, value: float) -> None: + ... + + @property + def velocity(self) -> Vector: + ... + + @velocity.setter + def velocity(self, value: Vector) -> None: + ... + + @property + def _angular_velocity_bias(self) -> float: + ... + + @_angular_velocity_bias.setter + def _angular_velocity_bias(self, value: float) -> None: + ... + + @property + def _velocity_bias(self) -> Vector: + ... + + @_velocity_bias.setter + def _velocity_bias(self, value: Vector) -> None: + ... + + def apply_force_at(self, force: Vector, at: Vector) -> None: + ... + + def apply_force_at_local(self, force: Vector, at: Vector) -> None: + ... + + def apply_impulse_at(self, force: Vector, at: Vector) -> None: + ... + + def apply_impulse_at_local(self, force: Vector, at: Vector) -> None: + ... + + def set_position_update_callback( + self, callback: Callable[[BodyNode, float], None], + ) -> None: + ... + + def set_velocity_update_callback( + self, callback: Callable[[BodyNode, Vector, float, float], None], + ) -> None: + ... + + +class SpaceNode(NodeBase): + def __init__( + self, *, + position: Vector = Vector(0, 0), + rotation: float = 0, + rotation_degrees: float = 0, + scale: Vector = Vector(1, 1), + z_index: Optional[int] = None, + color: Color = Color(0, 0, 0, 0), + sprite: Optional[Sprite] = None, + shape: Optional[AnyShape] = None, + origin_alignment: Alignment = Alignment.center, + lifetime: float = 0., + transition: AnyTransitionArgument = None, + transformation: Transformation = Transformation(), + visible: bool = True, + views: Optional[Set[int]] = None, + indexable: bool = True, + gravity: Vector = Vector(0, 0), + damping: float = 1., + sleeping_threshold: float = float('inf'), + ) -> None: + ... + + def setup( + self, *, + position: Vector = ..., + rotation: float = ..., + rotation_degrees: float = ..., + scale: Vector = ..., + z_index: Optional[int] = ..., + color: Color = ..., + sprite: Optional[Sprite] = ..., + shape: Optional[AnyShape] = ..., + origin_alignment: Alignment = ..., + lifetime: float = ..., + transition: AnyTransitionArgument = ..., + transformation: Transformation = ..., + visible: bool = ..., + views: Optional[Set[int]] = ..., + indexable: bool = ..., + gravity: Vector = ..., + damping: float = ..., + sleeping_threshold: float = ..., + ) -> None: + ... + + def add_child(self, node: AnyNode) -> AnyNode: + ... + + @property + def damping(self) -> float: + ... + + @damping.setter + def damping(self, damping_value: float) -> None: + ... + + @property + def gravity(self) -> Vector: + ... + + @gravity.setter + def gravity(self, gravity_value: Vector) -> None: + ... + + @property + def locked(self) -> bool: + ... + + @property + def sleeping_threshold(self) -> float: + ... + + @sleeping_threshold.setter + def sleeping_threshold(self, threshold_value: float) -> None: + ... + + def query_point_neighbors( + self, point: Vector, max_distance: float, + *, mask: int = COLLISION_BITMASK_ALL, + collision_mask: int = COLLISION_BITMASK_ALL, + group: int = COLLISION_GROUP_NONE, + ) -> PointQueryResult: + ... + + def query_ray( + self, ray_start: Vector, ray_end: Vector, radius: float = 0., + *, mask: int = COLLISION_BITMASK_ALL, + collision_mask: int = COLLISION_BITMASK_ALL, + group: int = COLLISION_GROUP_NONE, + ) -> RayQueryResult: + ... + def query_shape_overlaps( + self, shape: AnyShape, + *, mask: int = COLLISION_BITMASK_ALL, + collision_mask: int = COLLISION_BITMASK_ALL, + group: int = COLLISION_GROUP_NONE, + ) -> ShapeQueryResult: + ... + def set_collision_handler( + self, trigger_a: int, trigger_b: int, + handler: Callable[[Arbiter, CollisionPair, CollisionPair], Optional[bool]], + phases_mask: CollisionPhase = ..., + only_non_deleted_nodes: bool = True, + ) -> None: + ... diff --git a/src/kaa/py.typed b/src/kaa/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/kaa/sprites.pyi b/src/kaa/sprites.pyi new file mode 100644 index 00000000..6581e14d --- /dev/null +++ b/src/kaa/sprites.pyi @@ -0,0 +1,42 @@ +from __future__ import annotations + +from typing import List + +from .geometry import Vector + + +@final +class Sprite: + @property + def dimensions(self) -> Vector: + ... + + @property + def origin(self) -> Vector: + ... + + @property + def size(self) -> Vector: + ... + + def __init__(self, path: str) -> None: + ... + + def crop(self, origin: Vector, dimensions: Vector) -> Sprite: + ... + + def __eq__(self, other) -> bool: + ... + + def __hash__(self) -> int: + ... + + +def split_spritesheet( + spritesheet: Sprite, + frame_dimensions: Vector, + frames_offset: int = 0, + frames_count: int = 0, + frame_padding: Vector = Vector(0, 0), +) -> List[Sprite]: + ... diff --git a/src/kaa/statistics.pyi b/src/kaa/statistics.pyi new file mode 100644 index 00000000..0c799a83 --- /dev/null +++ b/src/kaa/statistics.pyi @@ -0,0 +1,46 @@ +from __future__ import annotations + +from typing import type_check_only, List, Tuple + + +@final +class StatisticAnalysis: + @property + def last_value(self) -> float: + ... + + @property + def max_value(self) -> float: + ... + + @property + def mean_value(self) -> float: + ... + + @property + def min_value(self) -> float: + ... + + @property + def samples_count(self) -> int: + ... + + @property + def standard_deviation(self) -> float: + ... + + +@type_check_only +class StatisticsManager: + def get_analysis_all(self) -> List[Tuple[str, StatisticAnalysis]]: + ... + + def get_last_all(self) -> List[Tuple[str, float]]: + ... + + def push_value(self, stat_name: str, value: float) -> None: + ... + + +def get_global_statistics_manager() -> StatisticsManager: + ... diff --git a/src/kaa/timers.pyi b/src/kaa/timers.pyi new file mode 100644 index 00000000..f340b262 --- /dev/null +++ b/src/kaa/timers.pyi @@ -0,0 +1,34 @@ +from __future__ import annotations + +from typing import Callable, Optional, type_check_only + +from .engine import Scene + + +@type_check_only +class TimerContext: + @property + def interval(self) -> float: + ... + + @property + def scene(self) -> Optional[Scene]: + ... + + +class Timer: + @property + def is_running(self) -> bool: + ... + + def __init__(self, callback: Callable[[TimerContext], Optional[float]]) -> None: + ... + + def start(self, interval: float, scene: Scene) -> None: + ... + + def start_global(self, interval: float) -> None: + ... + + def stop(self) -> None: + ... diff --git a/src/kaa/transitions.pyi b/src/kaa/transitions.pyi new file mode 100644 index 00000000..f036ab18 --- /dev/null +++ b/src/kaa/transitions.pyi @@ -0,0 +1,200 @@ +from __future__ import annotations + +import enum + +from typing import ( + final, type_check_only, Callable, List, Optional, TypeVar, Sequence, Union, +) + +from .colors import Color +from .easings import Easing +from .geometry import Vector +from .nodes import Node +from .sprites import Sprite + + +class AttributeTransitionMethod(enum.IntEnum): + add: AttributeTransitionMethod + multiply: AttributeTransitionMethod + set: AttributeTransitionMethod + + +@type_check_only +class NodeTransitionBase: + ... + + +@type_check_only +@final +class UnknownTransition(NodeTransitionBase): + ... + + +@final +class NodePositionTransition(NodeTransitionBase): + def __init__( + self, value_advance: Vector, duration: float, + *, + advance_method: AttributeTransitionMethod = AttributeTransitionMethod.set, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class NodeRotationTransition(NodeTransitionBase): + def __init__( + self, value_advance: float, duration: float, + *, + advance_method: AttributeTransitionMethod = AttributeTransitionMethod.set, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class NodeScaleTransition(NodeTransitionBase): + def __init__( + self, value_advance: Vector, duration: float, + *, + advance_method: AttributeTransitionMethod = AttributeTransitionMethod.set, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class NodeColorTransition(NodeTransitionBase): + def __init__( + self, value_advance: Color, duration: float, + *, + advance_method: AttributeTransitionMethod = AttributeTransitionMethod.set, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class BodyNodeVelocityTransition(NodeTransitionBase): + def __init__( + self, value_advance: Vector, duration: float, + *, + advance_method: AttributeTransitionMethod = AttributeTransitionMethod.set, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class BodyNodeAngularVelocityTransition(NodeTransitionBase): + def __init__( + self, value_advance: float, duration: float, + *, + advance_method: AttributeTransitionMethod = AttributeTransitionMethod.set, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class NodeSpriteTransition(NodeTransitionBase): + def __init__( + self, sprites: List[Sprite], duration: float, + *, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class NodeZIndexSteppingTransition(NodeTransitionBase): + def __init__( + self, z_indices: List[int], duration: float, + *, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +@final +class NodeTransitionDelay(NodeTransitionBase): + def __init__(self, duration: float): + ... + + +@final +class NodeTransitionsSequence(NodeTransitionBase): + def __init__( + self, sub_transitions: List[NodeTransitionBase], + *, + loops: int = 1, back_and_forth: bool = False, + ) -> None: + ... + + +@final +class NodeTransitionsParallel(NodeTransitionBase): + def __init__( + self, sub_transitions: List[NodeTransitionBase], + *, + loops: int = 1, back_and_forth: bool = False, + ) -> None: + ... + + +@final +class NodeTransitionCallback(NodeTransitionBase): + def __init__(self, callback_func: Callable[[Node], None]): + ... + + +CustomTransitionStateType = TypeVar('CustomTransitionStateType') + + +@final +class NodeCustomTransition(NodeTransitionBase): + def __init__( + self, prepare_func: Callable[[Node], CustomTransitionStateType], + evaluate_func: Callable[[CustomTransitionStateType, Node, float], None], + duration: float, + *, + loops: int = 1, back_and_forth: bool = False, + easing: Easing = Easing.none, + ) -> None: + ... + + +AnyTransition = Union[ + NodePositionTransition, NodeRotationTransition, NodeScaleTransition, + NodeColorTransition, BodyNodeVelocityTransition, BodyNodeAngularVelocityTransition, + NodeSpriteTransition, NodeZIndexSteppingTransition, + NodeTransitionDelay, NodeTransitionCallback, NodeCustomTransition, + NodeTransitionsSequence, NodeTransitionsParallel, +] + +AnyTransitionArgument = Union[ + AnyTransition, Sequence[AnyTransition], None, +] + + +def NodeTransition(attribute, *args, **kwargs) -> AnyTransition: + ... # TODO find a better way to type-spec this function + + +@type_check_only +class NodeTransitionsManager: + def get(self, transition_name: str) -> AnyTransition: + ... + + def set( + self, transition_name: str, transition: Optional[AnyTransition] + ) -> None: + ... diff --git a/src/kaa/vectors.pxi b/src/kaa/vectors.pxi index 512292f4..4fa7b47d 100644 --- a/src/kaa/vectors.pxi +++ b/src/kaa/vectors.pxi @@ -105,7 +105,7 @@ cdef class Vector: def angle_between(self, Vector other_vec): return c_vector_oriented_angle( - self.c_vector, other_vec.c_vector + c_vector_normalize(self.c_vector), c_vector_normalize(other_vec.c_vector) ) def angle_between_degrees(self, Vector other_vec):