diff --git a/Sources/arm/App.hx b/Sources/arm/App.hx index 0ceb8abd..f1e58aa5 100644 --- a/Sources/arm/App.hx +++ b/Sources/arm/App.hx @@ -390,7 +390,8 @@ class App { else if (dragMaterial != null) { // Material dragged onto viewport or layers tab if (inViewport || inLayers || in2dView) { - Layers.createFillLayer(); + var uvType = Input.getKeyboard().down("control") ? UVProject : UVMap; + Layers.createFillLayer(uvType); } else if (inNodes) { var index = 0; diff --git a/Sources/arm/Layers.hx b/Sources/arm/Layers.hx index 452d1ecd..8f891e86 100644 --- a/Sources/arm/Layers.hx +++ b/Sources/arm/Layers.hx @@ -614,10 +614,11 @@ class Layers { return l; } - public static function createFillLayer() { + public static function createFillLayer(uvType = UVMap) { function _init() { var l = newLayer(false); History.newLayer(); + l.uvType = uvType; l.objectMask = Context.layerFilter; History.toFillLayer(); l.toFillLayer(); diff --git a/Sources/arm/ProjectFormat.hx b/Sources/arm/ProjectFormat.hx index 75068474..6254defa 100644 --- a/Sources/arm/ProjectFormat.hx +++ b/Sources/arm/ProjectFormat.hx @@ -28,6 +28,7 @@ typedef TLayerData = { public var uv_scale: Float; public var uv_rot: Float; public var uv_type: Int; + public var decal_mat: kha.arrays.Float32Array; public var opacity_mask: Float; public var fill_layer: Int; public var fill_mask: Int; diff --git a/Sources/arm/data/LayerSlot.hx b/Sources/arm/data/LayerSlot.hx index 923b1c14..d726d8a3 100644 --- a/Sources/arm/data/LayerSlot.hx +++ b/Sources/arm/data/LayerSlot.hx @@ -44,9 +44,7 @@ class LayerSlot { public var paintHeight = true; public var paintEmis = true; public var paintSubs = true; - public var decalMat = iron.math.Mat4.identity(); // Decal layer - public var decalDim = new iron.math.Vec4(1, 1, 1); var createMaskColor: Int; var createMaskImage: Image; diff --git a/Sources/arm/io/ExportArm.hx b/Sources/arm/io/ExportArm.hx index 1578e9e8..37078737 100644 --- a/Sources/arm/io/ExportArm.hx +++ b/Sources/arm/io/ExportArm.hx @@ -58,6 +58,7 @@ class ExportArm { uv_scale: l.scale, uv_rot: l.angle, uv_type: l.uvType, + decal_mat: l.uvType == UVProject ? l.decalMat.toFloat32Array() : null, opacity_mask: l.maskOpacity, fill_layer: l.fill_layer != null ? Project.materials.indexOf(l.fill_layer) : -1, fill_mask: l.fill_mask != null ? Project.materials.indexOf(l.fill_mask) : -1, diff --git a/Sources/arm/io/ImportArm.hx b/Sources/arm/io/ImportArm.hx index bfd3d2f2..c51eef0a 100644 --- a/Sources/arm/io/ImportArm.hx +++ b/Sources/arm/io/ImportArm.hx @@ -11,6 +11,7 @@ import iron.data.MaterialData; import iron.data.MeshData; import iron.data.Data; import iron.data.SceneFormat; +import iron.math.Mat4; import iron.system.ArmPack; import iron.system.Lz4; import iron.object.Object; @@ -256,6 +257,7 @@ class ImportArm { l.scale = ld.uv_scale; l.angle = ld.uv_rot; l.uvType = ld.uv_type; + if (ld.decal_mat != null) l.decalMat = Mat4.fromFloat32Array(ld.decal_mat); l.maskOpacity = ld.opacity_mask; l.objectMask = ld.object_mask; l.blending = ld.blending; diff --git a/Sources/arm/node/MakeTexcoord.hx b/Sources/arm/node/MakeTexcoord.hx index bbcd0f78..d4faa360 100644 --- a/Sources/arm/node/MakeTexcoord.hx +++ b/Sources/arm/node/MakeTexcoord.hx @@ -21,12 +21,13 @@ class MakeTexcoord { frag.write_attrib('if (uvsp.x < 0.0 || uvsp.y < 0.0 || uvsp.x > 1.0 || uvsp.y > 1.0) discard;'); frag.n = true; - frag.write('if (abs(dot(n, vec3(0, 0, 1)) - 1.0) > 0.2) discard;'); + frag.add_uniform('vec3 decalLayerNor', '_decalLayerNor'); + frag.write('if (abs(dot(n, decalLayerNor) - 1.0) > 0.2) discard;'); - // frag.add_uniform('vec3 decalLayerLoc', '_decalLayerLoc'); - // frag.write_attrib('vec3 sdbox_q = abs(decalLayerLoc) - vec3(0.5, 0.5, 0.5);'); - // frag.write_attrib('float sdbox = length(max(sdbox_q, 0.0)) + min(max(sdbox_q.x, max(sdbox_q.y, sdbox_q.z)), 0.0);'); - // frag.write_attrib('if (sdbox > 0.5) discard;'); + frag.wposition = true; + frag.add_uniform('vec3 decalLayerLoc', '_decalLayerLoc'); + frag.add_uniform('float decalLayerDim', '_decalLayerDim'); + frag.write_attrib('if (abs(dot(decalLayerNor, decalLayerLoc - wposition)) > decalLayerDim) discard;'); } else if (decal) { frag.add_uniform('vec4 decalMask', '_decalMask'); diff --git a/Sources/arm/plugin/Gizmo.hx b/Sources/arm/plugin/Gizmo.hx index 687541c7..338034a8 100644 --- a/Sources/arm/plugin/Gizmo.hx +++ b/Sources/arm/plugin/Gizmo.hx @@ -16,6 +16,7 @@ class Gizmo { static var v = new Vec4(); static var v0 = new Vec4(); static var q = new Quat(); + static var q0 = new Quat(); public static function update() { @@ -132,19 +133,16 @@ class Gizmo { Context.object.transform.scale.z += Context.gizmoDrag - Context.gizmoDragLast; } else if (Context.rotateX) { - var euler = Context.object.transform.rot.getEuler(); - euler.x = Context.gizmoDrag; - Context.object.transform.rot.fromEuler(euler.x, euler.y, euler.z); + q0.fromAxisAngle(Vec4.xAxis(), Context.gizmoDrag - Context.gizmoDragLast); + Context.object.transform.rot.mult(q0); } else if (Context.rotateY) { - var euler = Context.object.transform.rot.getEuler(); - euler.y = Context.gizmoDrag; - Context.object.transform.rot.fromEuler(euler.x, euler.y, euler.z); + q0.fromAxisAngle(Vec4.yAxis(), Context.gizmoDrag - Context.gizmoDragLast); + Context.object.transform.rot.mult(q0); } else if (Context.rotateZ) { - var euler = Context.object.transform.rot.getEuler(); - euler.z = Context.gizmoDrag; - Context.object.transform.rot.fromEuler(euler.x, euler.y, euler.z); + q0.fromAxisAngle(Vec4.zAxis(), Context.gizmoDrag - Context.gizmoDragLast); + Context.object.transform.rot.mult(q0); } Context.gizmoDragLast = Context.gizmoDrag; @@ -184,23 +182,20 @@ class Gizmo { } else if (Context.rotateX) { Context.layer.decalMat.decompose(v, q, v0); - var euler = q.getEuler(); - euler.x = Context.gizmoDrag; - q.fromEuler(euler.x, euler.y, euler.z); + q0.fromAxisAngle(Vec4.xAxis(), -Context.gizmoDrag + Context.gizmoDragLast); + q.multquats(q0, q); Context.layer.decalMat.compose(v, q, v0); } else if (Context.rotateY) { Context.layer.decalMat.decompose(v, q, v0); - var euler = q.getEuler(); - euler.y = Context.gizmoDrag; - q.fromEuler(euler.x, euler.y, euler.z); + q0.fromAxisAngle(Vec4.yAxis(), -Context.gizmoDrag + Context.gizmoDragLast); + q.multquats(q0, q); Context.layer.decalMat.compose(v, q, v0); } else if (Context.rotateZ) { Context.layer.decalMat.decompose(v, q, v0); - var euler = q.getEuler(); - euler.z = Context.gizmoDrag; - q.fromEuler(euler.x, euler.y, euler.z); + q0.fromAxisAngle(Vec4.zAxis(), Context.gizmoDrag - Context.gizmoDragLast); + q.multquats(q0, q); Context.layer.decalMat.compose(v, q, v0); } Context.gizmoDragLast = Context.gizmoDrag; @@ -288,9 +283,9 @@ class Gizmo { if (hit != null) { if (Context.gizmoStarted) { Context.layer.decalMat.decompose(v, q, v0); - Context.gizmoOffset = q.getEuler().x - Math.atan2(hit.y - v.y, hit.z - v.z); + Context.gizmoOffset = Math.atan2(hit.y - v.y, hit.z - v.z); } - Context.gizmoDrag = Context.gizmoOffset + Math.atan2(hit.y - v.y, hit.z - v.z); + Context.gizmoDrag = Math.atan2(hit.y - v.y, hit.z - v.z) - Context.gizmoOffset; } } else if (Context.rotateY) { @@ -298,9 +293,9 @@ class Gizmo { if (hit != null) { if (Context.gizmoStarted) { Context.layer.decalMat.decompose(v, q, v0); - Context.gizmoOffset = q.getEuler().y - Math.atan2(hit.z - v.z, hit.x - v.x); + Context.gizmoOffset = Math.atan2(hit.z - v.z, hit.x - v.x); } - Context.gizmoDrag = Context.gizmoOffset + Math.atan2(hit.z - v.z, hit.x - v.x); + Context.gizmoDrag = Math.atan2(hit.z - v.z, hit.x - v.x) - Context.gizmoOffset; } } else if (Context.rotateZ) { @@ -308,9 +303,9 @@ class Gizmo { if (hit != null) { if (Context.gizmoStarted) { Context.layer.decalMat.decompose(v, q, v0); - Context.gizmoOffset = q.getEuler().z - Math.atan2(hit.y - v.y, hit.x - v.x); + Context.gizmoOffset = Math.atan2(hit.y - v.y, hit.x - v.x); } - Context.gizmoDrag = Context.gizmoOffset + Math.atan2(hit.y - v.y, hit.x - v.x); + Context.gizmoDrag = Math.atan2(hit.y - v.y, hit.x - v.x) - Context.gizmoOffset; } } diff --git a/Sources/arm/render/LineDraw.hx b/Sources/arm/render/LineDraw.hx index 31e6bd66..c9356e15 100644 --- a/Sources/arm/render/LineDraw.hx +++ b/Sources/arm/render/LineDraw.hx @@ -42,14 +42,13 @@ class LineDraw { public static function render(g4: kha.graphics4.Graphics) { - return; //// - + var hide = Operator.shortcut(Config.keymap.stencil_hide, ShortcutDown); var isPaint = UIHeader.inst.worktab.position == SpacePaint; var isDecal = isPaint && Context.layer.fill_layer != null && Context.layer.uvType == UVProject; - if (!isDecal) return; + if (!isDecal || hide) return; mat = Context.layer.decalMat; - dim = Context.layer.decalDim; + dim = Context.layer.decalMat.getScale(); g = g4; diff --git a/Sources/arm/render/Uniforms.hx b/Sources/arm/render/Uniforms.hx index be7241a5..1c8cdf1c 100644 --- a/Sources/arm/render/Uniforms.hx +++ b/Sources/arm/render/Uniforms.hx @@ -97,6 +97,9 @@ class Uniforms { case "_dilateRadius": { return UVUtil.dilatemap != null ? Config.raw.dilate_radius : 0.0; } + case "_decalLayerDim": { + return Context.layer.decalMat.getScale().z * 0.5; + } } if (MaterialParser.script_links != null) { for (key in MaterialParser.script_links.keys()) { @@ -173,6 +176,11 @@ class Uniforms { v.set(Context.layer.decalMat._30, Context.layer.decalMat._31, Context.layer.decalMat._32); return v; } + case "_decalLayerNor": { + v = iron.object.Uniforms.helpVec; + v.set(Context.layer.decalMat._20, Context.layer.decalMat._21, Context.layer.decalMat._22).normalize(); + return v; + } } return v; diff --git a/Sources/arm/ui/UIView2D.hx b/Sources/arm/ui/UIView2D.hx index ee0c60af..63be1a5a 100644 --- a/Sources/arm/ui/UIView2D.hx +++ b/Sources/arm/ui/UIView2D.hx @@ -266,7 +266,9 @@ class UIView2D { return; } - if (mouse.down("right") || mouse.down("middle") || (mouse.down("left") && kb.down("ctrl"))) { + var decal = Context.tool == ToolDecal || Context.tool == ToolText; + + if (mouse.down("right") || mouse.down("middle") || (mouse.down("left") && kb.down("control") && !decal)) { panX += mouse.movementX; panY += mouse.movementY; } @@ -280,7 +282,6 @@ class UIView2D { panY = _panY * panScale; } - var decal = Context.tool == ToolDecal || Context.tool == ToolText; var decalMask = decal && Operator.shortcut(Config.keymap.decal_mask + "+" + Config.keymap.action_paint, ShortcutDown); var setCloneSource = Context.tool == ToolClone && Operator.shortcut(Config.keymap.set_clone_source + "+" + Config.keymap.action_paint, ShortcutDown);