From 5f78ae015feeadc8a5d4cdc0ad045331fb131180 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 04:01:16 +0100 Subject: [PATCH 01/15] Enable nitpicky mode --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 03f5320b39..61c6333c51 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -256,7 +256,7 @@ def run_util(filename, run_name="__main__", init_globals=None): # Warn about all references where the target cannot be found. # This is important to always enable to catch broken doc or api links -# nitpicky = True +nitpicky = True # -- Options for HTML output ---------------------------------------------- From c1b312fc0bdb26e525e8dfb38d5ea02915241a95 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 04:01:48 +0100 Subject: [PATCH 02/15] Sound.source was never exposed in docs --- arcade/sound.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arcade/sound.py b/arcade/sound.py index 4bc3549114..6530f4d781 100644 --- a/arcade/sound.py +++ b/arcade/sound.py @@ -71,6 +71,9 @@ def __init__(self, file_name: str | Path, streaming: bool = False): self.file_name = str(file_name) self.source: Source = media.load(self.file_name, streaming=streaming) + """ + The :py:class:`pyglet.media.Source` object that holds the audio data. + """ if self.source.duration is None: raise ValueError( From 8e69a9fac5f2bcc0fada7cb97108caa007e2ae5b Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 04:02:19 +0100 Subject: [PATCH 03/15] Fix broken refs in sound manual --- doc/programming_guide/sound.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/programming_guide/sound.rst b/doc/programming_guide/sound.rst index 31b3b3192d..375072d225 100644 --- a/doc/programming_guide/sound.rst +++ b/doc/programming_guide/sound.rst @@ -179,7 +179,7 @@ Stopping Sounds Sound data vs Playbacks """"""""""""""""""""""" -Arcade uses the :py:mod:`pyglet` multimedia library to handle sound. +Arcade uses the pyglet multimedia library to handle sound. Each playback of a :py:class:`Sound` has its own |pyglet Player| object to control it: @@ -212,7 +212,7 @@ The first is to choose which function we'll pass its arcade.stop_sound(self.coin_playback_1) -* The :py:class:`Sound` data's :py:meth:`Sound.stop` +* The :py:class:`~arcade.Sound` data's :py:meth:`~arcade.Sound.stop` method: .. code-block:: python @@ -366,7 +366,7 @@ There are more ways to alter playback than stopping. Some are more qualitative. Many of them can be applied to both new and ongoing sound data playbacks, but in different ways. -Both :py:func:`play_sound` and :py:meth:`Sound.play` support the +Both :py:func:`arcade.play_sound` and :py:meth:`arcade.Sound.play` support the following advanced arguments: .. list-table:: @@ -376,22 +376,22 @@ following advanced arguments: - Values - Meaning - * - :py:attr:`~pyglet.media.player.Player.volume` + * - volume - :py:class:`float` between ``0.0`` (silent) and ``1.0`` (full volume) - A scaling factor for the original audio file. - * - :py:attr:`~pyglet.media.player.Player.pan` + * - pan - A :py:class:`float` between ``-1.0`` (left) and ``1.0`` (right) - The left / right channel balance - * - ``loop`` + * - loop - :py:class:`bool` (``True`` / ``False``) - Whether to restart playback automatically after finishing. [#streamingnoloop]_ - * - ``speed`` + * - speed - :py:class:`float` greater than ``0.0`` - The scaling factor for playback speed (and pitch) @@ -479,7 +479,7 @@ these keywords are similar or identical to those of properties on more: * :py:func:`arcade.play_sound` -* :py:meth:`Sound.play` +* :py:meth:`arcade.Sound.play` * :ref:`sound_speed_demo` .. _sound-compat: @@ -695,7 +695,7 @@ The most obvious external library for audio handling is pyglet: * It offers far better control over media than Arcade * You may have already used parts of it directly for :ref:`sound-intermediate-playback` -Note that :py:class:`Sound`'s :py:attr:`~Sound.source` attribute holds a +Note that the :py:class:`arcade.Sound.source` attribute holds a :py:class:`pyglet.media.Source`. This means you can start off by cleanly using Arcade's resource and sound loading with pyglet features as needed. From 452747470478a51341f78484af4ccf14f793155b Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 04:22:32 +0100 Subject: [PATCH 04/15] Fix performance_tips --- doc/programming_guide/performance_tips.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/programming_guide/performance_tips.rst b/doc/programming_guide/performance_tips.rst index e6319a79f1..7caaa1175d 100644 --- a/doc/programming_guide/performance_tips.rst +++ b/doc/programming_guide/performance_tips.rst @@ -35,7 +35,7 @@ The Simplest Solutions are Slow """"""""""""""""""""""""""""""" The simplest approach is a for loop over every wall. Even if the hitboxes -of both the player and the ground :py:class:`Sprite` objects are squares, +of both the player and the ground :py:class:`~arcade.Sprite` objects are squares, it will still be a lot of work. Game developers often use **Big O** notation to describe: @@ -79,7 +79,7 @@ Which should I use? .. [#] Arcade's non-PyMunk physics both engines assume it will be enabled - for any :py:class:`~arcade.sprite_list.SpriteList` provided via their + for any :py:class:`~arcade.SpriteList` provided via their ``walls`` argument. .. _collision_detection_performance_hashing: @@ -88,7 +88,7 @@ Spatial Hashing ^^^^^^^^^^^^^^^ **Spatial hashing** is meant for collision checking sprites -against a :py:class:`~arcade.sprite_list.SpriteList` of +against a :py:class:`~arcade.SpriteList` of **non-moving** sprites: * checking collisions against hashed sprites becomes much faster @@ -99,14 +99,14 @@ uses a **hash map** (:py:class:`dict`) of grid square coordinates to lists of :py:class:`~arcade.Sprite` objects in each square. How does this help us? We may need as few as zero hitbox checks to collide -a given sprite against a :py:class:`~arcade.sprite_list.SpriteList`. Yes, +a given sprite against a :py:class:`~arcade.SpriteList`. Yes, **zero**: .. image:: images/spatial_hash_grid_mockup.png :alt: A blue bird is alone in its own grid square. #. The sand-colored ground consists of sprites in a - :py:class:`~arcade.sprite_list.SpriteList` with spatial hashing enabled + :py:class:`~arcade.SpriteList` with spatial hashing enabled #. The bright green lines show the grid square boundaries #. The moving sprites are the blue bird and the red angry faces @@ -131,12 +131,12 @@ Enabling Spatial Hashing """""""""""""""""""""""" The best way to enable spatial hashing on a -:py:class:`~arcade.sprite_list.SpriteList` is before anything else, +:py:class:`~arcade.SpriteList` is before anything else, especially before gameplay. The simplest way is passing ``use_spatial_hash=True`` when creating and storing the list inside a :py:class:`~arcade.Window` or -:py:class:`~arcade.view.View`: +:py:class:`~arcade.View`: .. code-block:: python @@ -260,7 +260,7 @@ The rest of this section will cover how to avoid that. Drawing Shapes ^^^^^^^^^^^^^^ -The :py:mod:`arcade.draw` module is slow despite being convenient. +The ``arcade.draw_*`` functions are slow despite being convenient. This is because it does not perform batched drawing. Instead of sending batches of shapes to draw, it sends them individually. From 7c8279a09d6cfc870db72ac3668748e541559076 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 05:32:33 +0100 Subject: [PATCH 05/15] Fix gui docs --- arcade/gui/view.py | 3 ++ doc/extensions/prettyspecialmethods.py | 3 ++ doc/programming_guide/gui/concepts.rst | 61 +++++++++++------------ doc/programming_guide/gui/own_layout.rst | 4 +- doc/programming_guide/gui/own_widgets.rst | 8 +-- doc/programming_guide/sound.rst | 6 +-- 6 files changed, 44 insertions(+), 41 deletions(-) diff --git a/arcade/gui/view.py b/arcade/gui/view.py index df3cf01648..110f62734d 100644 --- a/arcade/gui/view.py +++ b/arcade/gui/view.py @@ -29,6 +29,9 @@ class UIView(View): def __init__(self): super().__init__() self.ui = UIManager() + """ + The UIManager of this view. + """ def add_widget(self, widget: W) -> W: """Add a widget to the UIManager of this view.""" diff --git a/doc/extensions/prettyspecialmethods.py b/doc/extensions/prettyspecialmethods.py index 4da89a089b..6bd7f861e3 100644 --- a/doc/extensions/prettyspecialmethods.py +++ b/doc/extensions/prettyspecialmethods.py @@ -214,6 +214,9 @@ def brackets(parameters_node): '__sizeof__': function_transformer('sys.getsizeof'), '__dir__': function_transformer('dir'), '__reversed__': function_transformer('reversed'), + + '__enter__': function_transformer('enter'), + '__exit__': function_transformer('exit'), } diff --git a/doc/programming_guide/gui/concepts.rst b/doc/programming_guide/gui/concepts.rst index c9817bf914..ac24797acc 100644 --- a/doc/programming_guide/gui/concepts.rst +++ b/doc/programming_guide/gui/concepts.rst @@ -8,7 +8,7 @@ The GUI is structured like a tree; every widget can have other widgets as children. The root of the tree is the :py:class:`~arcade.gui.UIManager`. The -:py:class:`UIManager` connects the user interactions with the GUI. Read more about +:py:class:`~arcade.gui.UIManager` connects the user interactions with the GUI. Read more about :ref:`UIEvent`. Classes of Arcade's GUI code are prefixed with ``UI-`` to make them easy to @@ -41,7 +41,6 @@ via the :py:attr:`~arcade.gui.UIView.ui` attribute. It automatically enables and disables the :py:class:`~arcade.gui.UIManager` when the view is shown or hidden. - UIWidget ```````` @@ -52,14 +51,14 @@ such as buttons or labels. User interaction with widgets is processed within :py:meth:`~arcade.gui.UIWidget.on_event`. -A :class:`UIWidget` has following properties. +A :class:`~arcade.gui.UIWidget` has following properties. ``rect`` A tuple with four slots. The first two are x and y coordinates (bottom left of the widget), and the last two are width and height. ``children`` - Child widgets rendered within this widget. A :class:`UIWidget` will not + Child widgets rendered within this widget. A :class:`~arcade.gui.UIWidget` will not move or resize its children; use a :py:class:`~arcade.gui.UILayout` instead. @@ -84,17 +83,17 @@ A :class:`UIWidget` has following properties. ``size_hint_min`` A tuple of two integers defining the minimum width and height of the - widget. These values should be taken into account by :class:`UILayout` when + widget. These values should be taken into account by :class:`~arcade.gui.UILayout` when a ``size_hint`` is given for the axis. ``size_hint_max`` A tuple of two integers defining the maximum width and height of the - widget. These values should be taken into account by :class:`UILayout` when + widget. These values should be taken into account by :class:`~arcade.gui.UILayout` when a ``size_hint`` is given for the axis. .. warning:: Size hints do nothing on their own! - They are hints to :class:`UILayout` instances, which may choose to use or + They are hints to :class:`~arcade.gui.UILayout` instances, which may choose to use or ignore them. UILayout @@ -168,8 +167,8 @@ changes only once. **Example**: Executed steps within :py:class:`~arcade.gui.UIBoxLayout`: -1. :py:meth:`~arcade.UIBoxLayout.prepare_layout` updates own size_hints -2. :py:meth:`~arcade.UIBoxLayout.do_layout` +1. :py:meth:`~arcade.gui.UIBoxLayout.prepare_layout` updates own size_hints +2. :py:meth:`~arcade.gui.UIBoxLayout.do_layout` 1. Collect current ``size``, ``size_hint``, ``size_hint_min`` of children 2. Calculate the new position and sizes 3. Set position and size of children @@ -222,17 +221,17 @@ changes only once. Size hint support ^^^^^^^^^^^^^^^^^ -+--------------------------+------------+----------------+----------------+ -| | size_hint | size_hint_min | size_hint_max | -+==========================+============+================+================+ -| :class:`UIAnchorLayout` | X | X | X | -+--------------------------+------------+----------------+----------------+ -| :class:`UIBoxLayout` | X | X | X | -+--------------------------+------------+----------------+----------------+ -| :class:`UIGridLayout` | X | X | X | -+--------------------------+------------+----------------+----------------+ -| :class:`UIManager` | X | X | X | -+--------------------------+------------+----------------+----------------+ ++--------------------------------------+------------+----------------+----------------+ +| | size_hint | size_hint_min | size_hint_max | ++======================================+============+================+================+ +| :class:`~arcade.gui.UIAnchorLayout` | X | X | X | ++--------------------------------------+------------+----------------+----------------+ +| :class:`~arcade.gui.UIBoxLayout` | X | X | X | ++--------------------------------------+------------+----------------+----------------+ +| :class:`~arcade.gui.UIGridLayout` | X | X | X | ++--------------------------------------+------------+----------------+----------------+ +| :class:`~arcade.gui.UIManager` | X | X | X | ++--------------------------------------+------------+----------------+----------------+ UIMixin ======= @@ -242,9 +241,9 @@ behaviour. Currently the available Mixins are still under heavy development. Available: -- :py:class:`UIDraggableMixin` - Makes a widget draggable with the mouse. -- :py:class:`UIMouseFilterMixin` - Captures all mouse events. -- :py:class:`UIWindowLikeMixin` - Makes a widget behave like a window, combining draggable and mouse filter behaviour. +- :py:class:`~arcade.gui.UIDraggableMixin` - Makes a widget draggable with the mouse. +- :py:class:`~arcade.gui.UIMouseFilterMixin` - Captures all mouse events. +- :py:class:`~arcade.gui.UIWindowLikeMixin` - Makes a widget behave like a window, combining draggable and mouse filter behaviour. UIConstructs ============ @@ -253,8 +252,8 @@ Constructs are predefined structures of widgets and layouts like a message box. Available: -- :py:class:`UIMessageBox` - A simple message box with a title, message and buttons. -- :py:class:`UIButtonRow` - A row of buttons. +- :py:class:`~arcade.gui.UIMessageBox` - A simple message box with a title, message and buttons. +- :py:class:`arcade.gui.UIButtonRow` - A row of buttons. Available Elements ================== @@ -273,7 +272,7 @@ can use the :py:attr:`~arcade.gui.UITextWidget.ui_label` attribute to get the Flat button ^^^^^^^^^^^ -**Name**: :py:class:`~arcade.gui.FlatButton` +**Name**: :py:class:`~arcade.gui.UIFlatButton` A flat button for simple interactions (hover, press, release, click). This button is created with a simple rectangle. Flat buttons can quickly create a @@ -373,14 +372,14 @@ parameters. ``bold`` and ``italic`` will set the text to bold or italic. ``align`` specifies the justification of the text. Additionally it takes ``font_name``, ``font_size``, and ``text_color`` options. -Using the :py:attr:`~arcade.gui.UILabel.label` property accesses the internal +Using the :py:attr:`~arcade.gui.UILabel`'s ``_label`` property accesses the internal :py:class:`~arcade.Text` class. .. hint:: A :py:attr:`~arcade.gui.UILabel.text` attribute can modify the displayed text. Beware-calling this again and again will give a lot of lag. Use - :py:meth:`~arcade.Text.begin_update` and py:meth:`~arcade.Text.end_update` - to speed things up. + :py:meth:`~arcade.Text.__enter__` through the ``with`` statement to speed + things up multiple changes to text instances. Text input field ^^^^^^^^^^^^^^^^ @@ -426,7 +425,7 @@ Arcade's GUI events are fully typed dataclasses, which provide information about an event affecting the UI. All pyglet window events are converted by the -:py:class:`~arcade.gui.UIManager` into :class:`UIEvents` and passed via +:py:class:`~arcade.gui.UIManager` into :class:`~arcade.gui.UIEvent` and passed via :py:meth:`~pyglet.event.EventDispatcher.dispatch_event` to the :py:meth:`~arcade.gui.UIWidget.on_event` callbacks. @@ -513,7 +512,7 @@ Different event systems Arcade's GUI uses different event systems, dependent on the required flow. A game developer should mostly interact with user-interface events, which are -dispatched from specific :py:class:`~arcade.gui.UIWidget`s like an ``on_click`` +dispatched from a specific :py:class:`~arcade.gui.UIWidget` like an ``on_click`` of a button. In cases where a developer implement own widgets themselves or want to diff --git a/doc/programming_guide/gui/own_layout.rst b/doc/programming_guide/gui/own_layout.rst index d054264c68..3232ca9bcc 100644 --- a/doc/programming_guide/gui/own_layout.rst +++ b/doc/programming_guide/gui/own_layout.rst @@ -20,7 +20,7 @@ The main method you need to implement is: - :meth:`arcade.gui.UILayout.do_layout` - This method is called to layout the child widgets. -Widgets added to the layout are accessible via the :attr:`arcade.gui.UILayout._children` attribute, +Widgets added to the layout are accessible via the ``arcade.gui.UILayout._children`` attribute, which is a list of all added widgets with the parameter provided when added. Children should be placed within the bounds of the layout. @@ -36,5 +36,3 @@ Example `CircleLayout` ~~~~~~~~~~~~~~~~~~~~~~ .. literalinclude:: ../../../arcade/examples/gui/own_layout.py - - diff --git a/doc/programming_guide/gui/own_widgets.rst b/doc/programming_guide/gui/own_widgets.rst index 495ab79fc2..dcad37500f 100644 --- a/doc/programming_guide/gui/own_widgets.rst +++ b/doc/programming_guide/gui/own_widgets.rst @@ -27,12 +27,12 @@ You can also make use of other base classes, which provide a more specialized in Further baseclasses are: - :class:`arcade.gui.UIInteractiveWidget` - `UIInteractiveWidget` is a baseclass for widgets that can be interacted with. - It handles mouse events and provides properties like `hovered` or `pressed` and an :meth:`on_click` method. + A base class for widgets that can be interacted with. + It handles mouse events and provides properties like `hovered` or `pressed` and an :meth:`~arcade.gui.UIInteractiveWidget.on_click` method. - :class:`arcade.gui.UIAnchorLayout` - `UIAnchorLayout` is basically a frame, which can be used to place widgets - to a position within itself. This makes it a great baseclass for a widget containing + Basically a frame, which can be used to place widgets + to a position within itself. This makes it a great base class for a widget containing multiple other widgets. (Examples: `MessageBox`, `Card`, etc.) If your widget should act more as a general layout, position various widgets and handle their size, diff --git a/doc/programming_guide/sound.rst b/doc/programming_guide/sound.rst index 375072d225..6ae28095df 100644 --- a/doc/programming_guide/sound.rst +++ b/doc/programming_guide/sound.rst @@ -152,14 +152,14 @@ The first way to play it is passing it to :py:func:`arcade.play_sound`: We store the return value because it is a special object which lets us control this specific playback of the :py:class:`Sound` data. -.. important:: You **must** pass a :py:class:`Sound`, not a path! +.. important:: You **must** pass a :py:class:`~arcade.Sound`, not a path! If you pass :py:func:`arcade.play_sound` anything other than a :py:class:`Sound` or ``None``, it will raise a :py:class:`TypeError`. -To avoid making this mistake, you can call the :py:class:`Sound` -data's :py:meth:`Sound.play` method instead: +To avoid making this mistake, you can call the :py:class:`~arcade.Sound` +data's :py:meth:`~arcade.Sound.play` method instead: .. code-block:: python From 44bfbee912336ce72bef3436dc4046951ae8fbe7 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 05:38:01 +0100 Subject: [PATCH 06/15] Fix event_loop --- doc/programming_guide/event_loop.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/programming_guide/event_loop.rst b/doc/programming_guide/event_loop.rst index 36532cab90..820ca26d08 100644 --- a/doc/programming_guide/event_loop.rst +++ b/doc/programming_guide/event_loop.rst @@ -54,33 +54,33 @@ to the window's own events. For simple time keeping Arcade provides global clock objects. Both clocks can be imported from ``arcade.clock`` as ``GLOBAL_CLOCK`` and ``GLOBAL_FIXED_CLOCK`` -:py:class:`arcade.Clock` -^^^^^^^^^^^^^^^^^^^^^^^^ +:py:class:`~arcade.clock.Clock` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The base Arcade clock tracks the elapsed time in seconds, the total number of clock ticks, and the amount of time that elapsed since the last tick. The currently active window automatically ticks the ``GLOBAL_CLOCK`` every ``on_update``. This means there is no reason to manually tick it. If you need more -clocks, possibly ticking at a different rate, an :py:class:`arcade.Clock` +clocks, possibly ticking at a different rate, an :py:class:`arcade.clock.Clock` can be created on the fly. -:py:class:`arcade.FixedClock` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:py:class:`~arcade.clock.FixedClock` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The fixed clock tracks the same values as the normal clock, but has two special features. Firstly it enforces that the ``delta_time`` passed into its ``tick`` method is always the same. This is because advanced physics engines require consistent time. Secondly the fixed clock requires a sibling regular clock. It uses this clock to track how offset from the true time it is. -Like the regular clock you may make a new :py:class:`arcade.FixedClock` at any time, +Like the regular clock you may make a new :py:class:`~arcade.clock.FixedClock` at any time, but ensure they have a sibling. Up Coming ^^^^^^^^^ -In future version of arcade :py:class:`Clock` will be updated to allow for sub clocks. +In future version of arcade :py:class:`~arcade.clock.Clock` will be updated to allow for sub clocks. Sub clocks will be ticked by their parent clock rather than be manually updated. Sub clocks will make it easier to control the flow of time for specific groups of objects. Such as only -slowing enemies or excluding UI elements. To gain access to a draft :py:class:`arcade.Clock` +slowing enemies or excluding UI elements. To gain access to a draft :py:class:`~arcade.clock.Clock` you can find it in ``arcade.future.sub_clock``. This version of the sub clock is not final. If you find any bugs do not hesitate to raise an issue on the github. @@ -88,22 +88,22 @@ More on Fixed update -------------------- The ``on_fixed_update`` event can be an extremely powerful tool, but it has many complications -that should be taken into account. If used imporperly the event can grind a game to a halt. +that should be taken into account. If used improperly the event can grind a game to a halt. Death Spiral ^^^^^^^^^^^^ A fixed update represents a very specific amount of time. If all of the computations take -longer than the fixed update represents than the ammount of time accumulated between update +longer than the fixed update represents than the amount of time accumulated between update events will grow. If this happens for multiple frames the game will begin to spiral. The first few frames of the spiral will lead to one update cycle requiring two fixed update calls. This will increase the extra time accumulated until three fixed updates must occur at once. This will continue to happen until either: the fixed updates start taking less time, or the game crashes. -There are a few solutions to this issue. The simplist method, which works best when there may be spikes in +There are a few solutions to this issue. The simplest method, which works best when there may be spikes in computation time that quickly settle, is to clamp the max number of fixed updates that can occur in a single -frame. In Arcade this is done by setting the ``fixed_frame_cap`` argument when initialising your +frame. In Arcade this is done by setting the ``fixed_frame_cap`` argument when initializing your :py:class:`arcade.Window`. The second method is to slow-down time temporarily. By changing the ``_tick_speed`` of Arcade's ``GLOBAL_CLOCK`` is is possible to slow down the accumulation of time. For example setting ``GLOBAL_CLOCK._tick_speed = 0.5`` would allow the fixed update twice as many frames From ea899a307dea2cddba153df3f67cc6ae5b605600 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 16:28:43 +0100 Subject: [PATCH 07/15] arcade.gl: Remove optional markers in docstrings --- arcade/gl/buffer.py | 4 ++-- arcade/gl/context.py | 30 +++++++++++++++--------------- arcade/gl/framebuffer.py | 4 ++-- arcade/gl/program.py | 14 +++++++------- arcade/gl/texture.py | 2 +- arcade/gl/texture_array.py | 4 ++-- arcade/gl/types.py | 4 ++-- arcade/gl/vertex_array.py | 6 +++--- 8 files changed, 34 insertions(+), 34 deletions(-) diff --git a/arcade/gl/buffer.py b/arcade/gl/buffer.py index de565dee41..7504bc46bd 100644 --- a/arcade/gl/buffer.py +++ b/arcade/gl/buffer.py @@ -249,10 +249,10 @@ def orphan(self, size: int = -1, double: bool = False): it will be deallocated by OpenGL when completed. Args: - size: (optional) + size: New size of buffer. -1 will retain the current size. Takes precedence over ``double`` parameter if specified. - double (optional): + double: Is passed in with `True` the buffer size will be doubled from its current size. """ diff --git a/arcade/gl/context.py b/arcade/gl/context.py index b7f33c24f6..d1a86c08bb 100644 --- a/arcade/gl/context.py +++ b/arcade/gl/context.py @@ -1029,7 +1029,7 @@ def texture( dtype: The data type of each component: f1, f2, f4 / i1, i2, i4 / u1, u2, u4 data: - The texture data (optional). Can be ``bytes`` + The texture data. Can be ``bytes`` or any object supporting the buffer protocol. wrap_x: How the texture wraps in x direction @@ -1114,7 +1114,7 @@ def depth_texture( Args: size: The size of the texture - data (optional): + data: The texture data. Can be``bytes`` or any object supporting the buffer protocol. """ @@ -1200,13 +1200,13 @@ def geometry( ) Args: - content (optional): + content: List of :py:class:`~arcade.gl.BufferDescription` - index_buffer (optional): + index_buffer: Index/element buffer - mode (optional): + mode: The default draw mode - mode (optional): + mode: The default draw mode index_element_size: Byte size of a single index/element in the index buffer. @@ -1241,23 +1241,23 @@ def program( Args: vertex_shader: vertex shader source - fragment_shader (optional): + fragment_shader: fragment shader source - geometry_shader (optional): + geometry_shader: geometry shader source - tess_control_shader (optional): + tess_control_shader: tessellation control shader source - tess_evaluation_shader (optional): + tess_evaluation_shader: tessellation evaluation shader source - common (optional): + common: Common shader sources injected into all shaders - defines (optional): + defines: Substitute #defines values in the source - varyings (optional): + varyings: The name of the out attributes in a transform shader. This is normally not necessary since we auto detect them, but some more complex out structures we can't detect. - varyings_capture_mode (optional): + varyings_capture_mode: The capture mode for transforms. - ``"interleaved"`` means all out attribute will be written to a single buffer. @@ -1326,7 +1326,7 @@ def compute_shader(self, *, source: str, common: Iterable[str] = ()) -> ComputeS Args: source: The glsl source - common (optional): + common: Common / library source injected into compute shader """ src = ShaderSource(self, source, common, gl.GL_COMPUTE_SHADER) diff --git a/arcade/gl/framebuffer.py b/arcade/gl/framebuffer.py index 15b7edc0ed..188c5a5634 100644 --- a/arcade/gl/framebuffer.py +++ b/arcade/gl/framebuffer.py @@ -41,9 +41,9 @@ class Framebuffer: Args: ctx: The context this framebuffer belongs to - color_attachments (optional): + color_attachments: A color attachment or a list of color attachments - depth_attachment (optional): + depth_attachment: A depth attachment """ diff --git a/arcade/gl/program.py b/arcade/gl/program.py index 7f531c0cb1..27d05504cc 100644 --- a/arcade/gl/program.py +++ b/arcade/gl/program.py @@ -45,19 +45,19 @@ class Program: Args: ctx: The context this program belongs to - vertex_shader (optional): + vertex_shader: Vertex shader source - fragment_shader (optional): + fragment_shader: Fragment shader source - geometry_shader (optional)v: + geometry_shader: Geometry shader source - tess_control_shader (optional): + tess_control_shader: Tessellation control shader source - tess_evaluation_shader (optional): + tess_evaluation_shader: Tessellation evaluation shader source - varyings (optional): + varyings: List of out attributes used in transform feedback. - varyings_capture_mode (optional): + varyings_capture_mode: The capture mode for transforms. ``"interleaved"`` means all out attribute will be written to a single buffer. ``"separate"`` means each out attribute will be written separate buffers. diff --git a/arcade/gl/texture.py b/arcade/gl/texture.py index 18ae743628..479fa23ce8 100644 --- a/arcade/gl/texture.py +++ b/arcade/gl/texture.py @@ -56,7 +56,7 @@ class Texture2D: dtype: The data type of each component: f1, f2, f4 / i1, i2, i4 / u1, u2, u4 data: - The texture data (optional). Can be bytes or any object supporting + The texture data. Can be bytes or any object supporting the buffer protocol. filter: The minification/magnification filter of the texture diff --git a/arcade/gl/texture_array.py b/arcade/gl/texture_array.py index f80aa9773e..c75d666e82 100644 --- a/arcade/gl/texture_array.py +++ b/arcade/gl/texture_array.py @@ -57,7 +57,7 @@ class TextureArray: dtype: The data type of each component: f1, f2, f4 / i1, i2, i4 / u1, u2, u4 data: - The texture data (optional). Can be bytes or any object supporting + The texture data. Can be bytes or any object supporting the buffer protocol. filter: The minification/magnification filter of the texture @@ -662,7 +662,7 @@ def write(self, data: BufferOrBufferProtocol, level: int = 0, viewport=None) -> :class:`~arcade.gl.Buffer` or buffer protocol object with data to write. level: The texture level to write (LoD level, now layer) - viewport (optional): + viewport: The area of the texture to write. Should be a 3 or 5-component tuple `(x, y, layer, width, height)` writes to an area of a single layer. If not provided the entire texture is written to. diff --git a/arcade/gl/types.py b/arcade/gl/types.py index 414fec15f1..a6f9dc3092 100644 --- a/arcade/gl/types.py +++ b/arcade/gl/types.py @@ -166,9 +166,9 @@ class AttribFormat: The OpenGL type such as GL_FLOAT, GL_HALF_FLOAT etc. bytes_per_component: Number of bytes for a single component - offset (optional): + offset: Offset for BufferDescription - location (optional): + location: Location for program attribute """ diff --git a/arcade/gl/vertex_array.py b/arcade/gl/vertex_array.py index ce4f659e4f..80ed9eda9a 100644 --- a/arcade/gl/vertex_array.py +++ b/arcade/gl/vertex_array.py @@ -37,11 +37,11 @@ class VertexArray: The context this object belongs to program: The program to use - content (optional): + content: List of BufferDescriptions - index_buffer (optional): + index_buffer: Index/element buffer - index_element_size (optional): + index_element_size: Byte size of the index buffer datatype. """ From 428de1e0a28e187757d5e1cdf253f4e244fd7f8f Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 17:44:01 +0100 Subject: [PATCH 08/15] gl module fixes --- arcade/gl/types.py | 26 +++++++++++++++----------- doc/api_docs/gl/index.rst | 1 + doc/api_docs/gl/types.rst | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 doc/api_docs/gl/types.rst diff --git a/arcade/gl/types.py b/arcade/gl/types.py index a6f9dc3092..190ea147ad 100644 --- a/arcade/gl/types.py +++ b/arcade/gl/types.py @@ -23,8 +23,8 @@ tuple[PyGLenum, PyGLenum], tuple[PyGLenum, PyGLenum, PyGLenum, PyGLenum] ] -# Depth compare functions -compare_funcs = { +#: Depth compare functions +compare_funcs: dict[str | None, int] = { None: gl.GL_NONE, "<=": gl.GL_LEQUAL, "<": gl.GL_LESS, @@ -36,8 +36,8 @@ "1": gl.GL_ALWAYS, } -# Swizzle conversion lookup -swizzle_enum_to_str = { +#: Swizzle conversion lookup +swizzle_enum_to_str: dict[int, str] = { gl.GL_RED: "R", gl.GL_GREEN: "G", gl.GL_BLUE: "B", @@ -45,7 +45,9 @@ gl.GL_ZERO: "0", gl.GL_ONE: "1", } -swizzle_str_to_enum = { + +#: Swizzle conversion lookup +swizzle_str_to_enum: dict[str, int] = { "R": gl.GL_RED, "G": gl.GL_GREEN, "B": gl.GL_BLUE, @@ -62,7 +64,7 @@ gl.GL_RGB_INTEGER, gl.GL_RGBA_INTEGER, ) -# format: (base_format, internal_format, type, size) +#: Pixel format lookup (base_format, internal_format, type, size) pixel_formats = { # float formats "f1": ( @@ -124,7 +126,7 @@ } -# String representation of a shader type +#: String representation of a shader types SHADER_TYPE_NAMES = { gl.GL_VERTEX_SHADER: "vertex shader", gl.GL_FRAGMENT_SHADER: "fragment shader", @@ -133,6 +135,7 @@ gl.GL_TESS_EVALUATION_SHADER: "tessellation evaluation shader", } +#: Lookup table for OpenGL type names GL_NAMES = { gl.GL_HALF_FLOAT: "GL_HALF_FLOAT", gl.GL_FLOAT: "GL_FLOAT", @@ -154,7 +157,7 @@ def gl_name(gl_type: PyGLenum | None) -> str | PyGLenum | None: class AttribFormat: - """ " + """ Represents a vertex attribute in a BufferDescription / Program. This is attribute metadata used when attempting to map vertex shader inputs. @@ -227,7 +230,7 @@ class BufferDescription: be used once for the whole geometry. The geometry will be repeated a number of times equal to the number of items in the Buffer. - Example:: + .. code-block:: python # Describe my_buffer # It contains two floating point numbers being a 2d position @@ -386,7 +389,7 @@ def __eq__(self, other) -> bool: class TypeInfo: """ - Describes an opengl type + Describes an opengl type. Args: name: @@ -515,7 +518,8 @@ class GLTypes: } @classmethod - def get(cls, enum: int): + def get(cls, enum: int) -> TypeInfo: + """Get the TypeInfo for a given""" try: return cls.types[enum] except KeyError: diff --git a/doc/api_docs/gl/index.rst b/doc/api_docs/gl/index.rst index 99bc39443a..d8afa586fc 100644 --- a/doc/api_docs/gl/index.rst +++ b/doc/api_docs/gl/index.rst @@ -49,5 +49,6 @@ directory (git). sampler utils exceptions + types .. _ModernGL: https://github.com/moderngl/moderngl diff --git a/doc/api_docs/gl/types.rst b/doc/api_docs/gl/types.rst new file mode 100644 index 0000000000..efb98dbe6c --- /dev/null +++ b/doc/api_docs/gl/types.rst @@ -0,0 +1,38 @@ + +.. py:currentmodule:: arcade.gl.types + +Types +===== + +.. autodata:: BufferProtocol +.. autodata:: BufferOrBufferProtocol +.. autodata:: PyGLenum +.. autodata:: GLuintLike +.. autodata:: PyGLuint +.. autodata:: OpenGlFilter +.. autodata:: BlendFunction + +.. autodata:: compare_funcs +.. autodata:: swizzle_enum_to_str +.. autodata:: swizzle_str_to_enum +.. autodata:: pixel_formats + +.. autodata:: SHADER_TYPE_NAMES +.. autodata:: GL_NAMES + +.. autofunction:: gl_name + +.. autoclass:: AttribFormat + :members: + :undoc-members: + :member-order: bysource + +.. autoclass:: TypeInfo + :members: + :undoc-members: + :member-order: bysource + +.. autoclass:: GLTypes + :members: + :undoc-members: + :member-order: bysource From 6750b840d08132d3565e37c9f7b0f4316ec5ebb3 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 17:54:59 +0100 Subject: [PATCH 09/15] Remove optional annotations in napoleon docstrings --- CONTRIBUTING.md | 3 +- arcade/application.py | 64 ++++++++++++------------ arcade/context.py | 28 +++++------ arcade/gui/widgets/__init__.py | 6 +-- arcade/sections.py | 18 ++++--- arcade/sprite/animated.py | 2 +- arcade/text.py | 70 +++++++++++++-------------- arcade/texture/generate.py | 10 ++-- arcade/texture/loading.py | 2 +- arcade/texture/manager.py | 12 ++--- arcade/texture/spritesheet.py | 4 +- arcade/texture/texture.py | 4 +- arcade/texture_atlas/atlas_default.py | 4 +- arcade/texture_atlas/region.py | 2 +- 14 files changed, 115 insertions(+), 114 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0864aef4dd..38ca1b7333 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,7 +103,7 @@ The minium for docstrings is covering all parameters in an `Args:` block. Args: width: The width of something height: The height of something - title (optional): The title of something + title: The title of something ``` * `Args:` should be used for all parameters @@ -115,7 +115,6 @@ Args: * `Attributes:` we should try to avoid it and instead document the attributes in the code * Types are visible in the api docs. It's not mandatory to include types in docstring, however, simple types like `int`, `str`, `float`, `bool` can be included. -* Using `optional` is a good way to indicate that a parameter is optional. * Properties and attribute docs don't need a type when this is already clear from type or return annotation. diff --git a/arcade/application.py b/arcade/application.py index a0979daae7..edf55efb04 100644 --- a/arcade/application.py +++ b/arcade/application.py @@ -86,51 +86,51 @@ class Window(pyglet.window.Window): .. _pyglet_pg_window_style: https://pyglet.readthedocs.io/en/latest/programming_guide/windowing.html#window-style Args: - width (optional): + width: Window width. Defaults to 1280. - height (optional): + height: Window height. Defaults to 720. - title (optional): + title: The title/caption of the window - fullscreen (optional): + fullscreen: Should this be full screen? - resizable (optional): + resizable: Can the user resize the window? - update_rate (optional): + update_rate: How frequently to run the on_update event. - draw_rate (optional): + draw_rate: How frequently to run the on_draw event. (this is the FPS limit) - fixed_rate (optional): + fixed_rate: How frequently should the fixed_updates run, fixed updates will always run at this rate. - fixed_frame_cap (optional): + fixed_frame_cap: The maximum number of fixed updates that can occur in one update loop. defaults to infinite. If large lag spikes cause your game to freeze, try setting this to a smaller number. This may cause your physics to lag behind temporarily. - antialiasing (optional): + antialiasing: Use multisampling framebuffer (antialiasing) samples: Number of samples used in antialiasing (default 4). Usually this is 2, 4, 8 or 16. - gl_version (optional): What OpenGL version to request. + gl_version: What OpenGL version to request. This is ``(3, 3)`` by default and can be overridden when using more advanced OpenGL features. - screen (optional): Pass a pyglet :py:class:`~pyglet.display.Screen` to + screen: Pass a pyglet :py:class:`~pyglet.display.Screen` to request the window be placed on it. See `pyglet's window size & position guide `_ to learn more. - style (optional): Request a non-default window style, such as borderless. + style: Request a non-default window style, such as borderless. Some styles only work in certain situations. See `pyglet's guide to window style `_ to learn more. - visible (optional): + visible: Should the window be visible immediately - vsync (optional): + vsync: Wait for vertical screen refresh before swapping buffer This can make animations and movement look smoother. - gc_mode (optional): Decides how OpenGL objects should be garbage collected + gc_mode: Decides how OpenGL objects should be garbage collected ("context_gc" (default) or "auto") - center_window (optional): + center_window: If true, will center the window. - enable_polling (optional): + enable_polling: Enabled input polling capability. This makes the :py:attr:`keyboard` and :py:attr:`mouse` attributes available for use. @@ -356,17 +356,17 @@ def clear( # type: ignore # not sure what to do here, BaseWindow.clear is stati set through :py:attr:`~arcade.Window.background_color`. Args: - color (optional): + color: Override the current background color with one of the following: 1. A :py:class:`~arcade.types.Color` instance 2. A 3 or 4-length RGB/RGBA :py:class:`tuple` of byte values (0 to 255) - color_normalized (optional): + color_normalized: override the current background color using normalized values (0.0 to 1.0). For example, (1.0, 0.0, 0.0, 1.0) making the window contents red. - viewport (optional): + viewport: The area of the window to clear. By default, the entire window is cleared. The viewport format is ``(x, y, width, height)``. """ @@ -455,19 +455,19 @@ def set_fullscreen( to the size it was before entering fullscreen mode. Args: - fullscreen (optional): + fullscreen: Should we enter or leave fullscreen mode? - screen (optional): + screen: Which screen should we display on? See :func:`get_screens` - mode (optional): + mode: The screen will be switched to the given mode. The mode must have been obtained by enumerating `Screen.get_modes`. If None, an appropriate mode will be selected from the given `width` and `height`. - width (optional): - Override the width of the window. Will be rounded to :py:attr:`int`. - height (optional): - Override the height of the window. Will be rounded to :py:attr:`int`. + width: + Override the width of the window. Will be rounded to :py:class:`int`. + height: + Override the height of the window. Will be rounded to :py:class:`int`. """ # fmt: off super().set_fullscreen( @@ -1280,7 +1280,7 @@ class View: and a game over screen. Each of these could be a different view. Args: - window (optional): + window: The window this view is associated with. If None, the current window is used. (Normally you don't need to provide this). """ @@ -1304,15 +1304,15 @@ def clear( set through :py:attr:`arcade.View.background_color`. Args: - color(optional): + color: override the current background color with one of the following: 1. A :py:class:`~arcade.types.Color` instance 2. A 3 or 4-length RGB/RGBA :py:class:`tuple` of byte values (0 to 255) - color_normalized (optional): + color_normalized: Override the current background color using normalized values (0.0 to 1.0). For example, (1.0, 0.0, 0.0, 1.0) making the window contents red. - viewport (optional): + viewport: The viewport range to clear """ if color is None and color_normalized is None: diff --git a/arcade/context.py b/arcade/context.py index 9a3a8d7e55..8ca0b58749 100644 --- a/arcade/context.py +++ b/arcade/context.py @@ -358,23 +358,23 @@ def load_program( Args: vertex_shader: Path to the vertex shader. - fragment_shader (optional): - Path to the fragment shader (optional). - geometry_shader (optional): - Path to the geometry shader (optional). - tess_control_shader (optional): + fragment_shader: + Path to the fragment shader. + geometry_shader: + Path to the geometry shader. + tess_control_shader: Tessellation Control Shader. - tess_evaluation_shader (optional): + tess_evaluation_shader: Tessellation Evaluation Shader. - common (optional): + common: Common files to be included in all shaders. - defines (optional): + defines: Substitute `#define` values in the source. - varyings (optional): + varyings: The name of the out attributes in a transform shader. This is normally not necessary since we auto detect them, but some more complex out structures we can't detect. - varyings_capture_mode (optional): + varyings_capture_mode: The capture mode for transforms. Based on these settings, the `transform()` method will accept a single @@ -435,7 +435,7 @@ def load_compute_shader( Args: path: Path to texture - common (optional): + common: Common sources injected into compute shader """ from arcade.resources import resolve @@ -492,13 +492,13 @@ def load_texture( The min and mag filter. Default is ``None``. build_mipmaps: Build mipmaps for the texture. Default is ``False``. - internal_format (optional): + internal_format: The internal format of the texture. This can be used to override the default internal format when using sRGBA or compressed textures. - immutable (optional): + immutable: Make the storage (not the contents) immutable. This can sometimes be required when using textures with compute shaders. - compressed (optional): + compressed: If the internal format is a compressed format meaning your texture will be compressed by the GPU. """ diff --git a/arcade/gui/widgets/__init__.py b/arcade/gui/widgets/__init__.py index 7d4f341a9c..26a56d4c42 100644 --- a/arcade/gui/widgets/__init__.py +++ b/arcade/gui/widgets/__init__.py @@ -396,9 +396,9 @@ def resize(self, *, width=None, height=None, anchor: Vec2 = AnchorPoint.CENTER): """Resizes the widget. Args: - width (optional): new width - height (optional): new height - anchor (optional): anchor point for resizing, default is center + width: new width + height: new height + anchor: anchor point for resizing, default is center """ self.rect = self.rect.resize(width=width, height=height, anchor=anchor) diff --git a/arcade/sections.py b/arcade/sections.py index 0e1f66ae17..4b34ab10b8 100644 --- a/arcade/sections.py +++ b/arcade/sections.py @@ -29,14 +29,16 @@ class Section: width: the width of this section height: the height of this section name: the name of this section - bool | Iterable accept_keyboard_keys: whether this section - captures keyboard keys through. keyboard events. If the param is an iterable - means the keyboard keys that are captured in press/release events: - for example: ``[arcade.key.UP, arcade.key.DOWN]`` will only capture this two keys - bool Iterable accept_mouse_events: whether this section - captures mouse events. If the param is an iterable means the mouse events - that are captured. for example: ``['on_mouse_press', 'on_mouse_release']`` - will only capture this two events. + accept_keyboard_keys: + bool | Iterable accept_keyboard_keys: whether this section + captures keyboard keys through. keyboard events. If the param is an iterable + means the keyboard keys that are captured in press/release events: + for example: ``[arcade.key.UP, arcade.key.DOWN]`` will only capture this two keys + accept_mouse_events: + bool Iterable accept_mouse_events: whether this section + captures mouse events. If the param is an iterable means the mouse events + that are captured. for example: ``['on_mouse_press', 'on_mouse_release']`` + will only capture this two events. prevent_dispatch: a list of event names that will not be dispatched to subsequent sections. You can pass None (default) or {True} to prevent the dispatch of all events. prevent_dispatch_view: a list of event names that will not be dispatched to the view. diff --git a/arcade/sprite/animated.py b/arcade/sprite/animated.py index 7325561c98..fec99c65c4 100644 --- a/arcade/sprite/animated.py +++ b/arcade/sprite/animated.py @@ -27,7 +27,7 @@ class TextureKeyframe: Texture to display for this keyframe. duration: Duration in milliseconds to display this keyframe. - tile_id (optional): + tile_id: Tile ID for this keyframe (only used for tiled maps). This can be ignored when not using tiled maps. """ diff --git a/arcade/text.py b/arcade/text.py index 39b0d9c55e..ae03a12170 100644 --- a/arcade/text.py +++ b/arcade/text.py @@ -204,25 +204,25 @@ class Text: text: Initial text to display. Can be an empty string x: x position to align the text's anchor point with y: y position to align the text's anchor point with - z (optional): z position to align the text's anchor point with - color (optional): Color of the text as an RGBA tuple or a + z: z position to align the text's anchor point with + color: Color of the text as an RGBA tuple or a :py:class:`~arcade.types.Color` instance. - font_size (optional): Size of the text in points - width (optional): A width limit in pixels - align (optional): Horizontal alignment; values other than "left" require width to be set. + font_size: Size of the text in points + width: A width limit in pixels + align: Horizontal alignment; values other than "left" require width to be set. Valid options: ``"left"``, ``"center"``, ``"right"``. - font_name (optional): A font name, path to a font file, or list of names - bold (optional): Whether to draw the text as bold, and if a string, + font_name: A font name, path to a font file, or list of names + bold: Whether to draw the text as bold, and if a string, how bold. See :py:attr:`.bold` to learn more. - italic (optional): Whether to draw the text as italic - anchor_x (optional): How to calculate the anchor point's x coordinate. + italic: Whether to draw the text as italic + anchor_x: How to calculate the anchor point's x coordinate. Options: "left", "center", or "right" - anchor_y (optional): How to calculate the anchor point's y coordinate. + anchor_y: How to calculate the anchor point's y coordinate. Options: "top", "bottom", "center", or "baseline". - multiline (optional): Requires width to be set; enables word wrap rather than clipping - rotation (optional): rotation in degrees, clockwise from horizontal - batch (optional): The batch to add the text to (for batch rendering text) - group (optional): The specific group in a a batch to add the text to + multiline: Requires width to be set; enables word wrap rather than clipping + rotation: rotation in degrees, clockwise from horizontal + batch: The batch to add the text to (for batch rendering text) + group: The specific group in a a batch to add the text to (for batch rendering text) All constructor arguments other than ``text`` have a corresponding @@ -738,19 +738,19 @@ def create_text_sprite( Args: text: Initial text to display. Can be an empty string - color (optional): Color of the text as an RGBA tuple or a + color: Color of the text as an RGBA tuple or a :py:class:`~arcade.types.Color` instance. - font_size (optional): Size of the text in points - width (optional): A width limit in pixels - align (optional): Horizontal alignment; values other than "left" require width to be set. + font_size: Size of the text in points + width: A width limit in pixels + align: Horizontal alignment; values other than "left" require width to be set. Valid options: ``"left"``, ``"center"``, ``"right"``. - font_name (optional): A font name, path to a font file, or list of names - bold (optional): Whether to draw the text as bold, and if a string, + font_name: A font name, path to a font file, or list of names + bold: Whether to draw the text as bold, and if a string, how bold. See :py:attr:`arcade.gui.widgets.text.bold` to learn more. - italic (optional): Whether to draw the text as italic - anchor_x (optional): How to calculate the anchor point's x coordinate. + italic: Whether to draw the text as italic + anchor_x: How to calculate the anchor point's x coordinate. Options: "left", "center", or "right" - multiline (optional): Requires width to be set; enables word wrap rather than clipping + multiline: Requires width to be set; enables word wrap rather than clipping background_color: The background color of the text. If None, the background will be transparent. texture_atlas: The texture atlas to use for the @@ -843,23 +843,23 @@ def draw_text( text: Initial text to display. Can be an empty string x: x position to align the text's anchor point with y: y position to align the text's anchor point with - z (optional): z position to align the text's anchor point with - color (optional): Color of the text as an RGBA tuple or a + z: z position to align the text's anchor point with + color: Color of the text as an RGBA tuple or a :py:class:`~arcade.types.Color` instance. - font_size (optional): Size of the text in points - width (optional): A width limit in pixels - align (optional): Horizontal alignment; values other than "left" require width to be set. + font_size: Size of the text in points + width: A width limit in pixels + align: Horizontal alignment; values other than "left" require width to be set. Valid options: ``"left"``, ``"center"``, ``"right"``. - font_name (optional): A font name, path to a font file, or list of names - bold (optional): Whether to draw the text as bold, and if a string, + font_name: A font name, path to a font file, or list of names + bold: Whether to draw the text as bold, and if a string, how bold. See :py:attr:`arcade.gui.widgets.text.bold` to learn more. - italic (optional): Whether to draw the text as italic - anchor_x (optional): How to calculate the anchor point's x coordinate. + italic: Whether to draw the text as italic + anchor_x: How to calculate the anchor point's x coordinate. Options: "left", "center", or "right" - anchor_y (optional): How to calculate the anchor point's y coordinate. + anchor_y: How to calculate the anchor point's y coordinate. Options: "top", "bottom", "center", or "baseline". - multiline (optional): Requires width to be set; enables word wrap rather than clipping - rotation (optional): rotation in degrees, clockwise from horizontal + multiline: Requires width to be set; enables word wrap rather than clipping + rotation: rotation in degrees, clockwise from horizontal By default, the text is placed so that: diff --git a/arcade/texture/generate.py b/arcade/texture/generate.py index cdd1b6c304..af98ce7dc3 100644 --- a/arcade/texture/generate.py +++ b/arcade/texture/generate.py @@ -27,10 +27,10 @@ def make_circle_texture( Diameter of the circle and dimensions of the square :class:`Texture` returned. color: Color of the circle as a :py:class:`~arcade.types.Color` instance a 3 or 4 tuple. - name (optional): + name: A unique name for the texture. If not provided, a name will be generated. This is used for caching and unique identifier for texture atlases. - hit_box_algorithm (optional): + hit_box_algorithm: The hit box algorithm to use for this texture. If not provided, the default hit box algorithm will be used. """ @@ -65,10 +65,10 @@ def make_soft_circle_texture( Alpha value of the circle at its center. outer_alpha: Alpha value of the circle at its edges. - name (optional): + name: A unique name for the texture. If not provided, a name will be generated. This is used for caching and unique identifier for texture atlases. - hit_box_algorithm (optional): + hit_box_algorithm: The hit box algorithm to use for this texture. If not provided, the default hit box algorithm will be used. """ @@ -125,7 +125,7 @@ def make_soft_square_texture( Alpha value of the square at its center. outer_alpha: Alpha value of the square at its edges. - name (optional): + name: A unique name for the texture. If not provided, a name will be generated. This is used for caching and unique identifier for texture atlases. """ diff --git a/arcade/texture/loading.py b/arcade/texture/loading.py index 5c56d5c5e9..a100929077 100644 --- a/arcade/texture/loading.py +++ b/arcade/texture/loading.py @@ -41,7 +41,7 @@ def load_texture( Args: file_path: Path to the image file - hit_box_algorithm (optional): + hit_box_algorithm: The hit box algorithm to use for this texture. If not specified the global default will be used. hash: diff --git a/arcade/texture/manager.py b/arcade/texture/manager.py index 40f5477a1b..b72f76dc57 100644 --- a/arcade/texture/manager.py +++ b/arcade/texture/manager.py @@ -143,7 +143,7 @@ def load_or_get_spritesheet_texture( Path to the sprite sheet image rect: Slice of the texture in the sprite sheet. - hit_box_algorithm (optional): + hit_box_algorithm: Hit box algorithm to use. If not specified, the global default will be used. """ real_path = self._get_real_path(path) @@ -216,15 +216,15 @@ def load_or_get_texture( Args: file_path: Path to the image file. - x (optional): + x: X coordinate of the texture in the image. - y (optional): + y: Y coordinate of the texture in the image. - width (optional): + width: Width of the texture in the image. - height (optional): + height: Height of the texture in the image. - hit_box_algorithm (optional): + hit_box_algorithm: The hit box algorithm to use for this texture. If not specified, the global default will be used. """ diff --git a/arcade/texture/spritesheet.py b/arcade/texture/spritesheet.py index 33772895d5..cd432e29f9 100644 --- a/arcade/texture/spritesheet.py +++ b/arcade/texture/spritesheet.py @@ -28,8 +28,8 @@ class SpriteSheet: (0, 0) in the upper left corner. This matches the coordinate system used by PIL. Args: - path (optional) Path to the image to load. - image (optional): PIL image to use. + path Path to the image to load. + image: PIL image to use. """ def __init__( diff --git a/arcade/texture/texture.py b/arcade/texture/texture.py index df3f11cabb..4919e9cd50 100644 --- a/arcade/texture/texture.py +++ b/arcade/texture/texture.py @@ -436,9 +436,9 @@ def create_empty( and uniqueness in texture atlases. size: The xy size of the internal image - color (optional): + color: The color to fill the texture with - hit_box_points (optional): + hit_box_points: A list of hitbox points for the texture """ return Texture( diff --git a/arcade/texture_atlas/atlas_default.py b/arcade/texture_atlas/atlas_default.py index b61aa2ae43..8223063939 100644 --- a/arcade/texture_atlas/atlas_default.py +++ b/arcade/texture_atlas/atlas_default.py @@ -87,11 +87,11 @@ class DefaultTextureAtlas(TextureAtlasBase): The number of edge pixels to repeat around images in the atlas. This kind of padding is important to avoid edge artifacts. Default is 1 pixel. - textures (optional): + textures: Optional sequence of textures to add to the atlas on creation auto_resize: Automatically resize the atlas when full. Default is ``True``. - ctx (optional): + ctx: The context for this atlas (will use window context if left empty) capacity: The number of textures the atlas keeps track of. diff --git a/arcade/texture_atlas/region.py b/arcade/texture_atlas/region.py index bec593a587..8b14eebb49 100644 --- a/arcade/texture_atlas/region.py +++ b/arcade/texture_atlas/region.py @@ -48,7 +48,7 @@ class AtlasRegion: The width of the texture in pixels height: The height of the texture in pixels - texture_coordinates (optional): + texture_coordinates: The texture coordinates for this region. If not provided, they will be calculated. """ From d823d498454ef3d32b864628626c0eae3dc9378e Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Thu, 20 Mar 2025 18:25:57 +0100 Subject: [PATCH 10/15] Camera fixes --- arcade/camera/data_types.py | 9 ++++----- arcade/camera/perspective.py | 4 ++-- pyproject.toml | 7 ++----- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/arcade/camera/data_types.py b/arcade/camera/data_types.py index 32b2219a34..2291c4f564 100644 --- a/arcade/camera/data_types.py +++ b/arcade/camera/data_types.py @@ -417,15 +417,14 @@ def use(self) -> None: :py:attr:`~arcade.Window.current_camera` to this object #. Calculate any required view and projection matrices #. Set any resulting values on the current - :py:class:`~arcade.context.ArcadeContext`, including the: + :py:class:`~arcade.ArcadeContext`, including the: - * :py:attr:`~arcade.context.ArcadeContext.viewport` - * :py:attr:`~arcade.context.ArcadeContext.view_matrix` - * :py:attr:`~arcade.context.ArcadeContext.projection_matrix` + * :py:attr:`~arcade.ArcadeContext.viewport` + * :py:attr:`~arcade.ArcadeContext.view_matrix` + * :py:attr:`~arcade.ArcadeContext.projection_matrix` This method should **never** handle cleanup. That is the responsibility of :py:attr:`.activate`. - """ ... diff --git a/arcade/camera/perspective.py b/arcade/camera/perspective.py index 3d3bf336e7..e9567aac3d 100644 --- a/arcade/camera/perspective.py +++ b/arcade/camera/perspective.py @@ -108,7 +108,7 @@ def generate_projection_matrix(self) -> Mat4: """Generates a projection matrix. This is an alias of - :py:class:`arcade.camera.get_perspective_matrix`. + :py:meth:`generate_perspective_matrix`. """ return generate_perspective_matrix(self._projection, self._view.zoom) @@ -116,7 +116,7 @@ def generate_view_matrix(self) -> Mat4: """Generates a view matrix. This is an alias of= - :py:class:`arcade.camera.get_view_matrix`. + :py:meth:`generate_view_matrix`. """ return generate_view_matrix(self._view) diff --git a/pyproject.toml b/pyproject.toml index a91a8f59aa..0c9d917f0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ - "pyglet~=2.1.0", + "pyglet~=2.1.3", "pillow~=11.0.0", "pymunk~=6.9.0", "pytiled-parser~=2.2.9", @@ -113,10 +113,7 @@ lint.select = [ [tool.ruff.format] docstring-code-format = false -exclude = [ - "arcade/examples/*", - "benchmarks/*", -] +exclude = ["arcade/examples/*", "benchmarks/*"] # This ignores __init__.py files and examples for import sorting [tool.ruff.lint.per-file-ignores] From 78739d8f8c432c31aba1fb4ae6197777e96ce244 Mon Sep 17 00:00:00 2001 From: pushfoo <36696816+pushfoo@users.noreply.github.com> Date: Sat, 22 Mar 2025 05:05:02 -0400 Subject: [PATCH 11/15] Fix a loose reference to pyglet.math.Vec3 by prefixing the full path --- arcade/camera/perspective.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcade/camera/perspective.py b/arcade/camera/perspective.py index e9567aac3d..0e1b26a83f 100644 --- a/arcade/camera/perspective.py +++ b/arcade/camera/perspective.py @@ -171,7 +171,7 @@ def project(self, world_coordinate: Point) -> Vec2: """Convert world coordinates to pixel screen coordinates. If a 2D :py:class:`~pyglet.math.Vec2` is provided instead of a 3D - :py:class:`Vec3`, then one will be calculated to the best of the + :py:class:`~pyglet.math.Vec3`, then one will be calculated to the best of the method's ability. Args: From de8dcf06b4b32595cb47d9839ea8ce2dc16a0eb1 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 23 Mar 2025 11:59:44 +0100 Subject: [PATCH 12/15] More doc fixes --- arcade/camera/camera_2d.py | 21 +++++++++++---------- arcade/shape_list.py | 3 +++ arcade/utils.py | 2 +- doc/example_code/shape_list_demo.rst | 2 +- doc/example_code/sprite_move_scrolling.rst | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/arcade/camera/camera_2d.py b/arcade/camera/camera_2d.py index 5aefd360a7..d0b048a9b4 100644 --- a/arcade/camera/camera_2d.py +++ b/arcade/camera/camera_2d.py @@ -197,10 +197,10 @@ def from_camera_data( Args: camera_data: - A :py:class:`~arcade.camera.data.CameraData` + A :py:class:`~arcade.camera.CameraData` describing the position, up, forward and zoom. projection_data: - A :py:class:`~arcade.camera.data.OrthographicProjectionData` + A :py:class:`~arcade.camera.OrthographicProjectionData` which describes the left, right, top, bottom, far, near planes and the viewport for an orthographic projection. render_target: @@ -377,10 +377,10 @@ def match_target( Sets the viewport to the size of the Camera2D's render target. Args: - viewport: Flag whether to equalise the viewport to the area of the render target - projection: Flag whether to equalise the size of the projection to - match the render target - The projection center stays fixed, and the new projection matches only in size. + viewport: Flag whether to equalize the viewport to the area of the render target + projection: Flag whether to equalize the size of the projection to + match the render target. + The projection center stays fixed, and the new projection matches only in size. scissor: Flag whether to update the scissor value. position: Flag whether to also center the camera to the value. Off by default @@ -415,14 +415,14 @@ def update_values( aspect: float | None = None, ): """ - Convienence method for updating the viewport, projection, position + Convenience method for updating the viewport, projection, position and a few others with the same value. Args: value: The rect that the values will be derived from. - viewport: Flag whether to equalise the viewport to the value. - projection: Flag whether to equalise the size of the projection to match the value. - The projection center stays fixed, and the new projection matches only in size. + viewport: Flag whether to equalize the viewport to the value. + projection: Flag whether to equalize the size of the projection to match the value. + The projection center stays fixed, and the new projection matches only in size. scissor: Flag whether to update the scissor value. position: Flag whether to also center the camera to the value. Off by default @@ -456,6 +456,7 @@ def update_values( def aabb(self) -> Rect: """ Retrieve the axis-aligned bounds box of the camera's view area. + If the camera isn't rotated , this will be precisely the view area, but it will cover a larger area when it is rotated. Useful for CPU culling """ diff --git a/arcade/shape_list.py b/arcade/shape_list.py index f1ead8cf9b..c1a191b30f 100644 --- a/arcade/shape_list.py +++ b/arcade/shape_list.py @@ -825,6 +825,9 @@ def create_ellipse_filled_with_colors( TShape = TypeVar("TShape", bound=Shape) +""" +Type variable for Shape or subclasses. +""" @copy_dunders_unimplemented diff --git a/arcade/utils.py b/arcade/utils.py index 0785f1a622..490be539fb 100644 --- a/arcade/utils.py +++ b/arcade/utils.py @@ -118,7 +118,7 @@ def is_nonstr_iterable(item: Any) -> bool: you can also pass it as an argument to other functions. These include: * The :py:func:`.grow_sequence` utility function - * Python's built-in :py:func:`filter` + * Python's built-in filter function .. note:: This is the opposite of :py:func:`is_str_or_noniterable`. diff --git a/doc/example_code/shape_list_demo.rst b/doc/example_code/shape_list_demo.rst index ace5b8bb92..0fc3d57b56 100644 --- a/doc/example_code/shape_list_demo.rst +++ b/doc/example_code/shape_list_demo.rst @@ -5,7 +5,7 @@ ShapeElementList Explanation ============================ -If you are drawing a lot of items on your screen, the :class:`arcade.ShapeElementList` can +If you are drawing a lot of items on your screen, the :class:`arcade.shape_list.ShapeElementList` can speed your drawing. How does it work? Say we have a screen with about 9,600 rectangles: diff --git a/doc/example_code/sprite_move_scrolling.rst b/doc/example_code/sprite_move_scrolling.rst index 5034015d42..327a4bbd29 100644 --- a/doc/example_code/sprite_move_scrolling.rst +++ b/doc/example_code/sprite_move_scrolling.rst @@ -5,7 +5,7 @@ Move with a Scrolling Screen - Centered ======================================= -Using a :class:`arcade.Camera`, a program can easily scroll around a larger +Using a :class:`arcade.Camera2D`, a program can easily scroll around a larger "world" while only showing part of it on the screen. If you are displaying a GUI or some other items that should NOT scroll, you'll From e1ad5badccb5e1b80cb5dff27e26c233369aed2a Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 23 Mar 2025 15:18:58 +0100 Subject: [PATCH 13/15] Missing docstrings in camera module --- arcade/camera/projection_functions.py | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arcade/camera/projection_functions.py b/arcade/camera/projection_functions.py index 2745fb90f5..5321b7e21f 100644 --- a/arcade/camera/projection_functions.py +++ b/arcade/camera/projection_functions.py @@ -125,6 +125,15 @@ def project_orthographic( view_matrix: Mat4, projection_matrix: Mat4, ) -> Vec2: + """ + Project a world coordinate to a screen coordinate using an orthographic projection. + + Args: + world_coordinate: The world coordinate to project. + viewport: The viewport of the camera. + view_matrix: The view matrix of the camera. + projection_matrix: The projection matrix of the camera. + """ x, y, *_z = world_coordinate z = 0.0 if not _z else _z[0] @@ -144,6 +153,15 @@ def unproject_orthographic( view_matrix: Mat4, projection_matrix: Mat4, ) -> Vec3: + """ + Unproject a screen coordinate to a world coordinate using an orthographic projection. + + Args: + screen_coordinate: The screen coordinate to unproject. + viewport: The viewport of the camera. + view_matrix: The view matrix of the camera. + projection_matrix: The projection matrix of the camera. + """ x, y, *_z = screen_coordinate z = 0.0 if not _z else _z[0] @@ -165,6 +183,15 @@ def project_perspective( view_matrix: Mat4, projection_matrix: Mat4, ) -> Vec2: + """ + Project a world coordinate to a screen coordinate using a perspective projection. + + Args: + world_coordinate: The world coordinate to project. + viewport: The viewport of the camera. + view_matrix: The view matrix of the camera. + projection_matrix: The projection matrix of the camera. + """ x, y, *_z = world_coordinate z = 1.0 if not _z else _z[0] @@ -188,6 +215,15 @@ def unproject_perspective( view_matrix: Mat4, projection_matrix: Mat4, ) -> Vec3: + """ + Unproject a screen coordinate to a world coordinate using a perspective projection. + + Args: + screen_coordinate: The screen coordinate to unproject. + viewport: The viewport of the camera. + view_matrix: The view matrix of the camera. + projection_matrix: The projection matrix of + """ x, y, *_z = screen_coordinate z = 1.0 if not _z else _z[0] From 6df1b7c8419b5a81b22fee50d6d9a1f4eb2d2cf7 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 23 Mar 2025 15:31:01 +0100 Subject: [PATCH 14/15] More fixes --- doc/programming_guide/camera.rst | 2 +- util/update_quick_index.py | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/programming_guide/camera.rst b/doc/programming_guide/camera.rst index 1f8645a5f8..06b837483b 100644 --- a/doc/programming_guide/camera.rst +++ b/doc/programming_guide/camera.rst @@ -15,7 +15,7 @@ equal to one pixel of the sprite's source texture. This does not necessarily equ Screen Space ^^^^^^^^^^^^ The final positions of anything drawn to screen is in screen space. The mouse positions returned by window -events like :py:func:`on_mouse_press` are also in screen space. Moving 1 unit in screen space is equivalent to moving +events like ``on_mouse_press`` are also in screen space. Moving 1 unit in screen space is equivalent to moving one pixel. Often positions in screen space are integer values, but this is not a strict rule. View Matrices diff --git a/util/update_quick_index.py b/util/update_quick_index.py index 1dca8953bb..8f4b41b8d6 100644 --- a/util/update_quick_index.py +++ b/util/update_quick_index.py @@ -551,6 +551,14 @@ def iter_declarations( for name in filter(member_not_excluded, kind_list): yield name, IMPORT_TREE.resolve(f"{module_name}.{name}") + # # Attributes + # for name, full_name in iter_declarations('type'): + # quick_index_file.write(f" * - :py:attr:`{full_name}`\n") + # quick_index_file.write(f" - {title}\n") + + # api_file.write(f".. autodata:: {full_name}\n") + # api_file.write("\n") + # Classes for name, full_name in iter_declarations('class'): quick_index_file.write(f" * - :py:class:`{full_name}`\n") From f17d920904e8b7229ffe42a2f1092bba301f8ec5 Mon Sep 17 00:00:00 2001 From: Einar Forselv Date: Sun, 23 Mar 2025 15:31:42 +0100 Subject: [PATCH 15/15] Disable nitpicky --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 61c6333c51..03f5320b39 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -256,7 +256,7 @@ def run_util(filename, run_name="__main__", init_globals=None): # Warn about all references where the target cannot be found. # This is important to always enable to catch broken doc or api links -nitpicky = True +# nitpicky = True # -- Options for HTML output ----------------------------------------------