墨水操作
矢量和光栅墨水操控的处理方式各不相同。 矢量操控修改生成的几何图形,而光栅擦除器仅“覆盖”笔划。
Raster Ink
目前的光栅墨水仅提供部分擦除器功能。
橡皮擦
擦除器被配置为一种类似于刷子的工具。
它使用特定的模糊模式BlendMode.DESTINATION_OUT覆盖笔划,以达到擦除的目的。
- Kotlin
- JavaScript
import com.wacom.ink.Calculator
import com.wacom.ink.PathPoint
import com.wacom.ink.PathPointLayout
import com.wacom.ink.rendering.BlendMode
...
class EraserRasterTool(context: Context) : RasterTool(context) {
companion object {
val uri = URIBuilder.getToolURI("raster", "eraser")
}
override var brush = BrushPalette.eraser(context)
override fun getLayout(): PathPointLayout {
return PathPointLayout(
PathPoint.Property.X,
PathPoint.Property.Y,
PathPoint.Property.SIZE,
PathPoint.Property.RED,
PathPoint.Property.GREEN,
PathPoint.Property.BLUE,
PathPoint.Property.ALPHA
)
}
override val touchCalculator: Calculator = { previous, current, next ->
// Use the following to compute size based on speed:
var size = current.computeValueBasedOnSpeed(
previous,
next,
minValue = 8f,
maxValue = 112f,
minSpeed = 720f,
maxSpeed = 3900f
)
if (size == null) size = 8f
PathPoint(current.x, current.y, size = size,
red = 1f, green = 1f, blue = 1f, alpha = 1f)
}
override val stylusCalculator: Calculator = { previous, current, next ->
// Use the following to compute size based on speed:
var size = current.computeValueBasedOnSpeed(
previous,
next,
minValue = 8f,
maxValue = 112f,
minSpeed = 720f,
maxSpeed = 3900f
)
if (size == null) size = 8f
PathPoint(current.x, current.y, size = size,
red = 1f, green = 1f, blue = 1f, alpha = 1f)
}
override fun getBlendMode(): BlendMode {
return BlendMode.DESTINATION_OUT
}
}
...
eraserRaster: {
brush: BrushPalette.circle,
blendMode: BlendMode.DESTINATION_OUT,
dynamics: {
size: {
value: {
min: 8,
max: 112
},
velocity: {
min: 720,
max: 3900
}
}
},
...
**注意:**笔划并未从模型中擦除,仅是被覆盖了。
Vector Ink
矢量墨水提供更多的笔划操控功能:
- 部分笔划擦除器
- 完整笔划擦除器
- 操控选项
部分擦除 / 分割
擦除器工具的工作原理与刷子工具类似。 因此需要定义它的计算器。 可在此确定擦除器宽度是否随压力或速度而改变。 还可定义不同手指或触控笔输入行为。
- Kotlin
- C#
- JavaScript
class EraserVectorTool : VectorTool() {
companion object {
val uri = "tool@erase_vector"
}
override var brush = BrushPalette.circle()
override fun getLayout(): PathPointLayout {
return PathPointLayout(
PathPoint.Property.X,
PathPoint.Property.Y,
PathPoint.Property.SIZE,
PathPoint.Property.RED,
PathPoint.Property.GREEN,
PathPoint.Property.BLUE
)
}
override var drawingMode = DrawingMode.ERASING_PARTIAL_STROKE
override val touchCalculator: Calculator = { previous, current, next ->
// Use the following to compute size based on speed:
var size = current.computeValueBasedOnSpeed(
previous,
next,
minValue = 8f,
maxValue = 112f,
minSpeed = 720f,
maxSpeed = 3900f
)
if (size == null) size = 1.0f
PathPoint(current.x, current.y, size = size, red = 1f, green = 1f, blue = 1f, alpha = 0.5f)
}
override val stylusCalculator: Calculator = { previous, current, next ->
// Use the following to compute size based on speed:
var size = current.computeValueBasedOnSpeed(
previous,
next,
minValue = 8f,
maxValue = 112f,
minSpeed = 720f,
maxSpeed = 3900f
)
if (size == null) size = 1.0f
PathPoint(current.x, current.y, size = size, red = 1f, green = 1f, blue = 1f)
}
}
/// <summary>
/// Vector "drawing" tool for erasing ink storkes
/// </summary>
public class VectorEraserTool : VectorSelectionTool
{
private static readonly ToolConfig mConfig = new ToolConfig()
{
initValue = 2,
minSpeed = 100,
maxSpeed = 4000,
minValue = 2,
maxValue = 24
};
public VectorEraserTool(ManipulationMode mode)
: base(mode)
{
}
public override bool BlendCurrentStroke => false;
public override VectorBrush Shape => mCircleBrush;
protected override ToolConfig SizeConfig => mConfig;
protected override float PreviousSize { get; set; } = 2f;
public override void OnReleased(UIElement uiElement, PointerRoutedEventArgs args)
{
base.OnReleased(uiElement, args);
}
public override PathPointLayout GetLayout(Windows.Devices.Input.PointerDeviceType deviceType)
{
switch (deviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
case Windows.Devices.Input.PointerDeviceType.Touch:
case Windows.Devices.Input.PointerDeviceType.Pen:
return new PathPointLayout(PathPoint.Property.X,
PathPoint.Property.Y,
PathPoint.Property.Size);
default:
throw new Exception("Unknown input device type");
}
}
public override Calculator GetCalculator(PointerDeviceType deviceType)
{
switch (deviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
case Windows.Devices.Input.PointerDeviceType.Touch:
case Windows.Devices.Input.PointerDeviceType.Pen:
return CalculatorForMouseAndTouch;
default:
throw new Exception("Unknown input device type");
}
}
}
}
eraserVector: {
brush: BrushPalette.circle,
intersector: new Intersector(Intersector.Mode.PARTIAL_STROKE),
dynamics: {
size: {
value: {
min: 8,
max: 12
},
velocity: {
min: 720,
max: 3900
}
}
},
完整笔划橡皮擦
- Kotlin
- C#
- JavaScript
class EraserWholeStrokeTool : VectorTool() {
companion object {
val uri = URIBuilder.getToolURI("vector", "eraser_whole_stroke")
}
override var brush = BrushPalette.basic()
override fun getLayout(): PathPointLayout {
return PathPointLayout(
PathPoint.Property.X,
PathPoint.Property.Y,
PathPoint.Property.SIZE
)
}
override var drawingMode = DrawingMode.ERASING_WHOLE_STROKE
override val touchCalculator: Calculator = { previous, current, next ->
//Use the following to compute size based on speed:
PathPoint(current.x, current.y, size = 3f)
}
override val stylusCalculator: Calculator = { previous, current, next ->
//Use the following to compute size based on speed:
PathPoint(current.x, current.y, size = 3f)
}
}
/// <summary>
/// Vector "drawing" tool for erasing ink storkes
/// </summary>
public class VectorEraserTool : VectorSelectionTool
{
private static readonly ToolConfig mConfig = new ToolConfig()
{
initValue = 2,
minSpeed = 100,
maxSpeed = 4000,
minValue = 2,
maxValue = 24
};
public VectorEraserTool(ManipulationMode mode)
: base(mode)
{
}
public override bool BlendCurrentStroke => false;
public override VectorBrush Shape => mCircleBrush;
protected override ToolConfig SizeConfig => mConfig;
protected override float PreviousSize { get; set; } = 2f;
public override void OnReleased(UIElement uiElement, PointerRoutedEventArgs args)
{
base.OnReleased(uiElement, args);
}
public override PathPointLayout GetLayout(Windows.Devices.Input.PointerDeviceType deviceType)
{
switch (deviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
case Windows.Devices.Input.PointerDeviceType.Touch:
case Windows.Devices.Input.PointerDeviceType.Pen:
return new PathPointLayout(PathPoint.Property.X,
PathPoint.Property.Y,
PathPoint.Property.Size);
default:
throw new Exception("Unknown input device type");
}
}
public override Calculator GetCalculator(PointerDeviceType deviceType)
{
switch (deviceType)
{
case Windows.Devices.Input.PointerDeviceType.Mouse:
case Windows.Devices.Input.PointerDeviceType.Touch:
case Windows.Devices.Input.PointerDeviceType.Pen:
return CalculatorForMouseAndTouch;
default:
throw new Exception("Unknown input device type");
}
}
}
}
eraserWholeStroke: {
brush: BrushPalette.basic2,
intersector: new Intersector(Intersector.Mode.WHOLE_STROKE),
statics: {
size: 3,
red: 255,
green: 255,
blue: 255,
alpha: 0.5
}
},