Barrel Rotation Input support [WIP]

I hacked away until I got some pen-rotation support take a look at the video, it is pretty fun!

https://github.com/briend/mypaint/tree/pen-rotation
https://github.com/briend/libmypaint/tree/pen-rotation

2 Likes

I’ve updated a bunch more files so the other tools seem to work fine. Still a few more screens like the Input Test Window that need to be fixed. I really feel silly that I basically searched all the files for “xtilt” and added “, rotation” and just kept recompiling to find the errors.

I think it’s ready to test, can’t find any obvious bugs. Just git clone the two repositories listed in the 1st post and try out your Art Pen or possibly other pens that have rotation support. This might also use the wheel on certain tablets and pens… it’s whatever GDK WHEEL maps to.

Hi briend !

I’m really interested in testing your code because Xorg and Krita are driving me crazy theses last few weeks because of bugs (last one here), so I’m thinking to move to Mypaint again, possibly with Wayland…

But, the repos you link are not found… Is there an easy way to test (I’m using Antergos, an Arch based distribution) ?

Thanks for you work !

Thanks, I should really make a pull request for this soon :stuck_out_tongue:
Weird, the links above seem to work fine for me. Are you getting a 404?
Have you built libmypaint and mypaint from scratch before? You’ll want to git clone the main repositories, and then add my repo as a remote branch, and then create a new local branch and merge my branch into that. Let me know if you need step by step instructions I’ll try to help.

Hi Brien !

Thanks for your answer :wink:
I used the AUR package mypaint-git (and libmypaint-git) to compile easily…

for your branch, I tried to git clone directly, maybe that’s why…
But the best way for me would me to edit the AUR package PKGBUILD or it’s install file, just adding a few lines…

But I’m afraid I’m a little lost… I don’t know where to add theses lines… Is it a lot of work for you to write the missing lines ? then I think I can make a custom package :wink:

Thanks again !

Or just push your code and I’ll be testing by simply reinstalling mypaint-git with AUR ?

Well, I do plan to make a pull request soon, but it will be quite a while before it gets accepted into the main code :smiley:

I think the best bet is to modify the AUR files to do the git merge:
this part in mypaint:

prepare() {
	cd "$srcdir/mypaint"
}

should become something like this:

prepare() {
	cd "$srcdir/mypaint"
	git remote add briend git@github.com:briend/mypaint.git
	git fetch briend
	git merge briend/pen-rotation --no-edit
}

for libmypaint you should change:

build() {
  cd "$srcdir/libmypaint"

  ./autogen.sh
  ./configure --prefix=/usr --enable-gegl
  make
}

to be:

build() {
  cd "$srcdir/libmypaint"
  git remote add briend git@github.com:briend/libmypaint.git
  git fetch briend
  git merge briend/pen-rotation --no-edit
  ./autogen.sh
  ./configure --prefix=/usr --enable-gegl
  make
}

Let me know if that works!

Thanks Brien, I’ll test as soon as I can, but I’m short on time today… it will be probably tomorrow !

Hi Brien,

I just tried to compile… but I’m sorry to announce it didn’t work.
First of all, for some unknow reason, repos are not found with git+SSH, but they are though HTTPS, so its works with this line:
git remote add briend https://github.com/briend/mypaint.git

but for mypaint, git automatic merge generate conflicts in gui/drawutils.py…
and for libmypaint git refuse to merge unrelated histories…

I’m afraid I’m not skilled enough with git and mypaint code to solve this (I’m an illustrator, not a dev…)… maybe you should rebase your branch before I test it ? What do you think ?

Please keep me updated :wink:

Good catch with the https, that sounds like a better url anyway. I was actually inspired to work on the libmypaint last night and fixed a lot of stuff. I never thought to rebase the mypaint side, which is like 7 months old. I bet that will fix it. I’ll let you know soon.

Great, thanks for your work ! I’ll be happy to test :wink:

Ok I rebased it and got rid of the conflicts but I haven’t been able to actually try to compile it or test it. I’ll do that tonight but feel free to try it again :smiley:

Tried again this morning…

