Skip to content
Merged
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
44 changes: 44 additions & 0 deletions crates/processing_input/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,47 @@ pub fn input_key() -> error::Result<Option<char>> {
pub fn input_key_code() -> error::Result<Option<KeyCode>> {
app_mut(|app| Ok(app.world().resource::<LastKey>().code))
}

pub fn input_mouse_any_just_pressed() -> error::Result<bool> {
app_mut(|app| {
Ok(app
.world()
.resource::<ButtonInput<MouseButton>>()
.get_just_pressed()
.next()
.is_some())
})
}

pub fn input_mouse_any_just_released() -> error::Result<bool> {
app_mut(|app| {
Ok(app
.world()
.resource::<ButtonInput<MouseButton>>()
.get_just_released()
.next()
.is_some())
})
}

pub fn input_key_any_just_pressed() -> error::Result<bool> {
app_mut(|app| Ok(app.world().resource::<LastKey>().just_pressed))
}

pub fn input_key_any_just_released() -> error::Result<bool> {
app_mut(|app| Ok(app.world().resource::<LastKey>().just_released))
}

pub fn input_mouse_moved() -> error::Result<bool> {
app_mut(|app| {
let d = app.world().resource::<AccumulatedMouseMotion>().delta;
Ok(d.x != 0.0 || d.y != 0.0)
})
}

pub fn input_mouse_scrolled() -> error::Result<bool> {
app_mut(|app| {
let d = app.world().resource::<AccumulatedMouseScroll>().delta;
Ok(d.x != 0.0 || d.y != 0.0)
})
}
24 changes: 17 additions & 7 deletions crates/processing_input/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ impl CursorPosition {
pub struct LastKey {
pub code: Option<KeyCode>,
pub character: Option<char>,
pub just_pressed: bool,
pub just_released: bool,
}

#[derive(Resource, Default)]
Expand All @@ -51,13 +53,21 @@ pub fn track_cursor_position(
}

pub fn track_last_key(mut reader: MessageReader<KeyboardInput>, mut last: ResMut<LastKey>) {
if let Some(event) = reader
.read()
.filter(|e| e.state == ButtonState::Pressed)
.last()
{
last.code = Some(event.key_code);
last.character = event.text.as_ref().and_then(|t| t.chars().next());
// our cbs fire on key auto repeats but bevy just_pressed only fires on the initial press
// we track edge state off of the raw input stream
last.just_pressed = false;
last.just_released = false;
for event in reader.read() {
match event.state {
ButtonState::Pressed => {
last.code = Some(event.key_code);
last.character = event.text.as_ref().and_then(|t| t.chars().next());
last.just_pressed = true;
}
ButtonState::Released => {
last.just_released = true;
}
}
}
}

Expand Down
64 changes: 63 additions & 1 deletion crates/processing_pyo3/mewnala/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,66 @@
_sub = getattr(_native, _name, None)
if _sub is not None:
_sys.modules[f"{__name__}.{_name}"] = _sub
del _sys, _native, _name, _sub

# global var handling. for wildcard import of our module, we copy into globals, otherwise
# we dispatch to get attr and call the underlying getter method

_DYNAMIC_GRAPHICS_ATTRS = (
"width",
"height",
"focused",
"pixel_width",
"pixel_height",
"pixel_density",
)
_DYNAMIC_FUNCTIONS = (
"mouse_x",
"mouse_y",
"pmouse_x",
"pmouse_y",
"frame_count",
"delta_time",
"elapsed_time",
)
_DYNAMIC = (
_DYNAMIC_GRAPHICS_ATTRS + _DYNAMIC_FUNCTIONS + (
"mouse_is_pressed",
"mouse_button",
"moved_x",
"moved_y",
"mouse_wheel",
"key",
"key_code",
"key_is_pressed",
"display_width",
"display_height",
Comment thread
tychedelia marked this conversation as resolved.
)
)


def _get_graphics():
return getattr(_native, "_graphics", None)


def __getattr__(name):
if name in _DYNAMIC_GRAPHICS_ATTRS:
g = _get_graphics()
if g is not None:
return getattr(g, name)
if name in _DYNAMIC_FUNCTIONS:
fn = getattr(_native, name, None)
if callable(fn):
return fn()
if name in ("display_width", "display_height"):
mon = getattr(_native, "primary_monitor", lambda: None)()
if mon is None:
return 0
return mon.width if name == "display_width" else mon.height
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


def __dir__():
return sorted(set(list(globals().keys()) + list(_DYNAMIC)))


del _sys, _name, _sub
63 changes: 29 additions & 34 deletions crates/processing_pyo3/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,40 +132,7 @@ impl PyBlendMode {
const OP_MAX: u8 = 4;
}

#[pyclass(unsendable)]
pub struct Surface {
pub(crate) entity: Entity,
glfw_ctx: Option<GlfwContext>,
}

#[pymethods]
impl Surface {
pub fn poll_events(&mut self) -> bool {
match &mut self.glfw_ctx {
Some(ctx) => ctx.poll_events(),
None => true, // no-op, offscreen surfaces never close
}
}

#[getter]
pub fn display_density(&self) -> PyResult<f32> {
match &self.glfw_ctx {
Some(ctx) => Ok(ctx.content_scale()),
None => Ok(1.0),
}
}

pub fn set_pixel_density(&self, density: f32) -> PyResult<()> {
surface_set_pixel_density(self.entity, density)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}
}

impl Drop for Surface {
fn drop(&mut self) {
let _ = surface_destroy(self.entity);
}
}
pub use crate::surface::Surface;

#[pyclass]
#[derive(Debug)]
Expand Down Expand Up @@ -318,6 +285,10 @@ impl Geometry {
pub struct Graphics {
pub(crate) entity: Entity,
pub surface: Surface,
#[pyo3(get)]
pub width: u32,
#[pyo3(get)]
pub height: u32,
}

impl Drop for Graphics {
Expand Down Expand Up @@ -364,6 +335,8 @@ impl Graphics {
Ok(Self {
entity: graphics,
surface,
width,
height,
})
}

Expand Down Expand Up @@ -399,9 +372,31 @@ impl Graphics {
Ok(Self {
entity: graphics,
surface,
width,
height,
})
}

#[getter]
pub fn focused(&self) -> PyResult<bool> {
self.surface.focused()
}

#[getter]
pub fn pixel_density(&self) -> PyResult<f32> {
self.surface.pixel_density()
}

#[getter]
pub fn pixel_width(&self) -> PyResult<u32> {
self.surface.pixel_width()
}

#[getter]
pub fn pixel_height(&self) -> PyResult<u32> {
self.surface.pixel_height()
}

pub fn readback_png(&self) -> PyResult<Vec<u8>> {
let raw = graphics_readback_raw(self.entity)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
Expand Down
28 changes: 14 additions & 14 deletions crates/processing_pyo3/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,20 @@ pub fn key_code() -> PyResult<Option<u32>> {
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn sync_globals(func: &Bound<'_, PyAny>, surface: Entity) -> PyResult<()> {
let globals = func.getattr("__globals__")?;
globals.set_item("mouse_x", mouse_x(surface)?)?;
globals.set_item("mouse_y", mouse_y(surface)?)?;
globals.set_item("pmouse_x", pmouse_x(surface)?)?;
globals.set_item("pmouse_y", pmouse_y(surface)?)?;
globals.set_item("mouse_is_pressed", mouse_is_pressed()?)?;
globals.set_item("mouse_button", mouse_button()?)?;
globals.set_item("moved_x", moved_x()?)?;
globals.set_item("moved_y", moved_y()?)?;
globals.set_item("mouse_wheel", mouse_wheel()?)?;
globals.set_item("key", key()?)?;
globals.set_item("key_code", key_code()?)?;
globals.set_item("key_is_pressed", key_is_pressed()?)?;
pub fn sync_globals(globals: &Bound<'_, PyAny>, surface: Entity) -> PyResult<()> {
use crate::set_tracked;
set_tracked(globals, "mouse_x", mouse_x(surface)?)?;
set_tracked(globals, "mouse_y", mouse_y(surface)?)?;
set_tracked(globals, "pmouse_x", pmouse_x(surface)?)?;
set_tracked(globals, "pmouse_y", pmouse_y(surface)?)?;
set_tracked(globals, "mouse_is_pressed", mouse_is_pressed()?)?;
set_tracked(globals, "mouse_button", mouse_button()?)?;
set_tracked(globals, "moved_x", moved_x()?)?;
set_tracked(globals, "moved_y", moved_y()?)?;
set_tracked(globals, "mouse_wheel", mouse_wheel()?)?;
set_tracked(globals, "key", key()?)?;
set_tracked(globals, "key_code", key_code()?)?;
set_tracked(globals, "key_is_pressed", key_is_pressed()?)?;
Ok(())
}

Expand Down
Loading
Loading