Stencil mask for brush

This commit is contained in:
luboslenco
2020-03-13 17:22:16 +01:00
parent 2d0ffe37de
commit e624b0e6ea
10 changed files with 106 additions and 10 deletions
+3 -1
View File
@@ -3,7 +3,9 @@
"action_rotate": "middle",
"action_pan": "shift+middle",
"action_zoom": "ctrl+middle",
"action_rotate_light": "shift+middle",
"rotate_light": "shift+middle",
"set_clone_source": "alt",
"stencil_transform": "ctrl",
"select_material": "shift+number",
"cycle_layers": "ctrl+tab",
"brush_radius": "f",
+3 -1
View File
@@ -3,7 +3,9 @@
"action_rotate": "alt+left",
"action_pan": "alt+middle",
"action_zoom": "alt+right",
"action_rotate_light": "shift+middle",
"rotate_light": "shift+middle",
"set_clone_source": "alt",
"stencil_transform": "ctrl",
"select_material": "shift+number",
"cycle_layers": "ctrl+tab",
"brush_radius": "f",
+2
View File
@@ -72,7 +72,9 @@ class Context {
if (Project.brushes.length <= i) return;
brush = Project.brushes[i];
MaterialParser.parseBrush();
UITrait.inst.parseBrushInputs();
UITrait.inst.hwnd1.redraws = 2;
UINodes.inst.hwnd.redraws = 2;
}
public static function setLayer(l: LayerSlot, isMask = false) {
+16
View File
@@ -221,6 +221,22 @@ class MakePaint {
frag.write('opacity *= textureLod(textexttool, texCoord, 0.0).r;');
}
if (UITrait.inst.brushStencilImage != null && (
Context.tool == ToolBrush ||
Context.tool == ToolEraser ||
Context.tool == ToolFill ||
Context.tool == ToolClone ||
Context.tool == ToolBlur ||
Context.tool == ToolParticle ||
decal)) {
frag.add_uniform('sampler2D texbrushstencil', '_texbrushstencil');
frag.add_uniform('vec4 stencilTransform', '_stencilTransform');
frag.write('vec2 stencil_uv = vec2((sp.xy - stencilTransform.xy) / stencilTransform.z * vec2(aspectRatio, 1.0));');
frag.write('if (stencil_uv.x < 0 || stencil_uv.x > 1 || stencil_uv.y < 0 || stencil_uv.y > 1) discard;');
frag.write('vec4 texbrushstencil_sample = textureLod(texbrushstencil, stencil_uv, 0.0);');
frag.write('opacity *= texbrushstencil_sample.r * texbrushstencil_sample.a;');
}
if (UITrait.inst.brushMaskImage != null && (Context.tool == ToolBrush || Context.tool == ToolEraser)) {
frag.add_uniform('sampler2D texbrushmask', '_texbrushmask');
frag.write('vec2 binp_mask = inp.xy * 2.0 - 1.0;');
+2 -2
View File
@@ -67,14 +67,14 @@ class Camera {
dist -= f;
}
if (mouse.wheelDelta != 0) {
if (mouse.wheelDelta != 0 && !modif) {
redraws = 2;
var f = mouse.wheelDelta * (-0.1);
camera.transform.move(camera.look(), f);
dist -= f;
}
if (Operator.shortcut(Config.keymap.action_rotate_light)) {
if (Operator.shortcut(Config.keymap.rotate_light)) {
redraws = 2;
var light = iron.Scene.active.lights[0];
var m = iron.math.Mat4.identity();
+8
View File
@@ -281,6 +281,11 @@ class Uniforms {
if (UITrait.inst.paint2d) vec2.x -= 1.0;
return vec2;
}
if (link == "_stencilTransform") {
vec2.set(UITrait.inst.brushStencilX, UITrait.inst.brushStencilY, UITrait.inst.brushStencilScale, 0.0);
if (UITrait.inst.paint2d) vec2.x -= 1.0;
return vec2;
}
#end
return null;
}
@@ -305,6 +310,9 @@ class Uniforms {
if (link == "_texbrushmask") {
return UITrait.inst.brushMaskImage;
}
if (link == "_texbrushstencil") {
return UITrait.inst.brushStencilImage;
}
if (link == "_texpaint_undo") {
var i = History.undoI - 1 < 0 ? Config.raw.undo_steps - 1 : History.undoI - 1;
return RenderPath.active.renderTargets.get("texpaint_undo" + i).image;
+3
View File
@@ -3,6 +3,7 @@ package arm.ui;
import iron.system.Time;
import zui.Zui;
import arm.data.BrushSlot;
import arm.node.MaterialParser;
class TabBrushes {
@@ -14,6 +15,8 @@ class TabBrushes {
if (ui.button("New")) {
Context.brush = new BrushSlot();
Project.brushes.push(Context.brush);
MaterialParser.parseBrush();
UITrait.inst.parseBrushInputs();
UINodes.inst.hwnd.redraws = 2;
}
if (ui.button("Import")) {}
+1
View File
@@ -58,6 +58,7 @@ class TabTextures {
if (Time.time() - UITrait.inst.selectTime < 0.25) UITrait.inst.show2DView(1);
UITrait.inst.selectTime = Time.time();
UIView2D.inst.hwnd.redraws = 2;
}
var _uix = ui._x;
+59 -3
View File
@@ -26,6 +26,7 @@ import arm.io.ImportFont;
import arm.io.ExportTexture;
import arm.Tool;
import arm.Project;
import arm.Res;
@:access(zui.Zui)
class UITrait {
@@ -174,6 +175,11 @@ class UITrait {
public var brushNodesOpacity = 1.0;
public var brushMaskImage: Image = null;
public var brushStencilImage: Image = null;
public var brushStencilX = 0.02;
public var brushStencilY = 0.02;
public var brushStencilRot = 0.0;
public var brushStencilScale = 0.9;
public var brushStencilScaling = false;
public var brushNodesScale = 1.0;
public var brushNodesHardness = 1.0;
@@ -656,6 +662,18 @@ class UITrait {
return 0.1;
}
static function hitRect(mx: Float, my: Float, x: Int, y: Int, w: Int, h: Int) {
return mx > x && mx < x + w && my > y && my < y + h;
}
function getBrushRect(): TRect {
var w = Std.int(brushStencilImage.width * (App.h() / brushStencilImage.height) * brushStencilScale);
var h = Std.int(App.h() * brushStencilScale);
var x = Std.int(App.x() + brushStencilX * App.w());
var y = Std.int(App.y() + brushStencilY * App.h());
return { w: w, h: h, x: x, y: y };
}
function updateUI() {
if (Log.messageTimer > 0) {
@@ -668,7 +686,36 @@ class UITrait {
var mouse = Input.getMouse();
var kb = Input.getKeyboard();
var setCloneSource = Context.tool == ToolClone && Operator.shortcut("alt+" + Config.keymap.action_paint);
var setCloneSource = Context.tool == ToolClone && Operator.shortcut(Config.keymap.set_clone_source + "+" + Config.keymap.action_paint);
if (brushStencilImage != null && Operator.shortcut(Config.keymap.stencil_transform)) {
var r = getBrushRect();
if (mouse.started("left")) {
brushStencilScaling =
hitRect(mouse.x, mouse.y, r.x - 8, r.y - 8, 16, 16) ||
hitRect(mouse.x, mouse.y, r.x - 8, r.h + r.y - 8, 16, 16) ||
hitRect(mouse.x, mouse.y, r.w + r.x - 8, r.y - 8, 16, 16) ||
hitRect(mouse.x, mouse.y, r.w + r.x - 8, r.h + r.y - 8, 16, 16);
}
var _scale = brushStencilScale;
if (mouse.down("left")) {
if (brushStencilScaling) {
var mult = mouse.x > r.x + r.w / 2 ? 1 : -1;
brushStencilScale += mouse.movementX / 500 * mult;
}
else {
brushStencilX += mouse.movementX / App.w();
brushStencilY += mouse.movementY / App.h();
}
}
else brushStencilScaling = false;
if (mouse.wheelDelta != 0) {
brushStencilScale -= mouse.wheelDelta / 10;
}
// Center after scale
brushStencilX += (_scale * brushStencilImage.width - brushStencilScale * brushStencilImage.width) / 2 / App.w();
brushStencilY += (_scale * brushStencilImage.height - brushStencilScale * brushStencilImage.height) / 2 / App.h();
}
var down = Operator.shortcut(Config.keymap.action_paint) ||
setCloneSource ||
@@ -813,9 +860,18 @@ class UITrait {
}
if (brushStencilImage != null && Context.tool != ToolBake && Context.tool != ToolPicker && Context.tool != ToolColorId) {
g.color = 0xaaffffff;
g.drawImage(brushStencilImage, 0, 0);
var transform = Operator.shortcut(Config.keymap.stencil_transform);
g.color = 0x88ffffff;
var r = getBrushRect();
g.drawScaledImage(brushStencilImage, r.x, r.y, r.w, r.h);
g.color = 0xffffffff;
if (transform) {
g.drawRect(r.x, r.y, r.w, r.h);
g.drawRect(r.x - 8, r.y - 8, 16, 16);
g.drawRect(r.x - 8 + r.w, r.y - 8, 16, 16);
g.drawRect(r.x - 8, r.y - 8 + r.h, 16, 16);
g.drawRect(r.x - 8 + r.w, r.y - 8 + r.h, 16, 16);
}
}
// Show picked material next to cursor
+9 -3
View File
@@ -95,7 +95,6 @@ class UIView2D {
ui.g.drawImage(UINodes.inst.grid, (panX * panScale) % 40 - 40, (panY * panScale) % 40 - 40);
// Texture
ui.g.pipeline = pipe;
var l = Context.layer;
var tex: Image = null;
var channel = 0;
@@ -127,9 +126,16 @@ class UIView2D {
var th = tw;
if (tex != null) {
th = tw * (tex.height / tex.width);
drawLayer(tex, tx, ty, tw, th, channel);
}
ui.g.pipeline = null;
if (type == View2DLayer) {
ui.g.pipeline = pipe;
drawLayer(tex, tx, ty, tw, th, channel);
ui.g.pipeline = null;
}
else {
ui.g.drawScaledImage(tex, tx, ty, tw, th);
}
// UV map
if (type == View2DLayer && uvmapShow) {