for mypaint :
git is no more complaining…
but scons is:
In file included from lib/mypaintlib.hpp:15:0,
from lib/mypaintlib_wrap.cc:3140:
lib/brush.hpp: Dans la fonction membre « bool Brush::stroke_to(Surface*, float, float, float, float, float, double, float) »:
lib/brush.hpp:68:110: erreur : too many arguments to function « int mypaint_brush_stroke_to(MyPaintBrush*, MyPaintSurface*, float, float, float, float, float, double) »
h_stroke_to(c_brush, c_surface, x, y, pressure, xtilt, ytilt, dtime, rotation);
^
In file included from lib/brush.hpp:17:0,
from lib/mypaintlib.hpp:15,
from lib/mypaintlib_wrap.cc:3140:
/usr/include/libmypaint/mypaint-brush.h:44:1: note : declared here
mypaint_brush_stroke_to(MyPaintBrush *self, MyPaintSurface *surface, float x, float y,
^~~~~~~~~~~~~~~~~~~~~~~
scons: *** [lib/mypaintlib_wrap.os] Error 1
scons: building terminated because of errors.

and for libmypaint git continue to refuse to merge unrelated histories… ?

Cheers :wink:

Ok this is good, I think. Mypaint gui is sending the “rotation” to libmypaint but libmypaint is not expecting it because it git hasn’t merged in my changes. I think this is because I did a “rude” thing and squashed all my commits into one (to prepare a pull request soon), but you already downloaded those other commits so our timelines are messed up. I think I was assuming that your build process deleted all your local folders every time (sorry I don’t quite know how Arch works). Can you try to delete all your local mypaint build directories and try the whole process again? I’m pretty confident it should work. :smiley:

Assuming you get it to work, let me know how you like the default orientation of the stylus. I tweaked the values so that on my Art Pen with the side button facing upwards, the rotation is “0”, and if I twist clockwise it goes up to +180, and if I twist Counter-Clockwise it goes down to -180. I thought this was a good compromise until there is a preference for it. Hmm, yeah I can imagine a preference to say “offset rotation by X degrees” to allow people to tweak it for left or right handed use, or a stylus that reports different values for whatever reason.

One annoying thing I realized last night was that my normal stylus reports a bogus (but valid) rotation value. I have no idea how to handle that without a manual preference to just disable rotation. For a mouse and other well-behaved devices, however, I figured out I could sense the missing rotation and have the mypaint gui send a clearly invalid rotation value to libmypaint, so libmypaint could properly ignore it and set the rotation to 0.

I’m sorry Brien, but I still can’t compile, with almost the same errors… even after cleaning the folders before compiling.
The only difference is for mypaint, scons is complaining about another line…

Is it because scons use python 2.7 ?
or because I’m fetching you branch in the main mypaint repo (git+https://github.com/mypaint/mypaint.git), not your “fork” on github (GitHub - briend/mypaint: MyPaint is a simple drawing and painting program that works well with Wacom-style graphics tablets.) ?

For the rotation values, even if I did not test it yet, maybe a value between 0 and 360° clockwise may be simpler for the user and for the math ? what happen if the pen rotate more than 180° ? and 180° = -180 ° ? :wink:
But I have to test ;p

for detecting the Art Pen, I believe libwacom (or xf86-input wacom) is able to detect it because I can define a custom pressure value and custom input for buttons only for this pen in the gnome control center… So maybe mypaint can know if it’s an Art pen or not by asking to the wacom drivers ?

If you can build mypaint with AUR then it’s definitely not a python or any dependency issues. I think it’s the git repo-- you definitely have to add my fork. Maybe paste the changes you are making to the AUR files? It should look like what I pasted above but just change the repo to
GitHub - briend/libmypaint: libmypaint, a.k.a. "brushlib", is a library for making brushstrokes which is used by MyPaint and other projects. and GitHub - briend/mypaint: MyPaint is a simple drawing and painting program that works well with Wacom-style graphics tablets. respectively.

The problem with 0-360 is, I think… what’s the “normal state”? Zero? But no one can hold their hand still and stay at zero so really it would be something like 355 to 5 degrees. Kinda confusing I think :-). But if we use -180 to 180 then “normal” is -5 to +5 degrees, which seems a bit more intuitive (well, to me). In either case people should create “V” shaped graphs so that if they twist all the way around it doesn’t have a sudden jarring effect.

I hope it works this time! :smiley:

I’m sorry, I may be wasting your time…
here are the two PKGBUILD I have, and the compilation I get…
I succesfully compile Mypaint and libmypaint from git with the AUR pacakges before

Mypaint

PKGBUILD

pkgname=mypaint-git
pkgver=1.2.0.r453.g7530c8e2
pkgrel=1
pkgdesc="A fast and easy painting application for digital painters, with brush dynamics"
arch=('i686' 'x86_64')
url="http://mypaint.org/"
license=('GPL')
depends=('desktop-file-utils' 'gtk3' 'gegl' 'babl' 'json-c' 'python2-cairo' 'python2-gobject' 'python2-numpy' 'libmypaint-git')
makedepends=('git' 'scons' 'swig')
provides=('mypaint')
conflicts=('mypaint')
install=mypaint-git.install
source=('git+https://github.com/briend/mypaint.git'
        'mypaint-git.install'
)

pkgver() {
	cd "$srcdir/mypaint"
	git describe --long --tags|sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g'
}

prepare() {
	cd "$srcdir/mypaint"
	git remote add briend https://github.com/briend/mypaint.git
	git fetch briend
	git merge briend/pen-rotation --no-edit
}

build() {
	cd "$srcdir/mypaint"
	scons prefix="/usr" enable_gegl=true use_sharedlib=yes
}

package() {
	cd "$srcdir/mypaint"
	scons prefix="/usr" enable_gegl=true use_sharedlib=yes --install-sandbox="$pkgdir" "$pkgdir"
}

sha256sums=('SKIP'
            '34dec9df2e005de9fae6c6352f49835a1d41e515c6131ed1df8c9e27ee3c9d1d')

compilation (partially in french, sorry)

[nylnook@nylnook-home mypaint-git]$ makepkg -si
==> Création du paquet mypaint-git 1.2.0.r453.g7530c8e2-1 (lun. mars 13 17:39:24 CET 2017)
==> Vérification des dépendances pour l’exécution...
==> Vérification des dépendances pour la compilation...
==> Récupération des sources...
  -> Clonage du dépôt mypaint git...
Clonage dans le dépôt nu '/home/nylnook/mypaint/mypaint-git/mypaint'
remote: Counting objects: 28700, done.
remote: Compressing objects: 100% (8/8), done.
remote: Total 28700 (delta 1), reused 0 (delta 0), pack-reused 28692
RĂ©ception d'objets: 100% (28700/28700), 79.26 MiB | 1007.00 KiB/s, fait.
RĂ©solution des deltas: 100% (20645/20645), fait.
  -> mypaint-git.install trouvé
==> Validation des fichiers source avec sha256sums...
    mypaint ... Ignoré
    mypaint-git.install ... RĂ©ussite
==> Extraction des sources...
  -> Création d’une copie de travail du dépot mypaint git...
Clonage dans 'mypaint'...
fait.
==> Lancement de prepare()...
Depuis https://github.com/briend/mypaint
 * [nouvelle branche]  BrushRandomizer  -> briend/BrushRandomizer
 * [nouvelle branche]  all-newinputs    -> briend/all-newinputs
 * [nouvelle branche]  curve-points     -> briend/curve-points
 * [nouvelle branche]  master           -> briend/master
 * [nouvelle branche]  pen-rotation     -> briend/pen-rotation
 * [nouvelle branche]  penrot-view-zoom -> briend/penrot-view-zoom
 * [nouvelle branche]  v1.2.x           -> briend/v1.2.x
 * [nouvelle branche]  view-zoom        -> briend/view-zoom
Mise Ă  jour 2dd8b509..7530c8e2
Fast-forward
 gui/drawutils.py        |   30 +-
 gui/freehand.py         |  215 +-
 gui/inktool.py          |   14 +-
 gui/inputtestwindow.py  |    7 +
 gui/linemode.py         |    4 +-
 gui/mode.py             |   12 +-
 gui/tileddrawwidget.py  |    6 +
 lib/SConscript          |    1 -
 lib/brush.hpp           |    4 +-
 lib/brush.py            |  219 +-
 lib/command.py          |    9 +-
 lib/eventhack.cpp       |  122 --
 lib/eventhack.hpp       |   45 -
 lib/layer/data.py       |    5 +-
 lib/mypaintlib.hpp      |    1 -
 lib/mypaintlib.i        |    1 -
 lib/python_brush.hpp    |    4 +-
 lib/stroke.py           |   10 +-
 po/ckb.po               | 5451 ++++++++++++++++++++++++++++++++++++++++++++++
 po/cs.po                |   59 +-
 po/en_CA.po             |   10 +-
 po/eo.po                | 5450 ++++++++++++++++++++++++++++++++++++++++++++++
 po/es.po                |    8 +-
 po/fa.po                |   18 +-
 po/fi.po                | 5454 +++++++++++++++++++++++++++++++++++++++++++++++
 po/hu.po                |   23 +-
 po/is.po                | 5446 ++++++++++++++++++++++++++++++++++++++++++++++
 po/{pt_PT.po => kab.po} |   78 +-
 po/ko.po                |  220 +-
 po/ms.po                | 5442 ++++++++++++++++++++++++++++++++++++++++++++++
 po/pl.po                |  770 +++----
 po/pt_BR.po             |  213 +-
 po/ro.po                |   46 +-
 po/uk.po                |   48 +-
 setup.py                |    1 -
 35 files changed, 28212 insertions(+), 1234 deletions(-)
 delete mode 100644 lib/eventhack.cpp
 delete mode 100644 lib/eventhack.hpp
 create mode 100644 po/ckb.po
 create mode 100644 po/eo.po
 create mode 100644 po/fi.po
 create mode 100644 po/is.po
 rename po/{pt_PT.po => kab.po} (99%)
 create mode 100644 po/ms.po
==> Lancement de pkgver()...
==> Lancement de build()...
scons: Reading SConscript files ...
building for 'python2.7' (use scons python_binary=xxx to change)
using 'python2.7-config' (use scons python_config=xxx to change)
Delete(["libmypaint-tests.so", "libmypaint-tests.so", "libmypaint.so", "libmypaintlib.so", "libmypaint.a", "libmypaint-tests.a", "lib/_mypaintlib.so"])
set umask to 0022 (was 0022)
scons: done reading SConscript files.
scons: Building targets ...
swig -o lib/mypaintlib_wrap.cc -Wall -noproxydel -python -c++ -DNO_TESTS lib/mypaintlib.i
g++ -o lib/mypaintlib_wrap.os -c -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wall -Wno-sign-compare -Wno-write-strings -fopenmp -O3 -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wall -g -pthread -DNO_TESTS -fPIC -DHAVE_GTK3 -I/usr/include/libmypaint -I/usr/include/json-c -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libpng16 -I/usr/include/pygobject-3.0 -I/usr/lib/libffi-3.2.1/include -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/gio-unix-2.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/harfbuzz -I/usr/include/libdrm -I/usr/include/gdk-pixbuf-2.0 -I/usr/lib/python2.7/site-packages/numpy/core/include -I/usr/include/python2.7 lib/mypaintlib_wrap.cc
In file included from lib/mypaintlib.hpp:15:0,
                 from lib/mypaintlib_wrap.cc:3140:
lib/brush.hpp: Dans la fonction membre « bool Brush::stroke_to(Surface*, float, float, float, float, float, double, float) »:
lib/brush.hpp:68:110: erreur : too many arguments to function « int mypaint_brush_stroke_to(MyPaintBrush*, MyPaintSurface*, float, float, float, float, float, double) »
 h_stroke_to(c_brush, c_surface, x, y, pressure, xtilt, ytilt, dtime, rotation);
                                                                              ^
In file included from lib/brush.hpp:17:0,
                 from lib/mypaintlib.hpp:15,
                 from lib/mypaintlib_wrap.cc:3140:
/usr/include/libmypaint/mypaint-brush.h:44:1: note : declared here
 mypaint_brush_stroke_to(MyPaintBrush *self, MyPaintSurface *surface, float x, float y,
 ^~~~~~~~~~~~~~~~~~~~~~~
scons: *** [lib/mypaintlib_wrap.os] Error 1
scons: building terminated because of errors.
==> ERREUR : Une erreur s’est produite dans build().
Abandon...

Libmypaint

PKGBUILD

pkgname=libmypaint-git
pkgver=1.3.0.beta.1.40.g4f32618
pkgrel=1
pkgdesc="a library for making brushstrokes which is used by MyPaint and other projects, with GEGL support"
arch=('i686' 'x86_64')
url="http://mypaint.org/"
license=('ISC')
depends=('gobject-introspection' 'json-c' 'gegl')
makedepends=('git' 'intltool' 'python')
source=('git+https://github.com/briend/libmypaint.git')
md5sums=('SKIP')

build() {
  cd "$srcdir/libmypaint"
  git remote add briend https://github.com/briend/mypaint.git
  git fetch briend
  git merge briend/pen-rotation --no-edit
  ./autogen.sh
  ./configure --prefix=/usr --enable-gegl
  make
}

package() {
  cd "$srcdir/libmypaint"

  make DESTDIR="$pkgdir" install
  install -D -m644 COPYING "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

pkgver() {
  cd "$srcdir/libmypaint"

  git describe --tags | sed 's/^v//g;s/-/./g'
}

# vim:set ts=2 sw=2 et:

compilation

[nylnook@nylnook-home libmypaint-git]$ makepkg -si
==> Création du paquet libmypaint-git 1.3.0.12.g4f32618-1 (lun. mars 13 17:42:24 CET 2017)
==> Vérification des dépendances pour l’exécution...
==> Vérification des dépendances pour la compilation...
==> Récupération des sources...
  -> Clonage du dépôt libmypaint git...
Clonage dans le dépôt nu '/home/nylnook/mypaint/libmypaint-git/libmypaint'
remote: Counting objects: 3369, done.
remote: Compressing objects: 100% (31/31), done.
remote: Total 3369 (delta 50), reused 37 (delta 37), pack-reused 3301
RĂ©ception d'objets: 100% (3369/3369), 2.20 MiB | 1.09 MiB/s, fait.
RĂ©solution des deltas: 100% (2312/2312), fait.
==> Validation des fichiers source avec md5sums...
    libmypaint ... Ignoré
==> Extraction des sources...
  -> Création d’une copie de travail du dépot libmypaint git...
Clonage dans 'libmypaint'...
fait.
==> Lancement de pkgver()...
==> Version mise Ă  jour : libmypaint-git 1.3.0.beta.1.40.g4f32618-1
==> Lancement de build()...
warning: pas de commit commun
remote: Counting objects: 28349, done.
remote: Compressing objects: 100% (23/23), done.
remote: Total 28349 (delta 1), reused 15 (delta 0), pack-reused 28326
RĂ©ception d'objets: 100% (28349/28349), 79.15 MiB | 1.11 MiB/s, fait.
RĂ©solution des deltas: 100% (20414/20414), fait.
Depuis https://github.com/briend/mypaint
 * [nouvelle branche]  BrushRandomizer  -> briend/BrushRandomizer
 * [nouvelle branche]  all-newinputs    -> briend/all-newinputs
 * [nouvelle branche]  curve-points     -> briend/curve-points
 * [nouvelle branche]  master           -> briend/master
 * [nouvelle branche]  pen-rotation     -> briend/pen-rotation
 * [nouvelle branche]  penrot-view-zoom -> briend/penrot-view-zoom
 * [nouvelle branche]  v1.2.x           -> briend/v1.2.x
 * [nouvelle branche]  view-zoom        -> briend/view-zoom
 * [nouvelle Ă©tiquette] v0.2             -> v0.2
 * [nouvelle Ă©tiquette] v0.3             -> v0.3
 * [nouvelle Ă©tiquette] v0.4             -> v0.4
 * [nouvelle Ă©tiquette] v0.4.1           -> v0.4.1
 * [nouvelle Ă©tiquette] v0.5.0           -> v0.5.0
 * [nouvelle Ă©tiquette] v0.6.0           -> v0.6.0
 * [nouvelle Ă©tiquette] v0.7.0           -> v0.7.0
 * [nouvelle Ă©tiquette] v0.8.0           -> v0.8.0
 * [nouvelle Ă©tiquette] v0.9.0           -> v0.9.0
 * [nouvelle Ă©tiquette] v0.9.0-beta1     -> v0.9.0-beta1
 * [nouvelle Ă©tiquette] v1.0.0           -> v1.0.0
 * [nouvelle Ă©tiquette] v1.1.0           -> v1.1.0
 * [nouvelle Ă©tiquette] v1.1.0-rc1       -> v1.1.0-rc1
 * [nouvelle Ă©tiquette] v1.1.0-rc2       -> v1.1.0-rc2
 * [nouvelle Ă©tiquette] v1.1.0-rc3       -> v1.1.0-rc3
 * [nouvelle Ă©tiquette] v1.2.0           -> v1.2.0
 * [nouvelle Ă©tiquette] v1.2.0-beta.0    -> v1.2.0-beta.0
 * [nouvelle Ă©tiquette] v1.2.0-beta.1    -> v1.2.0-beta.1
 * [nouvelle Ă©tiquette] v1.2.0-beta.2    -> v1.2.0-beta.2
 * [nouvelle Ă©tiquette] v1.2.0-beta.3    -> v1.2.0-beta.3
 * [nouvelle Ă©tiquette] v1.2.0-beta.4    -> v1.2.0-beta.4
 * [nouvelle Ă©tiquette] v1.2.1-beta.0    -> v1.2.1-beta.0
 * [nouvelle Ă©tiquette] v1.2.1-beta.1    -> v1.2.1-beta.1
fatal: refus de fusionner des historiques sans relation
==> ERREUR : Une erreur s’est produite dans build().
    Abandon...

I made a copy from the original PKGBUILD from AUR and modified to add you repo and your branch, that’s all, and I honestly don’t know why it doesn’t work.
If there is another way to compile, I can try too…

Oh no! I had a typo in my original post. I’m wasting YOUR time ;-). Sorry!

You don’t need to change the source= line, but that shouldn’t hurt. My typo was that I pasted the same URL for both packages. libmypaint needs to use my libmypaint repo, and likewise mypaint uses my mypaint repo. I can’t believe I missed that. I’ve updated the original post above to be correct now.

So for libmypaint that line within build() should be:
git remote add briend GitHub - briend/libmypaint: libmypaint, a.k.a. "brushlib", is a library for making brushstrokes which is used by MyPaint and other projects.

and for mypaint under prepare() it should be:
git remote add briend GitHub - briend/mypaint: MyPaint is a simple drawing and painting program that works well with Wacom-style graphics tablets.

Make sure you install libmypaint first, then mypaint. Again, sorry about that typo :frowning:

Successfully compiled ! :relieved:
I can’t believe I missed that myself, good you catch it !

So yes it works, and it works finely according my first tests :wink:
+180° to -180° values makes much more sense once I see it in the mypaint brush editing interface, and it seems to works for drawing, even if i have to test some more graph shapes…
the best one until now for me is to push the cursor to +180° and give the graph an inversed V shape as your did in your video.

As far as I can judge as a user, your code is ready to push in the official repo, but now … we really miss a visual feedback, especially for the “Elliptical Dab : angle” value : having a circle as a cursor while we are drawing with an ellipse is confusing. Ideally the cursor should have the same shape and angle than the radius and angles in the settings… like in Krita. I suppose that’s a big work too.
The idea is to be able to rotate the cursor while holding the stylus above the tablet before entering contact to know if we are about to draw thick or thin strokes. :yum:

and yes the name “barrel rotation” is clearer than simply “rotation” :wink:

Do you need some special test or a detailed feedback on something ?