Skip to content

Commit

Permalink
release 0.8.0a2
Browse files Browse the repository at this point in the history
  • Loading branch information
hx2A committed May 26, 2022
1 parent 42425dd commit 689e318
Show file tree
Hide file tree
Showing 33 changed files with 1,295 additions and 245 deletions.
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# py5

[![py5 downloads](https://pepy.tech/badge/py5/month)](https://pepy.tech/project/py5)
[![py5 montly downloads](https://pepy.tech/badge/py5/month)](https://pepy.tech/project/py5)

[![Downloads](https://pepy.tech/badge/py5/week)](https://pepy.tech/project/py5)
[![py5 weekly downloads](https://pepy.tech/badge/py5/week)](https://pepy.tech/project/py5)

[![mybinder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/hx2A/py5examples/HEAD?urlpath=lab)
[![mybinder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/py5coding/py5examples/HEAD?urlpath=lab)

py5 is a new version of [**Processing**][processing] for Python 3.8+. It makes the Java [**Processing**][processing] jars available to the CPython interpreter using [**JPype**][jpype]. It can do just about everything [**Processing**][processing] can do, except with Python instead of Java code.
py5 is a new version of [**Processing**][processing] for Python 3.8+. It makes the Java [**Processing**][processing] jars available to the CPython interpreter using [**JPype**][jpype]. It can do just about all of the 2D and 3D drawing [**Processing**][processing] can do, except with Python instead of Java code.

The goal of py5 is to create a new version of Processing that is integrated into the Python ecosystem. Built into the library are thoughtful choices about how to best get py5 to work with other popular Python libraries such as [numpy](https://www.numpy.org/) or [Pillow](https://python-pillow.org/).
The goal of py5 is to create a new version of Processing that is integrated into the Python ecosystem. Built into the library are thoughtful choices about how to best get py5 to work with other popular Python libraries and tools such as [Jupyter](https://jupyter.org/), [numpy](https://www.numpy.org/), and [Pillow](https://python-pillow.org/).

## Simple Example

Expand All @@ -19,14 +19,18 @@ import py5


def setup():
py5.size(200, 200)
py5.size(400, 400)
py5.rect_mode(py5.CENTER)


def draw():
py5.square(py5.mouse_x, py5.mouse_y, 10)


def mouse_clicked():
py5.fill(py5.random_int(255), py5.random_int(255), py5.random_int(255))


py5.run_sketch()
```

Expand All @@ -49,19 +53,19 @@ There are currently four basic ways to use py5. They are:
* **imported mode**: simplified code that omits the `py5.` prefix. This mode is supported by the py5 Jupyter notebook kernel and the `run_sketch` command line utility.
* **static mode**: functionless code to create static images. This mode is supported by the py5bot Jupyter notebook kernel, the `%%py5bot` IPython magic, and the `run_sketch` command line utility.

The documentation website, [https://py5.ixora.io/](https://py5.ixora.io/), is a work in progress. The reference documentation is solid but the how-to's and tutorials are a work in progress.
The documentation website, [https://py5.ixora.io/](https://py5.ixora.io/), is a work in progress. The reference documentation is solid but the how-to's and tutorials are incomplete.

[py5generator][py5_generator_repo] is a meta-programming project that creates the py5 library. To view the actual installed py5 library code, look at the [py5 repository][py5_repo]. All py5 library development is done through py5generator.

## Get In Touch

Have a comment or question? We'd love to hear from you! The best ways to reach out are:

* github [discussions](https://github.com/hx2A/py5generator/discussions) and [issues](https://github.com/hx2A/py5generator/issues)
* github [discussions](https://github.com/py5coding/py5generator/discussions) and [issues](https://github.com/py5coding/py5generator/issues)
* twitter [@py5coding](https://twitter.com/py5coding)
* [processing foundation discourse](https://discourse.processing.org/)

[py5_repo]: https://github.com/hx2A/py5
[py5_generator_repo]: https://github.com/hx2A/py5generator
[py5_repo]: https://github.com/py5coding/py5
[py5_generator_repo]: https://github.com/py5coding/py5generator
[processing]: https://github.com/processing/processing4
[jpype]: https://github.com/jpype-project/jpype
95 changes: 84 additions & 11 deletions py5/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""
from __future__ import annotations

import os
import sys
from pathlib import Path
from io import BytesIO
Expand All @@ -45,6 +46,10 @@
py5_tools.add_jars(str(base_path / 'jars'))
# if the cwd has a jars subdirectory, add that next
py5_tools.add_jars(Path('jars'))
# if the PY5_CLASSPATH environment variable exists, add those jars
if (py5_classpath := os.environ.get('PY5_JARS')):
py5_tools.add_jars(Path(py5_classpath))

try:
py5_tools.jvm._start_jvm()
started_jvm = True
Expand All @@ -67,7 +72,7 @@
raise RuntimeError("py5 is unable to start Java 17 Virtual Machine")

from .methods import register_exception_msg # noqa
from .sketch import Sketch, Py5Surface, Py5Graphics, Py5Image, Py5Shader, Py5Shape, Py5Font, Py5Promise # noqa
from .sketch import Sketch, Py5Surface, Py5Graphics, Py5Image, Py5Shader, Py5Shape, Py5Font, Py5KeyEvent, Py5MouseEvent, Py5Promise # noqa
from .render_helper import render_frame, render_frame_sequence, render, render_sequence # noqa
from .create_font_tool import create_font_file # noqa
from .image_conversion import register_image_conversion, NumpyImageArray # noqa
Expand All @@ -82,7 +87,7 @@
pass


__version__ = '0.7.2a0'
__version__ = '0.8.0a2'

_PY5_USE_IMPORTED_MODE = py5_tools.get_imported_mode()

Expand Down Expand Up @@ -297,6 +302,13 @@
pixel_width: int = None
pmouse_x: int = None
pmouse_y: int = None
ratio_left: float = None
ratio_scale: float = None
ratio_top: float = None
rheight: int = None
rmouse_x: int = None
rmouse_y: int = None
rwidth: int = None
width: int = None
window_x: int = None
window_y: int = None
Expand Down Expand Up @@ -3499,6 +3511,24 @@ def circle(x: float, y: float, extent: float, /) -> None:
return _py5sketch.circle(x, y, extent)


def clear() -> None:
"""Clear the drawing surface by setting every pixel to black.

Underlying Processing method: Sketch.clear

Notes
-----

Clear the drawing surface by setting every pixel to black. Calling this method
is the same as passing ``0`` to the ``background()`` method, as in
``background(0)``.

This method behaves differently than ``Py5Graphics.clear()`` because
``Py5Graphics`` objects allow transparent pixels.
"""
return _py5sketch.clear()


def clip(a: float, b: float, c: float, d: float, /) -> None:
"""Limits the rendering to the boundaries of a rectangle defined by the parameters.

Expand Down Expand Up @@ -17014,6 +17044,52 @@ def window_move(x: int, y: int, /) -> None:
return _py5sketch.window_move(x, y)


def window_ratio(wide: int, high: int, /) -> None:
"""Set a window ratio to enable scale invariant drawing.

Underlying Processing method: Sketch.windowRatio

Parameters
----------

high: int
height of scale invariant display window

wide: int
width of scale invariant display window

Notes
-----

Set a window ratio to enable scale invariant drawing. If the Sketch window is
resizable, drawing in a consistent way can be challenging as the window changes
size. This method activates some transformations to let the user draw to the
window in a way that will be consistent for all window sizes.

The usefulness of this feature is demonstrated in the example code. The size of
the text will change as the window changes size. Observe the example makes two
calls to ``text_size()`` with fixed values of ``200`` and ``100``. Without this
feature, calculating the appropriate text size for all window sizes would be
difficult. Similarly, positioning the text in the same relative location would
also involve several calculations. Using ``window_ratio()`` makes resizable
Sketches that resize well easier to create.

When using this feature, use ``rmouse_x`` and ``rmouse_y`` to get the cursor
coordinates. The transformations involve calls to ``translate()`` and
``scale()``, and the parameters to those methods can be accessed with
``ratio_top``, ``ratio_left``, and ``ratio_scale``. The transformed coordinates
enabled with this feature can be negative for the top and left areas of the
window that do not fit the desired aspect ratio. Experimenting with the example
and seeing how the numbers change will provide more understanding than what can
be explained with words.

When calling this method, it is better to do so with values like
``window_ratio(1280, 720)`` and not ``window_ratio(16, 9)``. The aspect ratio is
the same for both but the latter might result in floating point accuracy issues.
"""
return _py5sketch.window_ratio(wide, high)


def window_resizable(resizable: bool, /) -> None:
"""Set the Sketch window as resizable by the user.

Expand All @@ -17035,7 +17111,7 @@ def window_resizable(resizable: bool, /) -> None:
Changing the window size will clear the drawing canvas. If you do this, the
``width`` and ``height`` variables will change.

This method provides the same funcationality as ``Py5Surface.set_resizable()``
This method provides the same functionality as ``Py5Surface.set_resizable()``
but without the need to interact directly with the ``Py5Surface`` object.
"""
return _py5sketch.window_resizable(resizable)
Expand Down Expand Up @@ -17064,7 +17140,7 @@ def window_resize(new_width: int, new_height: int, /) -> None:
Changing the window size will clear the drawing canvas. If you do this, the
``width`` and ``height`` variables will change.

This method provides the same funcationality as ``Py5Surface.set_size()`` but
This method provides the same functionality as ``Py5Surface.set_size()`` but
without the need to interact directly with the ``Py5Surface`` object.
"""
return _py5sketch.window_resize(new_width, new_height)
Expand All @@ -17087,7 +17163,7 @@ def window_title(title: str, /) -> None:
Set the Sketch window's title. This will typically appear at the window's title
bar. The default window title is "Sketch".

This method provides the same funcationality as ``Py5Surface.set_title()`` but
This method provides the same functionality as ``Py5Surface.set_title()`` but
without the need to interact directly with the ``Py5Surface`` object.
"""
return _py5sketch.window_title(title)
Expand Down Expand Up @@ -20246,12 +20322,8 @@ def run_sketch(block: bool = None, *,
mixed in with the Jupyter Kernel logs."""
caller_globals = inspect.stack()[1].frame.f_globals
caller_locals = inspect.stack()[1].frame.f_locals
if sketch_functions:
functions = dict([(e, sketch_functions[e])
for e in reference.METHODS if e in sketch_functions and callable(sketch_functions[e])])
else:
functions = dict([(e, caller_locals[e])
for e in reference.METHODS if e in caller_locals and callable(caller_locals[e])])
functions, function_param_counts = methods._extract_py5_user_function_data(
sketch_functions if sketch_functions else caller_locals)
functions = _split_setup.transform(
functions,
caller_globals,
Expand All @@ -20278,6 +20350,7 @@ def run_sketch(block: bool = None, *,

_py5sketch._run_sketch(
functions,
function_param_counts,
block,
py5_options,
sketch_args,
Expand Down
Binary file modified py5/jars/core.jar
Binary file not shown.
Binary file modified py5/jars/dxf/dxf.jar
Binary file not shown.
Binary file modified py5/jars/pdf/pdf.jar
Binary file not shown.
Binary file modified py5/jars/py5.jar
Binary file not shown.
Binary file modified py5/jars/svg/svg.jar
Binary file not shown.
57 changes: 44 additions & 13 deletions py5/java_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,47 @@
#
# *****************************************************************************
import numpy as np
from jpype import _jcustomizer
from jpype import JClass, JArray, _jcustomizer

from .sketch import Sketch, Py5Graphics, Py5Image, Py5Font, Py5Shape, Py5Shader
from .sketch import Sketch, Py5Graphics, Py5Image, Py5Font, Py5Shape, Py5Shader, Py5KeyEvent, Py5MouseEvent
from .pmath import _py5vector_to_pvector_converter, _numpy_to_pvector_converter, _numpy_to_pmatrix_converter
from .vector import Py5Vector


JCONVERSION_CLASS_MAP = [
("processing.core.PImage", Py5Image),
("processing.core.PImage", Py5Graphics),
("processing.core.PGraphics", Py5Graphics),
("processing.core.PFont", Py5Font),
("processing.core.PShape", Py5Shape),
("processing.opengl.PShader", Py5Shader),
("processing.event.Event", Py5KeyEvent),
("processing.event.KeyEvent", Py5KeyEvent),
("processing.event.Event", Py5MouseEvent),
("processing.event.MouseEvent", Py5MouseEvent),
("processing.core.PApplet", Sketch),
("py5.core.Sketch", Sketch),
]

PROCESSING_TO_PY5_CLASS_MAP = [
(JClass("processing.core.PImage"), Py5Image),
(JClass("processing.core.PGraphics"), Py5Graphics),
(JClass("processing.core.PFont"), Py5Font),
(JClass("processing.core.PShape"), Py5Shape),
(JClass("processing.opengl.PShader"), Py5Shader),
(JClass("processing.event.KeyEvent"), Py5KeyEvent),
(JClass("processing.event.MouseEvent"), Py5MouseEvent),
# TODO: this won't work for Sketch. should it?
# (JClass("py5.core.Sketch"), Sketch),
]


def init_jpype_converters():
data = [
("processing.core.PImage", Py5Image),
("processing.core.PImage", Py5Graphics),
("processing.core.PGraphics", Py5Graphics),
("processing.core.PFont", Py5Font),
("processing.core.PShape", Py5Shape),
("processing.opengl.PShader", Py5Shader),
("processing.core.PApplet", Sketch),
("py5.core.Sketch", Sketch),
]

def convert(jcls, obj):
return obj._instance

for javaname, cls_ in data:
for javaname, cls_ in JCONVERSION_CLASS_MAP:
_jcustomizer.JConversion(javaname, cls_)(convert)

_jcustomizer.JConversion(
Expand All @@ -52,3 +70,16 @@ def convert(jcls, obj):
_jcustomizer.JConversion(
'processing.core.PMatrix',
np.ndarray)(_numpy_to_pmatrix_converter)


def convert_to_python_types(params):
for p in params:
for jclass, py5class in PROCESSING_TO_PY5_CLASS_MAP:
if isinstance(p, jclass):
yield py5class(p)
break
else:
if isinstance(p, JArray):
yield np.asarray(p)
else:
yield p
Loading

0 comments on commit 689e318

Please sign in to comment.