Hey Eric,

Le 20 juil. 09 à 21:12, Eric Wasylishen a écrit :

> Hey Quentin,
> I was playing with EUI last week and started to write a basic
> paintbrush tool - here's the current (very early and hacky) code. It
> only works in OS X for now because I'm using NSGradient.

Very cool :-) I played a bit with it and it works pretty well.
Having NSGradient on GNUstep would be nice, but it looks like a quite  
substantial task to implement it.

> I made a ETShape subclass called ETDrawingStrokeShape which stores the
> path of the drawing stroke, and currently the tablet pressure at each
> point in the path. I'm planning to extend it to store more info, such
> as timestamp of each event and parameters for fancy tablets (angle,
> rotation, etc.).

As we discussed it on the silc channel, I would make the tool more  
dumb, by moving the logic related ETDrawingStrokeShape into an  
ETActionHandler category. Something like:

- (BOOL) canBrushStrokeOnItem:
- (id) beginBrushStrokeAtPoint: onItem: withTouch: color: // returns a  
brush stroke object (an ETDrawingStrokeShape in the default  
implementation)
- (void) continueBrushStroke: atPoint: ontItem: withTouch: color:
- (void) endBrushStroke: onItem:

This way both are decoupled and we can more easily handle the  
persistency with CoreObject.

To provide stylus-related infos, you can declare an ETTouchAction  
protocol with methods like -pressure, -tilt etc. and makes ETEvent  
adopts it (see ETKeyInputAction as an example). Then in the action  
handler, you can receive the event as a touch action without exposing  
the event itself, and without declaring too many parameters or having  
to add more later. The idea is that you pass the action expressed as  
several parameters usually, but you can reify it (partially or not)  
when that makes sense.
Action handlers should never receive events in parameter, because a  
tool might later be extend to support events from another input  
device, or even combine events from multiple input devices into a  
single action. However some EUI tools such as ETSelectTool currently  
don't implement this separation very cleanly and needs to be improved.

> ETDrawingStrokeShape then has another stlye, as an ivar, which it
> delegates the actual drawing to. I wrote two styles which work here,
> ETBrushStyle, a bitmap brush, and ETPenStyle, a vector brush.

Sounds excellent.

You might want to introduce an ETBrushDab class which stores all the  
infos you need at each point in the path. Each instance would be  
stored in an array and this would replace the pressure array you  
currently have in ETDrawingStrokePath. ETBrushDab can have a factory  
method, which makes easy to create a dab in -continueBrushStroke:, like
- (ETBrushDab *) dabWithTouch: (ETTouchAction *)aTouch
Later ETBrushDab could also be used to cache the brush shape that gets  
stamped at each point on the path. e.g. with a natural painting  
application such as Painter, the brush shape gets potentially deformed  
with each dab and this needs to be computed before stamping it on the  
brush stroke path.

> I'm not too comfortable with the graphics coordinates yet, so I may be
> doing many things wrong.

The code looks correct at first sight.
I'll check what's going with -convertRect:toItem: vs - 
convertRect:fromItem:. I don't use -convertRect:toItem: anywhere and I  
wrote no tests for it unlike -convertRect:fromItem:.

> One bug is that if you start drawing on top of an existing layout item
> (rather than the window background) the drawing is offset vertically
> by 10 or 15 pixels.

I'll take a look at that. There are still some bugs in the event  
handling that remain to be fixed.

> Anyway, it was exciting to get this working very quickly. :)

:-)

Cheers,
Quentin.
_______________________________________________
Etoile-dev mailing list
Etoile-dev@gna.org
https://mail.gna.org/listinfo/etoile-dev

Reply via email to