Merge branch 'tiled-texture-view' into next

This commit is contained in:
JannisX11 2024-08-30 19:40:49 +02:00
commit 596ef01379
7 changed files with 107 additions and 5 deletions

View File

@ -2062,7 +2062,8 @@ span.controller_state_section_info {
pointer-events: none;
}
body[mode=paint] #uv_frame {
body[mode=paint] #uv_frame,
body[mode=paint] #uv_viewport.tiled_mode {
cursor: crosshair;
}
#uv_frame > #texture_canvas_wrapper > canvas,
@ -2076,6 +2077,16 @@ span.controller_state_section_info {
object-fit: cover;
object-position: 0 0;
}
#uv_frame > #texture_canvas_wrapper > canvas.overlay_canvas[overlay_mode=tiled] {
width: 300%;
height: 300%;
margin-left: -100%;
margin-top: -100%;
}
#uv_frame > #texture_canvas_wrapper > canvas.overlay_canvas[overlay_mode=onion_skin] {
width: 100%;
height: 100%;
}
/* Fix in Firefox + iPadOS */
#uv_frame_spacer {
width: 1px;
@ -2092,6 +2103,8 @@ span.controller_state_section_info {
left: 0;
object-fit: cover;
object-position: 0 0;
margin: -1px;
border: 1px solid var(--color-grid);
}
#uv_texture_grid path {
fill: none;

View File

