Stencil mask for brush
This commit is contained in:
@@ -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,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",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;');
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,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")) {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user