Implementation of the layer/masks node graph in Krita
- KisBaseNode: implements properties common to all nodes
- KisNode::KisBaseNode: implements the graph (but adding and removing nodes is private)
- KisNodeFacade: the only way to add and remove nodes. This class together with KisNodeGraphListener guarantees that when adding and removing nodes the right signals are emitted
- KisImage: KisImage is a node facade and a node graph listener. There are still a number of functions that take layers instead of nodes: those are deprecated
- KisMask::KisNode: the basis of all masks. Masks have a selection and cannot have child nodes. Masks apply their effect on the associated layer, they do not composite pixels. There are the following types of masks:
- KisTransparencyMask (makes pixels more or less transparent)
- KisTransformationMask (transforms the selected pixels)
- KisEffectMask (applies a filter to the associated layer)
- KisSelectionMask (defines the per-layer selection)
- KisLayer::KisNode: The basis for all layers. Layers are composited in groups and can have masks. There are paint layers, group layers, adjustment layers, clone layers and shape layers. Layers have a projection and may have a paint device (like a selection for an adj. layer, or the dried and current paint devices for paint layers).
- KisNodeModel: a QAbstractItemModel on the image's layer stack. This is connected to the layer box.
- KisShapeController: creates a shape for every node so the flake mechanism can activate the right tools
The visitor mechanism has changed slightly, too -- there's a visitAll function that can be pretty handy.
Note also that we're not storing the properties like visible, locked etc. hardcoded anymore, but in an extensible list. And it's possible to define a list of preferred properties and check for that. See for instance KisImage:189, where we check whether a layer is temporary.
XXX: Below this: design notes.
Selections can be visualized by two methods:
- marching ants
- mask view + outline (old krita style)
There needs to be a way to deactivate the add/subtract mode of selection
The selection which is global (but affects only the current layer) is shown somewhere special in the layer box. (a thumbnail of sorts). That thumbnail works as a drag and drop to exchange and create per layer selections.
The selections (and masks too) are "paint devices" in their own right from the users standpoint, so they can be painted on etc.
The paint and fill tools will work on the selections and masks, as will the special selection tools. XXX: interaction between global selection and effect/opacity masks?
We will have 3 concepts:
- Selection. Choose pixels for reading and writing
- Effect mask. Choose pixels for filtering non-destructively
- Opacity mask. Nondestructively affects transparency of pixels
We will have both global and per layer selection. The global selection can be drag & dropped to a layer, where it will merge/replace/subtract with the layer selection mask, if present.
Effect mask and opacity mask: Opacity mask is an effect mask with an opacity filter. We will show these as separate things to the user.
Effect masks and opacity masks consists of a single-channel paint device, and a KisFilter. There can be more than one of them per layer. The result is written to a projection: this projection is then composited. The original layer pixels are not changed.
Users would prefer to have effect and opacity masks as two things, though: We should implement this ui-wise, which means the KisFilter that handles opacity can stay hidden. So: a "opacity mask" is just a special "effect mask" with a filter that manipulates transparency.
There will be any number of effects masks associated with a single layer. Adjustment Layers will stay the way they are right now.