@ -2262,6 +2262,8 @@ const BARS = {
'color_erase_mode',
'lock_alpha',
'painting_grid',
'image_tiled_view',
'image_onion_skin_view',
]
})
Toolbars.vertex_snap = new Toolbar({

View File

@ -249,7 +249,16 @@ const Painter = {
} else {
texture.edit(canvas => {
Painter.drawBrushLine(texture, x, y, event, new_face, uv)
let is_line = true;
if (BarItems.image_tiled_view.value == true && (Math.abs(Painter.current.x - x) > texture.width/2 || Math.abs(Painter.current.y - y) > texture.display_height/2)) {
is_line = false;
}
if (is_line) {
Painter.drawBrushLine(texture, x, y, event, new_face, uv);
} else {
Painter.current.x = Painter.current.y = 0
Painter.useBrushlike(texture, x, y, event, uv)
}
}, {no_undo: true, use_cache: true});
}
Painter.current.x = x;
@ -3050,12 +3059,37 @@ BARS.defineActions(function() {
})
new Toggle('painting_grid', {
icon: 'grid_on',
icon: 'grid_3x3',
category: 'view',
condition: {modes: ['paint']},
keybind: new Keybind({key: 'g'}),
linked_setting: 'painting_grid'
})
new Toggle('image_tiled_view', {
category: 'paint',
icon: 'grid_view',
onChange(value) {
if (value && BarItems.image_onion_skin_view.value) {
BarItems.image_onion_skin_view.set(false);
}
UVEditor.vue.overlay_canvas_mode = value ? 'tiled' : null;
UVEditor.vue.updateTexture();
UVEditor.updateOverlayCanvas();
}
})
new Toggle('image_onion_skin_view', {
category: 'paint',
icon: 'animation',
condition: () => Panels.textures.vue.maxFrameCount(),
onChange(value) {
if (value && BarItems.image_tiled_view.value) {
BarItems.image_tiled_view.set(false);
}
UVEditor.vue.overlay_canvas_mode = value ? 'onion_skin' : null;
UVEditor.vue.updateTexture();
UVEditor.updateOverlayCanvas();
}
})
new NumSlider('slider_brush_size', {
condition: () => (Toolbox && ((Toolbox.selected.brush?.size == true) || ['draw_shape_tool'].includes(Toolbox.selected.id))),

View File

@ -127,6 +127,7 @@ BARS.defineActions(function() {
change: function(modify) {
let slider_tex = getSliderTexture()
if (!slider_tex) return;
UVEditor.previous_animation_frame = slider_tex.currentFrame;
slider_tex.currentFrame = (modify(slider_tex.currentFrame + slider_tex.frameCount) % slider_tex.frameCount) || 0;
let textures = Texture.all.filter(tex => tex.frameCount > 1);

View File

@ -206,6 +206,7 @@ class Texture {
scope.canvas.width = scope.width;
scope.canvas.height = scope.height;
scope.ctx.drawImage(img, 0, 0);
if (UVEditor.vue.texture == this) UVEditor.updateOverlayCanvas();
}
if (this.flags.has('update_uv_size_from_resolution')) {
@ -1745,6 +1746,7 @@ class Texture {
this.source = this.canvas.toDataURL('image/png', 1);
this.updateImageFromCanvas();
}
if (UVEditor.vue.texture == this) UVEditor.updateOverlayCanvas();
}
updateChangesAfterEdit() {
if (this.layers_enabled) {
@ -2645,12 +2647,15 @@ Interface.definePanels(function() {
convertTouchEvent(e2);
let pos = e2.clientX - timeline_offset;
let previous_frame = scope.currentFrame;
scope.currentFrame = Math.clamp(Math.round((pos / timeline_width) * maxFrameCount), 0, maxFrameCount-1);
if (previous_frame == scope.currentFrame) return;
let textures = Texture.all.filter(tex => tex.frameCount > 1);
Texture.all.forEach(tex => {
tex.currentFrame = (scope.currentFrame % tex.frameCount) || 0;
})
UVEditor.previous_animation_frame = previous_frame;
TextureAnimator.update(textures);
}
function off(e3) {

View File

@ -7,6 +7,12 @@ const UVEditor = {
panel: null,
sliders: {},
selected_element_faces: {},
previous_animation_frame: 1,
overlay_canvas: (() => {
let canvas = document.createElement('canvas');
canvas.classList.add('overlay_canvas');
return canvas;
})(),
get vue() {
return this.panel.inside_vue;
@ -60,6 +66,10 @@ const UVEditor = {
if (tex) {
if (tex.frameCount) result.y += (tex.height / tex.frameCount) * tex.currentFrame;
if (!tex.frameCount && tex.ratio != tex.getUVWidth() / tex.getUVHeight()) result.y /= tex.ratio;
if (BarItems.image_tiled_view.value == true) {
result.x = (tex.width + result.x) % tex.width;
result.y = (tex.display_height + result.y) % tex.display_height;
}
}
return result;
},
@ -248,6 +258,30 @@ const UVEditor = {
scrollTop: focus[1] + margin[1] - UVEditor.height / 2,
}, 100)
},
updateOverlayCanvas() {
if (!Texture.selected) return;
let canvas = UVEditor.overlay_canvas;
let texture = Texture.selected;
let ctx = canvas.getContext('2d');
if (BarItems.image_tiled_view.value == true) {
canvas.setAttribute('overlay_mode', 'tiled');
canvas.width = texture.width * 3;
canvas.height = texture.display_height * 3;
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
ctx.drawImage(texture.canvas, x * texture.width, y * texture.display_height);
}
}
} else if (BarItems.image_onion_skin_view.value == true) {
canvas.setAttribute('overlay_mode', 'onion_skin');
canvas.width = texture.width;
canvas.height = texture.display_height;
ctx.filter = `opacity(${45}%)`;
let frame = Math.clamp(UVEditor.previous_animation_frame, 0, texture.frameCount-1);
ctx.drawImage(texture.canvas, 0, frame * -texture.display_height);
}
},
//Get
get width() {
return this.vue.width;
@ -2105,6 +2139,7 @@ Interface.definePanels(function() {
copy_brush_source: null,
helper_lines: {x: -1, y: -1},
brush_type: BarItems.brush_shape.value,
overlay_canvas_mode: null,
selection_rect: {
pos_x: 0,
pos_y: 0,
@ -2316,12 +2351,19 @@ Interface.definePanels(function() {
this.texture.canvas.style.objectFit = this.texture.frameCount > 1 ? 'cover' : 'fill';
this.texture.canvas.style.imageRendering = this.texture.width < this.inner_width ? 'inherit' : 'auto';
UVEditor.updateOverlayCanvas();
Vue.nextTick(() => {
let wrapper = this.$refs.texture_canvas_wrapper;
if (!wrapper || wrapper.firstChild == this.texture.canvas) return;
if (wrapper.firstChild) {
let overlay_canvas_mode = this.overlay_canvas_mode;
if (this.mode != 'paint') overlay_canvas_mode = null;
if (!wrapper || (wrapper.firstChild == this.texture.canvas && !overlay_canvas_mode)) return;
while (wrapper.firstChild) {
wrapper.firstChild.remove();
}
if (UVEditor.overlay_canvas && overlay_canvas_mode) {
wrapper.append(UVEditor.overlay_canvas);
}
wrapper.append(this.texture.canvas);
})
},
@ -3941,6 +3983,7 @@ Interface.definePanels(function() {
@mouseenter="onMouseEnter($event)"
@mouseleave="onMouseLeave($event)"
class="checkerboard_target"
:class="{tiled_mode: overlay_canvas_mode == 'tiled'}"
ref="viewport"
v-if="!hidden && mode !== 'face_properties'"
:style="{width: (width+8) + 'px', height: (height+8) + 'px', overflowX: (zoom > 1) ? 'scroll' : 'hidden', overflowY: (inner_height > height) ? 'scroll' : 'hidden'}"

View File

@ -1169,6 +1169,10 @@
"action.mirror_painting.description": "Mirror your paint strokes to the other side of the model",
"action.lock_alpha": "Lock Alpha Channel",
"action.lock_alpha.description": "Lock the transparency of all pixels",
"action.image_tiled_view": "Tiled View",
"action.image_tiled_view.description": "Enable the tiled view in the 2D editor",
"action.image_onion_skin_view": "Image Editor Onion Skin",
"action.image_onion_skin_view.description": "Enable the onion skin view in the 2D editor",
"action.slider_brush_size": "Size",
"action.slider_brush_size.desc": "Radius of the brush in pixels",
"action.slider_brush_opacity": "Opacity",