Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ workspace = true
default = ["wayland"]
wayland = ["processing_render/wayland"]
x11 = ["processing_render/x11"]
python = ["processing_render/python"]

[workspace]
resolver = "3"
Expand Down
2 changes: 1 addition & 1 deletion crates/processing_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod error;
#[unsafe(no_mangle)]
pub extern "C" fn processing_init() {
error::clear_error();
error::check(init);
error::check(|| init(None));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll eventually need to accept configuration over FFI

}

/// Create a WebGPU surface from a macOS NSWindow handle.
Expand Down
2 changes: 1 addition & 1 deletion crates/processing_pyo3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ x11 = ["processing/x11"]

[dependencies]
pyo3 = "0.27.0"
processing = { workspace = true }
processing = { workspace = true, features = ["python"] }
bevy = { workspace = true }
glfw = { version = "0.60.0"}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions crates/processing_pyo3/examples/background_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from processing import *

def setup():
size(800, 600)

def draw():
background(220)
image("images/logo.png")


# TODO: this should happen implicitly on module load somehow
run()
12 changes: 10 additions & 2 deletions crates/processing_pyo3/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ impl Drop for Graphics {
#[pymethods]
impl Graphics {
#[new]
pub fn new(width: u32, height: u32) -> PyResult<Self> {
pub fn new(width: u32, height: u32, asset_path: &str) -> PyResult<Self> {
let glfw_ctx =
GlfwContext::new(width, height).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;

init().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
let mut config = Config::new();
config.set(ConfigKey::AssetRootPath, asset_path.to_string());
init(Some(config)).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;

let surface = glfw_ctx
.create_surface(width, height, 1.0)
Expand Down Expand Up @@ -122,6 +124,12 @@ impl Graphics {
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn image(&self, file: &str) -> PyResult<()> {
let image = image_load(file).unwrap();
graphics_record_command(self.entity, DrawCommand::BackgroundImage(image))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn push_matrix(&self) -> PyResult<()> {
graphics_record_command(self.entity, DrawCommand::PushMatrix)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
Expand Down
46 changes: 33 additions & 13 deletions crates/processing_pyo3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! receiver.
//!
//! To allow Python users to create a similar experience, we provide module-level
//! functions that forward to a singleton Graphics object bepub(crate) pub(crate) hind the scenes.
//! functions that forward to a singleton Graphics object pub(crate) behind the scenes.
mod glfw;
mod graphics;

Expand All @@ -16,23 +16,37 @@ use pyo3::{exceptions::PyRuntimeError, prelude::*};

#[pymodule]
fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Graphics>()?;
m.add_function(wrap_pyfunction!(size, m)?)?;
m.add_function(wrap_pyfunction!(run, m)?)?;
m.add_function(wrap_pyfunction!(background, m)?)?;
m.add_function(wrap_pyfunction!(fill, m)?)?;
m.add_function(wrap_pyfunction!(no_fill, m)?)?;
m.add_function(wrap_pyfunction!(stroke, m)?)?;
m.add_function(wrap_pyfunction!(no_stroke, m)?)?;
m.add_function(wrap_pyfunction!(stroke_weight, m)?)?;
m.add_function(wrap_pyfunction!(rect, m)?)?;
Ok(())
Python::attach(|py| {
let sys = PyModule::import(py, "sys")?;
let argv: Vec<String> = sys.getattr("argv")?.extract()?;
let filename: &str = argv[0].as_str();
let os = PyModule::import(py, "os")?;
let path = os.getattr("path")?;
let dirname = path.getattr("dirname")?.call1((filename,))?;
let abspath = path.getattr("abspath")?.call1((dirname,))?;
let abspath = path.getattr("join")?.call1((abspath, "assets"))?;

m.add("_root_dir", abspath)?;
m.add_class::<Graphics>()?;
m.add_function(wrap_pyfunction!(size, m)?)?;
m.add_function(wrap_pyfunction!(run, m)?)?;
m.add_function(wrap_pyfunction!(background, m)?)?;
m.add_function(wrap_pyfunction!(fill, m)?)?;
m.add_function(wrap_pyfunction!(no_fill, m)?)?;
m.add_function(wrap_pyfunction!(stroke, m)?)?;
m.add_function(wrap_pyfunction!(no_stroke, m)?)?;
m.add_function(wrap_pyfunction!(stroke_weight, m)?)?;
m.add_function(wrap_pyfunction!(rect, m)?)?;
m.add_function(wrap_pyfunction!(image, m)?)?;
Ok(())
})
}

#[pyfunction]
#[pyo3(pass_module)]
fn size(module: &Bound<'_, PyModule>, width: u32, height: u32) -> PyResult<()> {
let graphics = Graphics::new(width, height)?;
let asset_path: String = module.getattr("_root_dir")?.extract()?;
let graphics = Graphics::new(width, height, asset_path.as_str())?;
module.setattr("_graphics", graphics)?;
Ok(())
}
Expand Down Expand Up @@ -122,3 +136,9 @@ fn rect(
) -> PyResult<()> {
get_graphics(module)?.rect(x, y, w, h, tl, tr, br, bl)
}

#[pyfunction]
#[pyo3(pass_module, signature = (image_file))]
fn image(module: &Bound<'_, PyModule>, image_file: &str) -> PyResult<()> {
get_graphics(module)?.image(image_file)
}
3 changes: 2 additions & 1 deletion crates/processing_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ workspace = true
default = []
wayland = ["bevy/wayland"]
x11 = ["bevy/x11"]
python = []

[dependencies]
bevy = { workspace = true }
Expand All @@ -32,4 +33,4 @@ windows = { version = "0.58", features = ["Win32_Foundation", "Win32_System_Libr
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
web-sys = { version = "0.3", features = ["Window", "Document", "HtmlCanvasElement"] }
web-sys = { version = "0.3", features = ["Window", "Document", "HtmlCanvasElement"] }
32 changes: 32 additions & 0 deletions crates/processing_render/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! Options object for configuring various aspects of libprocessing.
//!
//! To add a new Config just add a new enum with associated value

use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq)]
pub enum ConfigKey {
AssetRootPath,
}
// TODO: Consider Box<dyn Any> instead of String
pub type ConfigMap = HashMap<ConfigKey, String>;
pub struct Config {
map: ConfigMap,
}

impl Config {
pub fn new() -> Self {
// TODO consider defaults
Config {
map: ConfigMap::new(),
}
}

pub fn get(&self, k: ConfigKey) -> Option<&String> {
self.map.get(&k)
}

pub fn set(&mut self, k: ConfigKey, v: String) {
self.map.insert(k, v);
}
}
5 changes: 5 additions & 0 deletions crates/processing_render/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//! It can be created from raw pixel data, loaded from disk, resized, and read back to CPU memory.
use std::path::PathBuf;

#[cfg(feature = "python")]
use bevy::asset::{AssetPath, io::AssetSourceId};
use bevy::{
asset::{
LoadState, RenderAssetUsages, handle_internal_asset_events, io::embedded::GetAssetServer,
Expand Down Expand Up @@ -138,6 +140,9 @@ pub fn from_handle(
}

pub fn load(In(path): In<PathBuf>, world: &mut World) -> Result<Entity> {
#[cfg(feature = "python")]
let path = AssetPath::from_path_buf(path).with_source(AssetSourceId::from("assets_directory"));

let handle: Handle<bevy::image::Image> = world.get_asset_server().load(path);
while let LoadState::Loading = world.get_asset_server().load_state(&handle) {
world.run_system_once(handle_internal_asset_events).unwrap();
Expand Down
23 changes: 20 additions & 3 deletions crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod config;
pub mod error;
mod graphics;
pub mod image;
Expand All @@ -6,6 +7,10 @@ mod surface;

use std::{cell::RefCell, num::NonZero, path::PathBuf, sync::OnceLock};

use config::*;

#[cfg(feature = "python")]
use bevy::asset::io::AssetSourceBuilder;
#[cfg(not(target_arch = "wasm32"))]
use bevy::log::tracing_subscriber;
use bevy::{
Expand Down Expand Up @@ -202,7 +207,7 @@ pub fn surface_resize(graphics_entity: Entity, width: u32, height: u32) -> error
})
}

fn create_app() -> App {
fn create_app(_config: Config) -> App {
let mut app = App::new();

#[cfg(not(target_arch = "wasm32"))]
Expand All @@ -227,6 +232,15 @@ fn create_app() -> App {
..default()
});

#[cfg(feature = "python")]
{
let asset_path = _config.get(ConfigKey::AssetRootPath).unwrap();
app.register_asset_source(
"assets_directory",
AssetSourceBuilder::platform_default(asset_path, None),
);
}

app.add_plugins(plugins);
app.add_plugins((ImagePlugin, GraphicsPlugin, SurfacePlugin));
app.add_systems(First, (clear_transient_meshes, activate_cameras))
Expand Down Expand Up @@ -257,14 +271,17 @@ fn set_app(app: App) {

/// Initialize the app, if not already initialized. Must be called from the main thread and cannot
/// be called concurrently from multiple threads.
/// asset_path is Optional because only python needs to use it.
#[cfg(not(target_arch = "wasm32"))]
pub fn init() -> error::Result<()> {
pub fn init(config: Option<Config>) -> error::Result<()> {
let config = config.unwrap_or_else(|| Config::new());

setup_tracing()?;
if is_already_init()? {
return Ok(());
}

let mut app = create_app();
let mut app = create_app(config);
app.finish();
app.cleanup();
set_app(app);
Expand Down
2 changes: 1 addition & 1 deletion examples/background_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init()?;
init(None)?;

let width = 400;
let height = 400;
Expand Down
2 changes: 1 addition & 1 deletion examples/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init()?;
init(None)?;

let width = 400;
let height = 400;
Expand Down
2 changes: 1 addition & 1 deletion examples/transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init()?;
init(None)?;

let surface = glfw_ctx.create_surface(400, 400, 1.0)?;
let graphics = graphics_create(surface, 400, 400)?;
Expand Down
2 changes: 1 addition & 1 deletion examples/update_pixels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(100, 100)?;
init()?;
init(None)?;

let width = 100;
let height = 100;
Expand Down
2 changes: 1 addition & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub use bevy::prelude::default;
pub use processing_render::{render::command::DrawCommand, *};
pub use processing_render::{config::*, render::command::DrawCommand, *};
Loading