██ ████ ██ ██ ███ ██ ███ ██ ██ ██ ██ ██ ██ `rx` is a modern and minimalist pixel editor. Designed with great care and love with pixel artists and animators in mind. OVERVIEW `rx` is an extensible, modern and minimalist pixel editor implemented in rust[0]. rx is free software, licensed under the GPLv3. Most of the information on how to use rx is on the website: https://rx.cloudhead.io. There, you can also find a user guide (https://rx.cloudhead.io/guide.html), installation instructions, and binary download links. To build rx from source, see the build sections below. Once inside rx, enter the `:help` command to get a list of key bindings and commands. [0]: https://rust-lang.org REQUIREMENTS At a minimum, OpenGL 3.3 support is required. BUILD DEPENDENCIES * rust (https://www.rust-lang.org/tools/install) * cmake (https://cmake.org/download/) On macOS, `Xcode` and the `Xcode Command Line Tools` are required. The latter can be obtained by running `xcode-select --install` CMake can be installed with `brew install cmake`. BUILD & INSTALLATION Before proceeding, make sure the BUILD DEPENDENCIES have been installed. Then, clone this repository and from its root, run: $ cargo install --locked --path . This will install rx under `~/.cargo/bin/rx`. If you prefer a different install location, you can specify it via the `--root <prefix>` flag, where <prefix> is for example '/usr/local'. CONTRIBUTING See the CONTRIBUTING file for details. Contributions are appreciated. USAGE See the guide at https://rx.cloudhead.io/guide.html. TROUBLESHOOTING If something isn't working like it's supposed to, there are various things you can do to debug the problem: * Run `rx` with verbose logging, by using the `-v` command-line flag. This will log errors from the underlying libraries that are usually suppressed, and will show debug output that might indicate what the problem is. * If `rx` is crashing, run it with `RUST_BACKTRACE=1` set in your environment to show a backtrace on crash. * It could be that the issue is related to your configuration - in that case the program can be run without loading the initialization script like so: rx -u - LICENSE This software is licensed under the GPL. See the LICENSE file for more details. COPYRIGHT (c) 2019 Alexis Sellier
rx — Vi inspired Modern Pixel Art Editor
██ ████ ██ ██ ███ ██ ███ ██ ██ ██ ██ ██ ██ `rx` is a modern and minimalist pixel editor. Designed with gCategory: Rust / Applications |
Watchers: 23 |
Star: 2.7k |
Fork: 102 |
Last update: Mar 16, 2023 |
Related to #18
Windows 10, compiled with 1.38 stable. (--vulkan
feature flag)
rx does not go into command mode when writing :
using a Swedish/Nordic keyboard layout (Shift + Period) and instead zooms in one level.
It seems to recieve a colon in the RecievedCharacter
event, but the KeyboardInput
contains a period.
Logs:
[2019-09-30T13:57:01Z DEBUG rx] event: KeyboardInput(KeyboardInput { state: Pressed, key: Some(Shift), modifiers: ModifiersState { shift: true, ctrl: false, alt: false, meta: false } })
[2019-09-30T13:57:01Z DEBUG rx::session] KeyboardInput { state: Pressed, key: Some(Shift), modifiers: ModifiersState { shift: true, ctrl: false, alt: false, meta: false } }
[2019-09-30T13:57:01Z DEBUG rx::session] command: BrushSet(Multi)
[2019-09-30T13:57:02Z DEBUG rx] event: KeyboardInput(KeyboardInput { state: Pressed, key: Some(Period), modifiers: ModifiersState { shift: true, ctrl: false, alt: false, meta: false } })
[2019-09-30T13:57:02Z DEBUG rx] event: ReceivedCharacter(':')
[2019-09-30T13:57:02Z DEBUG rx::session] KeyboardInput { state: Pressed, key: Some(Period), modifiers: ModifiersState { shift: true, ctrl: false, alt: false, meta: false } }
[2019-09-30T13:57:02Z DEBUG rx::session] command: Zoom(Incr)
[2019-09-30T13:57:02Z DEBUG rx::session] zoom: 1 -> 2
[2019-09-30T13:57:02Z DEBUG rx] event: KeyboardInput(KeyboardInput { state: Released, key: Some(Period), modifiers: ModifiersState { shift: true, ctrl: false, alt: false, meta: false } })
[2019-09-30T13:57:02Z DEBUG rx::session] KeyboardInput { state: Released, key: Some(Period), modifiers: ModifiersState { shift: true, ctrl: false, alt: false, meta: false } }
[2019-09-30T13:57:02Z DEBUG rx] event: KeyboardInput(KeyboardInput { state: Released, key: Some(Shift), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, meta: false } })
[2019-09-30T13:57:02Z DEBUG rx::session] KeyboardInput { state: Released, key: Some(Shift), modifiers: ModifiersState { shift: false, ctrl: false, alt: false, meta: false } }
[2019-09-30T13:57:02Z DEBUG rx::session] command: BrushUnset(Multi)
Full copying and pasting ability would be very useful ofc and I'm sure it's on the roadmap, but in the meantime two features would help a lot with the animation process:
- Frame cloning: add a new frame at the end (or even in the middle) with contents copied from another frame. Maybe a
f/clone
command with frame index? - Synchronous editing: propagate edits in a single frame to one or more other frames.
Maybe I can add the features myself and open some PRs if you like the idea? Let me know. Thank you for building and sharing this project, looks really promising and it's pleasing to use.
Cloning master and building with cargo install --locked --path .
and running the resulting binary results in a blank window and the following error: GLFW Error: Cocoa: Failed to find service port for display
. Building from the stable branch as on the website using:
cargo install \
--git https://github.com/cloudhead/rx \
--tag v0.4.0
Does not result in this error, the only thing I found related to this issue was the following GLFW issue that was fixed earlier this year: https://github.com/bjornbytes/lovr/pull/357
Hi, this is my humble attempt at implementing the functionality to flip a selection. It was once again a pleasant experience as I really like the structure of the code, but I'm not sure if I'm doing it "idiomatically".
Here is a demonstration of how it looks:
(yea, the colors are screwed because it's a gif, here's a webm for more pleasant viewing -> flip.webm)
This is what I did for these changes:
- create a command
selection/flip
which takes one argument of direction, valid values areh
orhorizontal
andv
orvertical
. - then I created a
ViewOp
for flip and went togl/mod.rs
to create an implementation. It's pretty much a yank, which also takes direction as an argument and then flips the pixels accordingly - In session.rs, I added appropriate functions taking yank as example. To allow possibly doing a bunch of flips with a hotkey, I figured the easiest would be doing it in the place of selection, so I did this:
Command::SelectionFlip(dir) => {
self.flip_selection(dir);
// I think its handy to flip in place for now, hence these commands
// 1., 2. prevent overlap and paste
// 3. preserve location so you can flip repeatedly w/ hotkey
self.command(Command::SelectionErase);
self.command(Command::SelectionPaste);
self.command(Command::Mode(Mode::Visual(VisualState::Selecting { dragging: false })));
}
I'm really unsure if this is the correct way to do it, so I am sorry if I did something wrong, haha :sweat_smile:
thread 'main' panicked at 'No adapters found. Please enable the feature for one of the graphics backends: vulkan, metal, dx12, dx11, gl', src/libcore/option.rs:1166:5
"gl"
cargo install --force --git https://github.com/cloudhead/rx --locked --features gl
Package
rx v0.1.0 (https://github.com/cloudhead/rx#465f95f4)does not have these features:
gl``
cargo install --git https://github.com/cloudhead/rx --locked
△ ~ RUST_BACKTRACE=full rx -u -
[2019-11-17T19:15:33Z INFO rx] framebuffer size: 1280x720
[2019-11-17T19:15:33Z INFO rx] hidpi factor: 2.2999980449676514
[2019-11-17T19:15:33Z INFO rx::session] rx v0.2.0
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
stack backtrace:
0: 0x556f5ce1c524 - backtrace::backtrace::libunwind::trace::hda41dbcdfba36aa0
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/libunwind.rs:88
1: 0x556f5ce1c524 - backtrace::backtrace::trace_unsynchronized::h1a8d6e1f8cb3f5d4
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.37/src/backtrace/mod.rs:66
2: 0x556f5ce1c524 - std::sys_common::backtrace::_print_fmt::h610c4127487e10da
at src/libstd/sys_common/backtrace.rs:76
3: 0x556f5ce1c524 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h0722dc552e01bd1d
at src/libstd/sys_common/backtrace.rs:60
4: 0x556f5ce3d21c - core::fmt::write::h01edf6dd68a42c9c
at src/libcore/fmt/mod.rs:1030
5: 0x556f5ce19087 - std::io::Write::write_fmt::hf15985f193f03c04
at src/libstd/io/mod.rs:1412
6: 0x556f5ce1e7d5 - std::sys_common::backtrace::_print::hd8d5d08a1795e743
at src/libstd/sys_common/backtrace.rs:64
7: 0x556f5ce1e7d5 - std::sys_common::backtrace::print::hf89a79e3921a2366
at src/libstd/sys_common/backtrace.rs:49
8: 0x556f5ce1e7d5 - std::panicking::default_hook::{{closure}}::h3a8f42beb3bb8ae3
at src/libstd/panicking.rs:196
9: 0x556f5ce1e4c6 - std::panicking::default_hook::h8f803b0bc31a5c37
at src/libstd/panicking.rs:210
10: 0x556f5ce1ee75 - std::panicking::rust_panic_with_hook::h825f041245da8739
at src/libstd/panicking.rs:473
11: 0x556f5ce1ea12 - std::panicking::continue_panic_fmt::hbe0378e33481e81b
at src/libstd/panicking.rs:380
12: 0x556f5ce1e906 - rust_begin_unwind
at src/libstd/panicking.rs:307
13: 0x556f5ce3931a - core::panicking::panic_fmt::h527855ce0bc891f6
at src/libcore/panicking.rs:85
14: 0x556f5ce39259 - core::panicking::panic::h2f49f09cf859b728
at src/libcore/panicking.rs:49
15: 0x556f5cd5f86f - wgpu_request_adapter
16: 0x556f5cd5a4b7 - wgpu::Adapter::request::hc06a386463c80c30
17: 0x556f5cc265bc - rx::init::h3fab2ab361ffb234
18: 0x556f5cc343e8 - rx::main::ha967765a9e31cdfc
19: 0x556f5cc1d013 - std::rt::lang_start::{{closure}}::hc4ee2151b7bf7afb
20: 0x556f5ce1e8a3 - std::rt::lang_start_internal::{{closure}}::ha04574f12d97cbe2
at src/libstd/rt.rs:49
21: 0x556f5ce1e8a3 - std::panicking::try::do_call::h7c2a8488f72db90c
at src/libstd/panicking.rs:292
22: 0x556f5ce214fa - __rust_maybe_catch_panic
at src/libpanic_unwind/lib.rs:80
23: 0x556f5ce1f36d - std::panicking::try::hc3a9b5da4250385d
at src/libstd/panicking.rs:271
24: 0x556f5ce1f36d - std::panic::catch_unwind::hf27600bf8c37809a
at src/libstd/panic.rs:394
25: 0x556f5ce1f36d - std::rt::lang_start_internal::h409d4f2fe51133b0
at src/libstd/rt.rs:48
26: 0x556f5cc34a22 - main
27: 0x7f637cacab97 - __libc_start_main
28: 0x556f5cc1b2ca - _start
29: 0x0 - <unknown>
This is the rust backtrace
thread 'main' panicked at 'called Option::unwrap()
on a None
value', C:\Users\notar.cargo\registry\src\github.com-1ecc6299db9ec823\wgpu-native-0.4.3\src\instance.rs:474:5
stack backtrace:
Fix/basic implementation of #112. Automatically pulls characters from the status string and replaces them with "...". This method does have the downside of showing the full status string if the window is resized small enough, however I presume the average user isn't going to be doing this, so it shouldn't matter.
Important to note that this is not configurable currently, but configurable behavior could be feasibly added on in the future.
Run the program with the --fullscreen
flag to open the program in fullscreen mode
warning: lint `mutable_borrow_reservation_conflict` has been removed: now allowed, see issue #59159 <https://github.com/rust-lang/rust/issues/59159> for more information
--> src/session.rs:2681:21
|
2681 | #[allow(mutable_borrow_reservation_conflict)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(renamed_and_removed_lints)]` on by default
warning: `rx` (lib) generated 1 warning
This lint has been removed. See https://github.com/rust-lang/rust/issues/59159. This removes the allow for this now non-existent lint. 😃
Solves #95 (actually the command is :saveas
and not :sav
).
Save view to disk and change its name.
If there is a character after the cursor delete that, otherwise delete the current character.
If the deletion should be only delete the character after the cursor these change must be made:
fn cmdline_handle_delete(&mut self) {
if self.cmdline.cursor_forward().is_some() {
self.cmdline.delc();
}
if self.cmdline.is_empty() {
self.cmdline_hide();
}
}