Skip to content

Commit a2bc93d

Browse files
authored
Merge pull request #6 from hx2A/version01011
release 0.10.1a1
2 parents 7176872 + 9f6024e commit a2bc93d

File tree

17 files changed

+915
-843
lines changed

17 files changed

+915
-843
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Have a comment or question? We'd love to hear from you! The best ways to reach o
7777
* github [discussions](https://github.com/py5coding/py5generator/discussions) and [issues](https://github.com/py5coding/py5generator/issues)
7878
* Mastodon <a rel="me" href="https://fosstodon.org/@py5coding">fosstodon.org/@py5coding</a>
7979
* twitter [@py5coding](https://twitter.com/py5coding)
80-
* [processing foundation discourse](https://discourse.processing.org/)
80+
* [processing foundation discourse](https://discourse.processing.org/c/28)
8181

8282
[processing]: https://github.com/processing/processing4
8383
[jpype]: https://github.com/jpype-project/jpype

py5/__init__.py

Lines changed: 760 additions & 748 deletions
Large diffs are not rendered by default.

py5/jars/py5.jar

1.16 KB
Binary file not shown.

py5/mixins/data.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,6 @@ def load_strings(
141141
) -> list[str]:
142142
"""Load a list of strings from a file or URL.
143143
144-
Underlying Processing method: Sketch.loadStrings
145-
146144
Parameters
147145
----------
148146
@@ -189,8 +187,6 @@ def save_strings(
189187
) -> None:
190188
"""Save a list of strings to a file.
191189
192-
Underlying Processing method: Sketch.saveStrings
193-
194190
Parameters
195191
----------
196192
@@ -229,8 +225,6 @@ def load_bytes(
229225
) -> bytearray:
230226
"""Load byte data from a file or URL.
231227
232-
Underlying Processing method: Sketch.loadBytes
233-
234228
Parameters
235229
----------
236230
@@ -277,8 +271,6 @@ def save_bytes(
277271
) -> None:
278272
"""Save byte data to a file.
279273
280-
Underlying Processing method: Sketch.saveBytes
281-
282274
Parameters
283275
----------
284276
@@ -305,8 +297,6 @@ def save_bytes(
305297
def load_pickle(self, pickle_path: Union[str, Path]) -> Any:
306298
"""Load a pickled Python object from a file.
307299
308-
Underlying Processing method: Sketch.loadPickle
309-
310300
Parameters
311301
----------
312302
@@ -321,7 +311,16 @@ def load_pickle(self, pickle_path: Union[str, Path]) -> Any:
321311
path.
322312
323313
There are security risks associated with Python pickle files. A pickle file can
324-
contain malicious code, so never load a pickle file from an untrusted source."""
314+
contain malicious code, so never load a pickle file from an untrusted source.
315+
316+
When using py5 in imported mode, pickling will not work on objects instantiated
317+
from new classes you have defined yourself on the main sketch file. This applies
318+
to py5's `save_pickle()` and `load_pickle()` methods, as well as the Python's
319+
standard library pickle module methods they depend upon. If you need to pickle
320+
objects from classes you defined, move the class definitions to a different .py
321+
file that you import as a module or import the classes from. Otherwise, you
322+
could also try using module mode if you want to use pickle with your classes and
323+
keep all the sketch code in a single file."""
325324
path = Path(pickle_path)
326325
if not path.is_absolute():
327326
cwd = self.sketch_path()
@@ -338,8 +337,6 @@ def load_pickle(self, pickle_path: Union[str, Path]) -> Any:
338337
def save_pickle(self, obj: Any, filename: Union[str, Path]) -> None:
339338
"""Pickle a Python object to a file.
340339
341-
Underlying Processing method: Sketch.savePickle
342-
343340
Parameters
344341
----------
345342
@@ -356,10 +353,19 @@ def save_pickle(self, obj: Any, filename: Union[str, Path]) -> None:
356353
be saved relative to the current working directory (`sketch_path()`). The saved
357354
file can be reloaded with `load_pickle()`.
358355
359-
Object "pickling" is a method for serializing objects and saving them to a file
360-
for later retrieval. The recreated objects will be clones of the original
356+
Object "pickling" is a technique for serializing objects and saving them to a
357+
file for later retrieval. The recreated objects will be clones of the original
361358
objects. Not all Python objects can be saved to a Python pickle file. This
362-
limitation prevents any py5 object from being pickled."""
359+
limitation prevents any py5 object from being pickled.
360+
361+
When using py5 in imported mode, pickling will not work on objects instantiated
362+
from new classes you have defined yourself on the main sketch file. This applies
363+
to py5's `save_pickle()` and `load_pickle()` methods, as well as the Python's
364+
standard library pickle module methods they depend upon. If you need to pickle
365+
objects from classes you defined, move the class definitions to a different .py
366+
file that you import as a module or import the classes from. Otherwise, you
367+
could also try using module mode if you want to use pickle with your classes and
368+
keep all the sketch code in a single file."""
363369
path = Path(filename)
364370
if not path.is_absolute():
365371
path = self.sketch_path() / filename

py5/mixins/math.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ def constrain(
277277
low: Union[float, npt.NDArray],
278278
high: Union[float, npt.NDArray],
279279
) -> Union[float, npt.NDArray]:
280-
"""Constrains a value to not exceed a maximum and minimum value.
280+
"""Constrains a value between a minimum and maximum value.
281281
282282
Parameters
283283
----------
@@ -286,15 +286,15 @@ def constrain(
286286
the value to constrain
287287
288288
high: Union[float, npt.NDArray]
289-
minimum limit
289+
maximum limit
290290
291291
low: Union[float, npt.NDArray]
292-
maximum limit
292+
minimum limit
293293
294294
Notes
295295
-----
296296
297-
Constrains a value to not exceed a maximum and minimum value."""
297+
Constrains a value between a minimum and maximum value."""
298298
return np.where(amt < low, low, np.where(amt > high, high, amt))
299299

300300
@classmethod
@@ -733,7 +733,7 @@ def floor(cls, value: Union[float, npt.ArrayLike]) -> Union[int, npt.NDArray]:
733733
parameter.
734734
735735
This function makes a call to the numpy `floor()` function."""
736-
return np.floor(value).astype(np.int_)
736+
return np.floor(value).astype(np.int64)
737737

738738
@classmethod
739739
def ceil(cls, value: Union[float, npt.ArrayLike]) -> Union[int, npt.NDArray]:
@@ -753,7 +753,7 @@ def ceil(cls, value: Union[float, npt.ArrayLike]) -> Union[int, npt.NDArray]:
753753
the parameter.
754754
755755
This function makes a call to the numpy `ceil()` function."""
756-
return np.ceil(value).astype(np.int_)
756+
return np.ceil(value).astype(np.int64)
757757

758758
@classmethod
759759
def exp(cls, value: Union[float, npt.ArrayLike]) -> Union[float, npt.NDArray]:

py5/mixins/pixels.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
# *****************************************************************************
2020
from __future__ import annotations
2121

22+
import tempfile
2223
import threading
2324
from io import BytesIO
2425
from pathlib import Path
@@ -30,6 +31,7 @@
3031
from PIL import Image
3132
from PIL.Image import Image as PIL_Image
3233

34+
from .. import bridge
3335
from ..decorators import _hex_converter
3436

3537
_Sketch = jpype.JClass("py5.core.Sketch")
@@ -679,14 +681,36 @@ def save(
679681
if isinstance(self._instance, _Sketch)
680682
else self._instance.parent
681683
)
682-
if not isinstance(filename, BytesIO):
683-
filename = Path(str(sketch_instance.savePath(str(filename))))
684-
self.load_np_pixels()
685-
arr = (
686-
self.np_pixels[:, :, 1:]
687-
if drop_alpha
688-
else np.roll(self.np_pixels, -1, axis=2)
689-
)
684+
if (
685+
isinstance(self._instance, _Sketch)
686+
and bridge.check_run_method_callstack()
687+
and self._py5_bridge.current_running_method not in ["setup", "draw"]
688+
):
689+
if (
690+
drop_alpha
691+
# and not use_thread # ignore use_thread because the alternative is always slower
692+
and format is None
693+
and isinstance((filename_param := Path(str(filename))), (str, Path))
694+
and filename_param.suffix.lower() in [".jpg", ".jpeg", ".png"]
695+
):
696+
self._instance.save(filename)
697+
return
698+
699+
with tempfile.TemporaryDirectory() as td:
700+
temp_filename = Path(td) / "temp.png"
701+
self._instance.save(temp_filename)
702+
arr = np.asarray(Image.open(temp_filename))
703+
if not drop_alpha:
704+
arr = np.dstack([arr, np.full(arr.shape[:2], 255, dtype=np.uint8)])
705+
else:
706+
if not isinstance(filename, BytesIO):
707+
filename = Path(str(sketch_instance.savePath(str(filename))))
708+
self.load_np_pixels()
709+
arr = (
710+
self.np_pixels[:, :, 1:]
711+
if drop_alpha
712+
else np.roll(self.np_pixels, -1, axis=2)
713+
)
690714

691715
if use_thread:
692716

py5/mouseevent.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ def get_count(self) -> int:
125125
126126
Get the number of mouse clicks. This will be 1 for a single mouse click and 2
127127
for a double click. The value can be much higher if the user clicks fast enough.
128+
129+
This method also responds to the mouse wheel. It will be 1 when the mouse wheel
130+
is rotating down and -1 when the mouse wheel is rotating up.
128131
"""
129132
return self._instance.getCount()
130133

py5/reference.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
settings=[0],
2626
setup=[0],
2727
draw=[0],
28+
predraw_update=[0],
2829
pre_draw=[0],
2930
post_draw=[0],
3031
key_pressed=[0, 1],
@@ -246,14 +247,22 @@
246247
(('Sketch', 'save_bytes'), ['(bytes_data: Union[bytes, bytearray], filename: Union[str, Path]) -> None']),
247248
(('Sketch', 'load_pickle'), ['(pickle_path: Union[str, Path]) -> Any']),
248249
(('Sketch', 'save_pickle'), ['(obj: Any, filename: Union[str, Path]) -> None']),
250+
(('Sketch', 'set_println_stream'), ['(println_stream: Any) -> None']),
251+
(('Sketch', 'println'), ['(*args, sep: str = " ", end: str = "\\n", stderr: bool = False) -> None']),
252+
(('Sketch', 'launch_thread'), ['(f: Callable, name: str = None, *, daemon: bool = True, args: tuple = None, kwargs: dict = None, ) -> str']),
253+
(('Sketch', 'launch_promise_thread'), ['(f: Callable, name: str = None, *, daemon: bool = True, args: tuple = None, kwargs: dict = None, ) -> Py5Promise']),
254+
(('Sketch', 'launch_repeating_thread'), ['(f: Callable, name: str = None, *, time_delay: float = 0, daemon: bool = True, args: tuple = None, kwargs: dict = None, ) -> str']),
255+
(('Sketch', 'has_thread'), ['(name: str) -> None']),
256+
(('Sketch', 'join_thread'), ['(name: str, *, timeout: float = None) -> bool']),
257+
(('Sketch', 'stop_thread'), ['(name: str, wait: bool = False) -> None']),
258+
(('Sketch', 'stop_all_threads'), ['(wait: bool = False) -> None']),
259+
(('Sketch', 'list_threads'), ['() -> None']),
249260
(('Sketch', 'load_np_pixels'), ['() -> None']),
250261
(('Sketch', 'update_np_pixels'), ['() -> None']),
251262
(('Sketch', 'set_np_pixels'), ['(array: npt.NDArray[np.uint8], bands: str = "ARGB") -> None']),
252263
(('Sketch', 'get_np_pixels'), ['(*, bands: str = "ARGB", dst: npt.NDArray[np.uint8] = None) -> npt.NDArray[np.uint8]', '(x: int, y: int, w: int, h: int, /, *, bands: str = "ARGB", dst: npt.NDArray[np.uint8] = None, ) -> npt.NDArray[np.uint8]']),
253264
(('Sketch', 'to_pil'), ['() -> PIL_Image', '(x: int, y: int, w: int, h: int, /) -> PIL_Image']),
254265
(('Sketch', 'save'), ['(filename: Union[str, Path, BytesIO], *, format: str = None, drop_alpha: bool = True, use_thread: bool = False, **params, ) -> None']),
255-
(('Sketch', 'set_println_stream'), ['(println_stream: Any) -> None']),
256-
(('Sketch', 'println'), ['(*args, sep: str = " ", end: str = "\\n", stderr: bool = False) -> None']),
257266
(('Sketch', 'hex_color'), ['(color: int) -> str']),
258267
(('Sketch', 'sin'), ['(angle: Union[float, npt.ArrayLike]) -> Union[float, npt.NDArray]']),
259268
(('Sketch', 'cos'), ['(angle: Union[float, npt.ArrayLike]) -> Union[float, npt.NDArray]']),
@@ -284,14 +293,6 @@
284293
(('Sketch', 'random_gaussian'), ['() -> float', '(loc: float, /) -> float', '(loc: float, scale: float, /) -> float']),
285294
(('Sketch', 'noise'), ['(x: Union[float, npt.NDArray], /) -> Union[float, npt.NDArray]', '(x: Union[float, npt.NDArray], y: Union[float, npt.NDArray], /) -> Union[float, npt.NDArray]', '(x: Union[float, npt.NDArray], y: Union[float, npt.NDArray], z: Union[float, npt.NDArray], /, ) -> Union[float, npt.NDArray]']),
286295
(('Sketch', 'os_noise'), ['(x: Union[float, npt.NDArray], y: Union[float, npt.NDArray], /) -> Union[float, npt.NDArray]', '(x: Union[float, npt.NDArray], y: Union[float, npt.NDArray], z: Union[float, npt.NDArray], /, ) -> Union[float, npt.NDArray]', '(x: Union[float, npt.NDArray], y: Union[float, npt.NDArray], z: Union[float, npt.NDArray], w: Union[float, npt.NDArray], /, ) -> Union[float, npt.NDArray]']),
287-
(('Sketch', 'launch_thread'), ['(f: Callable, name: str = None, *, daemon: bool = True, args: tuple = None, kwargs: dict = None, ) -> str']),
288-
(('Sketch', 'launch_promise_thread'), ['(f: Callable, name: str = None, *, daemon: bool = True, args: tuple = None, kwargs: dict = None, ) -> Py5Promise']),
289-
(('Sketch', 'launch_repeating_thread'), ['(f: Callable, name: str = None, *, time_delay: float = 0, daemon: bool = True, args: tuple = None, kwargs: dict = None, ) -> str']),
290-
(('Sketch', 'has_thread'), ['(name: str) -> None']),
291-
(('Sketch', 'join_thread'), ['(name: str, *, timeout: float = None) -> bool']),
292-
(('Sketch', 'stop_thread'), ['(name: str, wait: bool = False) -> None']),
293-
(('Sketch', 'stop_all_threads'), ['(wait: bool = False) -> None']),
294-
(('Sketch', 'list_threads'), ['() -> None']),
295296
(('Sketch', 'sketch_path'), ['() -> Path', '(where: str, /) -> Path']),
296297
(('Sketch', 'hot_reload_draw'), ['(draw: Callable) -> None']),
297298
(('Sketch', 'profile_functions'), ['(function_names: list[str]) -> None']),
@@ -609,8 +610,8 @@
609610
(('Py5Vector', 'normalize'), ['() -> Py5Vector']),
610611
(('Py5Vector', 'set_limit'), ['(max_mag: float) -> Py5Vector']),
611612
(('Py5Vector', 'set_heading'), ['(*heading) -> Py5Vector']),
612-
(('Py5Vector', 'from_heading'), ['(*heading, dtype: int = np.float_) -> Py5Vector']),
613-
(('Py5Vector', 'random'), ['(dim: int, *, dtype: type = np.float_) -> Py5Vector']),
613+
(('Py5Vector', 'from_heading'), ['(*heading, dtype: int = np.float64) -> Py5Vector']),
614+
(('Py5Vector', 'random'), ['(dim: int, *, dtype: type = np.float64) -> Py5Vector']),
614615
(('Py5Vector', 'rotate'), ['(angle: float) -> Py5Vector2D', '(angle: float, dim: Union[int, str]) -> Py5Vector3D']),
615616
(('Py5Vector', 'rotate_around'), ['(angle: float, v: Py5Vector3D) -> Py5Vector3D']),
616617
(('Py5Graphics', 'points'), ['(coordinates: npt.NDArray[np.floating], /) -> None']),
@@ -627,7 +628,7 @@
627628
(('Py5Shape', 'bezier_vertices'), ['(coordinates: npt.NDArray[np.floating], /) -> None']),
628629
(('Py5Shape', 'curve_vertices'), ['(coordinates: npt.NDArray[np.floating], /) -> None']),
629630
(('Py5Shape', 'quadratic_vertices'), ['(coordinates: npt.NDArray[np.floating], /) -> None']),
630-
(('Sketch', 'run_sketch'), ['(block: bool = None, *, py5_options: list[str] = None, sketch_args: list[str] = None, sketch_functions: dict[str, Callable] = None, jclassname: str = None) -> None']),
631+
(('Sketch', 'run_sketch'), ['(block: bool = None, *, py5_options: list[str] = None, sketch_args: list[str] = None, sketch_functions: dict[str, Callable] = None, jclassname: str = None, jclass_params: tuple[Any] = ()) -> None']),
631632
(('Py5Functions', 'create_font_file'), ['(font_name: str, font_size: int, filename: str = None, characters: str = None, pause: bool = True) -> None']),
632633
(('Py5Functions', 'get_current_sketch'), ['() -> Sketch']),
633634
(('Py5Functions', 'reset_py5'), ['(jclassname: str = None) -> bool']),
@@ -649,6 +650,6 @@
649650
(('Py5Tools', 'screenshot'), ['(*, sketch: Sketch = None, hook_post_draw: bool = False) -> PIL_Image']),
650651
(('Py5Tools', 'save_frames'), ['(dirname: str, *, filename: str = "frame_####.png", period: float = 0.0, start: int = None, limit: int = 0, sketch: Sketch = None, hook_post_draw: bool = False, block: bool = False, display_progress: bool = True) -> None']),
651652
(('Py5Tools', 'animated_gif'), ['(filename: str, *, count: int = 0, period: float = 0.0, frame_numbers: Iterable = None, duration: float = 0.0, loop: int = 0, optimize: bool = True, sketch: Sketch = None, hook_post_draw: bool = False, block: bool = False) -> None']),
652-
(('Py5Tools', 'offline_frame_processing'), ['(func: Callable[[npt.NDArray[np.uint8]], None], *, limit: int = 0, period: float = 0.0, batch_size: int = 1, complete_func: Callable[[], None] = None, stop_processing_func: Callable[[], bool] = None, sketch: Sketch = None, hook_post_draw: bool = False, queue_limit: int = None, block: bool = False) -> None']),
653+
(('Py5Tools', 'offline_frame_processing'), ['(func: Callable[[npt.NDArray[np.uint8]], None], *, limit: int = 0, period: float = 0.0, batch_size: int = 1, complete_func: Callable[[], None] = None, stop_processing_func: Callable[[], bool] = None, sketch: Sketch = None, hook_post_draw: bool = False, queue_limit: int = None, block: bool = False, display_progress: bool = True) -> None']),
653654
(('Py5Tools', 'capture_frames'), ['(*, count: float = 0, period: float = 0.0, frame_numbers: Iterable = None, sketch: Sketch = None, hook_post_draw: bool = False, block: bool = False) -> list[PIL_Image]']),
654655
(('Py5Tools', 'sketch_portal'), ['(*, time_limit: float = 0.0, throttle_frame_rate: float = 30, scale: float = 1.0, quality: int = 75, portal_widget: Py5SketchPortal = None, sketch: Sketch = None, hook_post_draw: bool = False) -> None']),])

0 commit comments

Comments
 (0)