This is an idea that I think would be very nice to have in GIMP. It would probably take a bit of programming, and I can't do that unfortunately.
Definitions: I'm not sure of the proper terms, so I will define what I mean: Controller - A source of data that is used to modify an attribute of the brush Attribute - Part of the data for a brush, such as size, color, opacity, angle, etc, etc. Can be modified by a controller. Problems: The current control-to-attribute has few features and does not offer a great deal of control to the user. It only supports one control and a few attributes. Additionally, for the attributes, there is no specification for how much the attribute is affected. What I mean is, in the toolbox you can check to have the pressure affect the opacity, but not by any given range. Each attribute connected to a control should have some parameters. Three important ones are start-adjustment, end-adjustment, and adjustment-type. adjustment-type can be 'absolute', 'relative', or 'percent', and start-adjustment/end-adjustment would the the absolute, relative, or percentage of adjustment caused to the selected attribute based on the value of the controller. If adjustment-type is 'relative', adjustment-start is '-10', adjustment-end is '10', the selected attribute is brush-size, and the brush size is currently 76, then the controller would cause the brush to go from 66 to 86. if the controller value at the time the data is sampled is 0, then it would be 66, if the controller value is 1, it would be 86. If adjustment-type is 'absolute', adjustment-start is '50', adjustment-end is '75', the selected attribute is brush-size, and the brush size is currently 76 (that does not matter since it is absolute), then the controller would cause the brush to go from 50 to 75. if the controller value at the time the data is sampled is 0, then it would be 50, if the controller value is 1, it would be 75 If the adjustment-type is 'percent', then it is relative but by percentage. If adjustment-start is '50% (0.5)', adjustment-end is '150% (1.5)', the selected attribute is brush-size, and the brush size is currently 76, then the controller would cause the brush to go from 38 to 114. if the controller value at the time the data is sampled is 0, then it would be 38, if the controller value is 1, it would be 114 adjustment-start can also be larger than adjustment-end, to cause the opposite affect. For example, to have the opacity be higher with a 'soft' pressure than with a 'hard' pressure Controller-attribute chain: The design could be such that for each controller, the user can select which attribute(s) is modified, and set the parameters, the problem is that one controller can only be connected the attributes and shares the parameters GUI: [Checkbox] - Controller1 Enabled [Checkbox] - Attribute1 affected [Checkbox] - Attribute2 affected ... [Checkbox] -AttributeN affected ___ [RadioBox]-Adjustment Type [NumberBox]-Adjustment Start [NumberBox]-Adjustment End This would allow the user to enable the controller, tell it that the controller affects this attribute and that one, and the parameters. But the parameters are the same for Controller1->Attribute2 and Controller1->Attribute2. It would be desired to have separate parameters for different controller->attribute links. For example, pressure may vary opacity by a certain amount, but size by an even greater amount, for this to be, they can't share parameters. A controller-attribute chain is really just a list of what controller affects what attribute, and parameters for that specific item: struct ControllerAttributeSomethingOrAnother { int controllerSource; int targetAttribute; AdjustmentType type; double start; double end; } When a given brush is applied, each item in the chain would be applied to the 'original' brush attributes, modifying it by some manor: BrushAttributes b = GetCurrentBrushAttributes(); foreach item in chain { // interpolate the controller value with the start/end range // so that controller value 0 represents the start value and controller value 1 represents the end value double control_value = GetControllerValue(item.controllerSource) * (item.end - item.start) + item.start; double value; switch(item.type) { case 'absolute' value = control_value; break; case 'relative' value = control_value + b.GetAttributeValue(item.targetAttribute); break; case 'percent' value = control_value * b.GetAttributeValue(item.targetAttribute); break; } b.SetAttributeValue(item.targetAttribute, value); } It would also be possible for the same attribute to be affected by two different controllers. Order does matter for such things, such as Pressure->Opacity percent 0%-100% Direction->Opacity relative -0.2-0.2 Inital opacity: 75% (0.75) Pressure controller: 0.75 Direction controller: 0.75 Results: 1. opacity becomes 56% (0.5625) from Pressure->Opacity 2. opacity becomes 66% (0.6625) from Direction->Opacity Results if order is switched: 1. opacity becomes 85% (0.85) from Direction->Opacity 2. opacity becomes 63% (0.6375) from Pressure->Opacity Additional types of controllers and attributes: I also think it would be nice if there were some additional controllers and additional attributes: Controllers: pressure - Same as usual, represents the pressure, only specialized devices can use it (tablets) tilt - Again only special devices can support it rotation - Not the same as 'direction' below, but some devices can detect the rotation of the pen on the tablet, or so I've heard direction - Based on sampling the position of two points, determine the direction of the line from the first point to the second point speed - Determine timing between the sampling of two points noise - A random source from 0 to 1. This can allow the 'jitter' option to be applied to other things, such as jitter the color or size as well. Note that a 'noise' controller is different than a 'jitter' attribute It allows an attribute to be 'randomly' changed. It can even be connected to the 'jitter' attribute to allow the jitter radius to be random. Attributes: opacity size color hue saturation lightness gradient - When using a gradient for a stroke, normally it is based on the movement of distance. This would allow a controller to select what part of the gradient to use. The valid range would be from 0 (start of gradient) to 1 (end of gradient). The initial value of this attribute would be computed as normal (distance into the stroke and the length), and adjustment types would still work, absolute specifying an exact position, and relative/percent specifying a position offset from where it is 'supposed' to be in the gradient angle - One useful combination would be to connect a 'direction' controller to the 'angle' attribute, so it seems that the brush is rotating with the stroke. This means that 'direction' and 'angle' would need to be in the same orientation, either both clockwise or both counter clockwise. jitter - The position of the applied stroke. Default value is 0 (draw where the cursor is), but it can be adjusted by by a controller if desired. For example, a light pressure can draw directly at the given position and a hard pressure can increase the jitter radius. GUI interface: A new dialog would exist which would allow the creation of the controller-attribute chain. Some features would thus be removed from the toolbox. It may still be desired to have a separate 'chain' per tool, similar to how the settings of one tool can be difference from the other tool, and when selecting the first tool, it will restore it settings like blend mode/etc. It may be desirable to implement separate chains per tool, so when the user selects one tool, it's chain is used, and when selecting another tool, it's chain is reloaded and used. This new dialog would consist of a list-like control that is by default empty, with a +/- button to add a new item to the chain. Pressing '+' would insert a new item with default values, '-' would remove the selected item, also maybe a '*' to clone the current item. Attached is a small mock-up of an idea for the interface. It shows 3 items in the list chain. *Pressure will adjust the opacity by the current value from 0 to 100 percent. If the brush opacity is 75%, then it will vary from 0 to 75% based on the pressure. *Pressure will adjust the size by the current value from -20 to 50. If the brush size is currently 45, it will vary from 20 to 95 based on the pressure *Direction will adjust the angle by an absolute value from 0 to 1. (0 to 360 degrees of direction will adjust the angle of the brush from 0 to 360 degrees). Since it is absolute, the current brush angle is disregarded. If it was relative, it would be added to the current brush angle. More often, relative would probably be the desired setting and not absolute, as the initial 'angle' for the brush may be properly set. Also, how this would work for bitmap brushes would be unclear, (the bitmap would be rotated, and may loose quality), but if it was a vector brush, it would probably work fine as rotation would not cause bad quality.. Again this is just an idea that I think would be useful and would love to see in a future version. The code shown is just the idea for operation, I don't know much about the actual GIMP code. Changes:Another idea proposed by David Gowers is to use a tree-based approach instead of a list based approach. Each top-level item in the tree would represent the 'target' attribute, and items in the tree represent the 'source' controller and parameters:
Opacity: Pressure [absolute: 0 to 100%] Direction [relative: -0.2 to 0.2] Etc: Etc Etc ...Absolute items for any given destination attribute would be moved to the top automatically. During processing of each attribute based on input controllers, encountering an absolute attribute would stop processing, after since it should set the value absolutely instead of relative to the current value.
Brian Vanderburg II
<<inline: gui.png>>
_______________________________________________ Gimp-developer mailing list Gimp-developer@lists.XCF.Berkeley.EDU https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer