Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions js/interface/setup_settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ function setupSettings() {
//Defaults
new Setting('default_cube_size', {category: 'defaults', value: 2, type: 'number', min: 0, max: 32});
new Setting('autouv', {category: 'defaults', value: true});
new Setting('clampuv', {category: 'defaults', value: true});
new Setting('inherit_parent_color', {category: 'defaults', value: false});
new Setting('create_rename', {category: 'defaults', value: false});
new Setting('show_only_selected_uv', {category: 'defaults', value: false});
Expand Down
159 changes: 101 additions & 58 deletions js/texturing/uv.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,9 @@ export const UVEditor = {
if (zoom) {
let width = (max_x-min_x) / UVEditor.getUVWidth();
let height = (max_y-min_y) / UVEditor.getUVHeight();
let target_zoom_factor = 1/Math.max(width, height);
let target_zoom = Math.clamp(UVEditor.zoom, target_zoom_factor * 0.618, Math.max(1, target_zoom_factor * 0.84));
let target_zoom = 1/Math.max(width, height);
if (settings.clampuv.value)
target_zoom = Math.clamp(UVEditor.zoom, target_zoom_factor * 0.618, Math.max(1, target_zoom_factor * 0.84));
UVEditor.setZoom(target_zoom);
await new Promise(Vue.nextTick);
}
Expand Down Expand Up @@ -487,8 +488,11 @@ export const UVEditor = {
},
//Set
setZoom(zoom) {
let max_zoom = Math.round((this.vue.texture ? this.vue.texture.height : Project.texture_width) * 32 / UVEditor.width);
zoom = Math.clamp(zoom, UVEditor.height > 800 ? 0.2 : 0.5, Math.clamp(max_zoom, 16, 64))
if (settings.clampuv.value) {
let max_zoom = Math.round(
(this.vue.texture ? this.vue.texture.height : Project.texture_width) * 32 / UVEditor.width);
zoom = Math.clamp(zoom, UVEditor.height > 800 ? 0.2 : 0.5, Math.clamp(max_zoom, 16, 64))
}
this.vue.zoom = zoom;
Project.uv_viewport.zoom = this.zoom;
Vue.nextTick(() => {
Expand Down Expand Up @@ -955,12 +959,14 @@ export const UVEditor = {
obj.faces[side].uv[0] -= uv[1];
obj.faces[side].uv[2] -= uv[1];
}
let overlap_px = Math.clamp(Math.max(obj.faces[side].uv[0], obj.faces[side].uv[2]) - UVEditor.getUVWidth(), 0, Infinity);
obj.faces[side].uv[0] -= overlap_px;
obj.faces[side].uv[2] -= overlap_px;
let overlap_py = Math.clamp(Math.max(obj.faces[side].uv[1], obj.faces[side].uv[3]) - UVEditor.getUVHeight(), 0, Infinity);
obj.faces[side].uv[1] -= overlap_py;
obj.faces[side].uv[3] -= overlap_py;
if (settings.clampuv.value) {
let overlap_px = Math.clamp(Math.max(obj.faces[side].uv[0], obj.faces[side].uv[2]) - UVEditor.getUVWidth(), 0, Infinity);
obj.faces[side].uv[0] -= overlap_px;
obj.faces[side].uv[2] -= overlap_px;
let overlap_py = Math.clamp(Math.max(obj.faces[side].uv[1], obj.faces[side].uv[3]) - UVEditor.getUVHeight(), 0, Infinity);
obj.faces[side].uv[1] -= overlap_py;
obj.faces[side].uv[3] -= overlap_py;
}
})
obj.autouv = 0;
obj.preview_controller.updateUV(obj);;
Expand Down Expand Up @@ -1001,12 +1007,17 @@ export const UVEditor = {
if (face.rotation % 180) {
[width, height] = [height, width];
}
width *= UVEditor.getResolution(0, face) / UVEditor.getUVWidth();
height *= UVEditor.getResolution(1, face) / UVEditor.getUVHeight();
width = Math.clamp(width, 0, UVEditor.getUVWidth());
height = Math.clamp(height, 0, UVEditor.getUVHeight());
face.uv[0] = Math.min(face.uv[0], UVEditor.getUVWidth() - width);
face.uv[1] = Math.min(face.uv[1], UVEditor.getUVHeight() - height);
const uv_width = UVEditor.getUVWidth();
const uv_height = UVEditor.getUVHeight();
width *= UVEditor.getResolution(0, face) / uv_width;
height *= UVEditor.getResolution(1, face) / uv_height;
if (settings.clampuv.value)
{
width = Math.clamp(width, 0, uv_width);
height = Math.clamp(height, 0, uv_height);
face.uv[0] = Math.min(face.uv[0], uv_width - width);
face.uv[1] = Math.min(face.uv[1], uv_height - height);
}
face.uv_size = [width, height];
// left2 *= UVEditor.getResolution(0, face) / UVEditor.getUVWidth();
// top2 *= UVEditor.getResolution(1, face) / UVEditor.getUVHeight();
Expand Down Expand Up @@ -1345,8 +1356,12 @@ export const UVEditor = {
face.uv[vkey][1] -= center[1];
let a = (face.uv[vkey][0] * cos - face.uv[vkey][1] * sin);
let b = (face.uv[vkey][0] * sin + face.uv[vkey][1] * cos);
face.uv[vkey][0] = Math.clamp(a + center[0], 0, UVEditor.getUVWidth());
face.uv[vkey][1] = Math.clamp(b + center[1], 0, UVEditor.getUVHeight());
face.uv[vkey][0] = a + center[0];
face.uv[vkey][1] = b + center[1];
if (settings.clampuv.value) {
face.uv[vkey][0] = Math.clamp(face.uv[vkey][0], 0, UVEditor.getUVWidth());
face.uv[vkey][1] = Math.clamp(face.uv[vkey][1], 0, UVEditor.getUVHeight());
}
})
})
Mesh.preview_controller.updateUV(mesh);
Expand Down Expand Up @@ -2184,8 +2199,12 @@ BARS.defineActions(function() {
if (!face || face == face1) return;
face.vertices.forEach(vkey => {
if (!face.uv[vkey]) return;;
face.uv[vkey][0] = Math.clamp(face.uv[vkey][0] + offset[0], 0, Project.texture_width);
face.uv[vkey][1] = Math.clamp(face.uv[vkey][1] + offset[1], 0, Project.texture_height);
face.uv[vkey][0] = face.uv[vkey][0];
face.uv[vkey][1] = face.uv[vkey][1];
if (settings.clampuv.value) {
face.uv[vkey][0] = Math.clamp(face.uv[vkey][0], 0, Project.texture_width);
face.uv[vkey][1] = Math.clamp(face.uv[vkey][1], 0, Project.texture_height);
}
})
})

Expand Down Expand Up @@ -2216,15 +2235,25 @@ BARS.defineActions(function() {
if (element instanceof Mesh) {
face.vertices.forEach(vkey => {
if ((!selected_vertices.length || selected_vertices.includes(vkey)) && face.uv[vkey]) {
face.uv[vkey][0] = Math.clamp(Math.round(face.uv[vkey][0] / res_x) * res_x, 0, UVEditor.getUVWidth());
face.uv[vkey][1] = Math.clamp(Math.round(face.uv[vkey][1] / res_y) * res_y, 0, UVEditor.getUVHeight());
face.uv[vkey][0] = Math.round(face.uv[vkey][0] / res_x) * res_x;
face.uv[vkey][1] = Math.round(face.uv[vkey][1] / res_y) * res_y;
if (settings.clampuv.value) {
face.uv[vkey][0] = Math.clamp(face.uv[vkey][0], 0, UVEditor.getUVWidth());
face.uv[vkey][1] = Math.clamp(face.uv[vkey][1], 0, UVEditor.getUVHeight());
}
}
})
} else if (face instanceof CubeFace) {
face.uv[0] = Math.clamp(Math.round(face.uv[0] / res_x) * res_x, 0, UVEditor.getUVWidth());
face.uv[1] = Math.clamp(Math.round(face.uv[1] / res_y) * res_y, 0, UVEditor.getUVHeight());
face.uv[2] = Math.clamp(Math.round(face.uv[2] / res_x) * res_x, 0, UVEditor.getUVWidth());
face.uv[3] = Math.clamp(Math.round(face.uv[3] / res_y) * res_y, 0, UVEditor.getUVHeight());
} else if (element instanceof CubeFace) {
face.uv[0] = Math.round(face.uv[0] / res_x) * res_x;
face.uv[1] = Math.round(face.uv[1] / res_y) * res_y;
face.uv[2] = Math.round(face.uv[2] / res_x) * res_x;
face.uv[3] = Math.round(face.uv[3] / res_y) * res_y;
if (settings.clampuv.value) {
face.uv[0] = Math.clamp(face.uv[0], 0, UVEditor.getUVWidth());
face.uv[1] = Math.clamp(face.uv[1], 0, UVEditor.getUVHeight());
face.uv[2] = Math.clamp(face.uv[2], 0, UVEditor.getUVWidth());
face.uv[3] = Math.clamp(face.uv[3], 0, UVEditor.getUVHeight());
}
}
})
element.preview_controller.updateUV(element);
Expand Down Expand Up @@ -3178,29 +3207,35 @@ Interface.definePanels(function() {
UVEditor.getSelectedFaces(element).forEach(key => {
let face = element.faces[key];
if (!face) return;
face.vertices.forEach(vertex_key => {
diff_x = Math.clamp(diff_x, -face.uv[vertex_key][0], UVEditor.getUVWidth() - face.uv[vertex_key][0]);
diff_y = Math.clamp(diff_y, -face.uv[vertex_key][1], UVEditor.getUVHeight() - face.uv[vertex_key][1]);
})
if (settings.clampuv.value) {
face.vertices.forEach(vertex_key => {
diff_x = Math.clamp(diff_x, -face.uv[vertex_key][0], UVEditor.getUVWidth() - face.uv[vertex_key][0]);
diff_y = Math.clamp(diff_y, -face.uv[vertex_key][1], UVEditor.getUVHeight() - face.uv[vertex_key][1]);
})
}
})
} else if (element.box_uv) {
let size = element.size(undefined, Format.box_uv_float_size != true);
let uv_size = [
size[2] + size[0] + (size[1] ? size[2] : 0) + size[0],
size[2] + size[1],
]
diff_x = Math.clamp(diff_x, -element.uv_offset[0] - (size[1] ? 0 : size[2]), UVEditor.getUVWidth() - element.uv_offset[0] - uv_size[0]);
diff_y = Math.clamp(diff_y, -element.uv_offset[1] - (size[0] ? 0 : size[2]), UVEditor.getUVHeight() - element.uv_offset[1] - uv_size[1]);
if (settings.clampuv.value) {
diff_x = Math.clamp(diff_x, -element.uv_offset[0] - (size[1] ? 0 : size[2]), UVEditor.getUVWidth() - element.uv_offset[0] - uv_size[0]);
diff_y = Math.clamp(diff_y, -element.uv_offset[1] - (size[0] ? 0 : size[2]), UVEditor.getUVHeight() - element.uv_offset[1] - uv_size[1]);
}

} else {
UVEditor.getSelectedFaces(element).forEach(key => {
if (element.faces[key] && element.getTypeBehavior('cube_faces') && element.faces[key].texture !== null) {
diff_x = Math.clamp(diff_x, -element.faces[key].uv[0], UVEditor.getUVWidth() - element.faces[key].uv[0]);
diff_y = Math.clamp(diff_y, -element.faces[key].uv[1], UVEditor.getUVHeight() - element.faces[key].uv[1]);
diff_x = Math.clamp(diff_x, -element.faces[key].uv[2], UVEditor.getUVWidth() - element.faces[key].uv[2]);
diff_y = Math.clamp(diff_y, -element.faces[key].uv[3], UVEditor.getUVHeight() - element.faces[key].uv[3]);
}
})
if (settings.clampuv.value) {
UVEditor.getSelectedFaces(element).forEach(key => {
if (element.faces[key] && element.getTypeBehavior('cube_faces') && element.faces[key].texture !== null) {
diff_x = Math.clamp(diff_x, -element.faces[key].uv[0], UVEditor.getUVWidth() - element.faces[key].uv[0]);
diff_y = Math.clamp(diff_y, -element.faces[key].uv[1], UVEditor.getUVHeight() - element.faces[key].uv[1]);
diff_x = Math.clamp(diff_x, -element.faces[key].uv[2], UVEditor.getUVWidth() - element.faces[key].uv[2]);
diff_y = Math.clamp(diff_y, -element.faces[key].uv[3], UVEditor.getUVHeight() - element.faces[key].uv[3]);
}
})
}
}
})
elements.forEach(element => {
Expand Down Expand Up @@ -3290,13 +3325,16 @@ Interface.definePanels(function() {
this.drag({
event,
onDrag: (x, y) => {
const clampUvIfEnabled = settings.clampuv.value
? (value, upper_bound) => Math.clamp(value, 0, upper_bound)
: (value, _upper_bound) => value;
elements.forEach(element => {
UVEditor.getSelectedFaces(element).forEach(key => {
if (element.faces[key] && element.getTypeBehavior('cube_faces')) {
if (x_side && (x_side == -1) != inverted[element.uuid][key][0]) element.faces[key].uv[0] = Math.clamp(element.faces[key].uv[0] + x, 0, UVEditor.getUVWidth());
if (y_side && (y_side == -1) != inverted[element.uuid][key][1]) element.faces[key].uv[1] = Math.clamp(element.faces[key].uv[1] + y, 0, UVEditor.getUVHeight());
if (x_side && (x_side == 1) != inverted[element.uuid][key][0]) element.faces[key].uv[2] = Math.clamp(element.faces[key].uv[2] + x, 0, UVEditor.getUVWidth());
if (y_side && (y_side == 1) != inverted[element.uuid][key][1]) element.faces[key].uv[3] = Math.clamp(element.faces[key].uv[3] + y, 0, UVEditor.getUVHeight());
if (x_side && (x_side == -1) != inverted[element.uuid][key][0]) element.faces[key].uv[0] = clampUvIfEnabled(element.faces[key].uv[0] + x, UVEditor.getUVWidth());
if (y_side && (y_side == -1) != inverted[element.uuid][key][1]) element.faces[key].uv[1] = clampUvIfEnabled(element.faces[key].uv[1] + y, UVEditor.getUVHeight());
if (x_side && (x_side == 1) != inverted[element.uuid][key][0]) element.faces[key].uv[2] = clampUvIfEnabled(element.faces[key].uv[2] + x, UVEditor.getUVWidth());
if (y_side && (y_side == 1) != inverted[element.uuid][key][1]) element.faces[key].uv[3] = clampUvIfEnabled(element.faces[key].uv[3] + y, UVEditor.getUVHeight());
}
})
})
Expand All @@ -3309,6 +3347,9 @@ Interface.definePanels(function() {
})
},
rotateFace(event) {
const clampUvIfEnabled = settings.clampuv.value
? (value, upper_bound) => Math.clamp(value, 0, upper_bound)
: (value, _upper_bound) => value;
if (event.which == 2 || event.which == 3) return;
event.stopPropagation();
convertTouchEvent(event);
Expand Down Expand Up @@ -3391,8 +3432,8 @@ Interface.definePanels(function() {
face.uv[vkey][1] = face.old_uv[vkey][1] - face_center[1];
let a = (face.uv[vkey][0] * cos - face.uv[vkey][1] * sin);
let b = (face.uv[vkey][0] * sin + face.uv[vkey][1] * cos);
face.uv[vkey][0] = Math.clamp(a + face_center[0], 0, UVEditor.getUVWidth());
face.uv[vkey][1] = Math.clamp(b + face_center[1], 0, UVEditor.getUVHeight());
face.uv[vkey][0] = clampUvIfEnabled(a + face_center[0], UVEditor.getUVWidth());
face.uv[vkey][1] = clampUvIfEnabled(b + face_center[1], UVEditor.getUVHeight());
})
})
}
Expand Down Expand Up @@ -3532,19 +3573,21 @@ Interface.definePanels(function() {
this.drag({
event,
onDrag: (x, y, event) => {
elements.forEach(element => {
let vertices = element.getSelectedVertices();
UVEditor.getSelectedFaces(element).forEach(key => {
let face = element.faces[key];
if (!face) return;
face.vertices.forEach(vertex_key => {
if (vertices.includes(vertex_key)) {
x = Math.clamp(x, -face.uv[vertex_key][0], UVEditor.getUVWidth() - face.uv[vertex_key][0]);
y = Math.clamp(y, -face.uv[vertex_key][1], UVEditor.getUVHeight() - face.uv[vertex_key][1]);
}
if (settings.clampuv.value) {
elements.forEach(element => {
let vertices = element.getSelectedVertices();
UVEditor.getSelectedFaces(element).forEach(key => {
let face = element.faces[key];
if (!face) return;
face.vertices.forEach(vertex_key => {
if (vertices.includes(vertex_key)) {
x = Math.clamp(x, -face.uv[vertex_key][0], UVEditor.getUVWidth() - face.uv[vertex_key][0]);
y = Math.clamp(y, -face.uv[vertex_key][1], UVEditor.getUVHeight() - face.uv[vertex_key][1]);
}
})
})
})
})
}
elements.forEach(element => {
let vertices = element.getSelectedVertices().slice();
UVEditor.getSelectedFaces(element).forEach(key => {
Expand Down
2 changes: 2 additions & 0 deletions lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "Beschränkt den Pinsel auf das Verändern der Seite, auf die geklickt wurde",
"settings.autouv": "Auto-UV",
"settings.autouv.desc": "Auto-UV standardmäßig aktivieren",
"settings.clampuv": "UV-Begrenzung",
"settings.clampuv.desc": "Begrenzung der UV-Koordinaten auf die Texturgrenzen standardmäßig aktivieren",
"settings.create_rename": "Neue Elemente umbenennen",
"settings.create_rename.desc": "Beim Erstellen von Elementen oder Gruppen das Namensfeld zum Umbenennen auswählen",
"settings.edit_size": "Gitterauflösung",
Expand Down
2 changes: 2 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,8 @@

"settings.autouv": "Auto UV",
"settings.autouv.desc": "Enable Auto UV by default",
"settings.clampuv": "Clamp UV",
"settings.clampuv.desc": "Enable clamping of UV coordinates to texture bounds by default",
"settings.default_cube_size": "Cube Size",
"settings.default_cube_size.desc": "Set the default cube size when creating a new cube",
"settings.inherit_parent_color": "Inherit Parent Color",
Expand Down
2 changes: 2 additions & 0 deletions lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "Restringe los pinceles para que solo pinten en el lado actual",
"settings.autouv": "Auto UV",
"settings.autouv.desc": "Activar Auto UV por defecto",
"settings.clampuv": "Sujetar UV",
"settings.clampuv.desc": "Activar la sujeción de coordenadas UV a los bordes de la textura por defecto",
"settings.create_rename": "Renombrar Nuevo Elemento",
"settings.create_rename.desc": "Enfocar el campo de nombre al crear un nuevo elemento o grupo",
"settings.edit_size": "Resolución de Cuadrícula",
Expand Down
2 changes: 2 additions & 0 deletions lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "Restreint le pinceau pour ne peindre que du côté en cours",
"settings.autouv": "UV automatiques",
"settings.autouv.desc": "Active l'UV automatique par défaut",
"settings.clampuv": "Limitation UV",
"settings.clampuv.desc": "Activer la limitation des UV aux bords de la texture par défaut",
"settings.create_rename": "Renommer le nouvel élément",
"settings.create_rename.desc": "Entrer dans le champ de saisie du nom à la création d'un élément ou d'un groupe",
"settings.edit_size": "Résolution de la grille",
Expand Down
2 changes: 2 additions & 0 deletions lang/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "Restringi i pennelli a disegnare solo sul lato corrente",
"settings.autouv": "UV Automatico",
"settings.autouv.desc": "Attiva UV Automatico come predefinito",
"settings.clampuv": "Limitazione UV",
"settings.clampuv.desc": "Attiva la limitazione delle coordinate UV ai bordi della texture per impostazione predefinita",
"settings.create_rename": "Renomina Nuovo Cubo",
"settings.create_rename.desc": "Focalizzare il campo d'inserimento del nome quando si crea un nuovo elemento o un gruppo",
"settings.edit_size": "Risoluzione Griglia",
Expand Down
2 changes: 2 additions & 0 deletions lang/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "選択されたフェイスのみにペイントします",
"settings.autouv": "オート UV",
"settings.autouv.desc": "オート UV を有効にします",
"settings.clampuv": "UVクランプ",
"settings.clampuv.desc": "デフォルトでUV座標をテクスチャの境界にクランプする",
"settings.create_rename": "エレメントのリネーム",
"settings.create_rename.desc": "新しいエレメントを作成する際に名前フィールドがフォーカスされます",
"settings.edit_size": "グリッドステップ",
Expand Down
2 changes: 2 additions & 0 deletions lang/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "브러시가 현재 면에만 칠하도록 제한",
"settings.autouv": "자동 UV",
"settings.autouv.desc": "자동 UV를 기본으로 허용",
"settings.clampuv": "클램핑 UV",
"settings.clampuv.desc": "기본적으로 UV 좌표를 텍스쳐 경계로 클램핑합니다.",
"settings.create_rename": "요소 이름 바꾸기",
"settings.create_rename.desc": "요소 또는 그룹을 생성할 때 이름 강조",
"settings.edit_size": "격자 크기",
Expand Down
2 changes: 2 additions & 0 deletions lang/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "Beperk Kwast om enkel op het huidige vlak te tekenen",
"settings.autouv": "Auto UV",
"settings.autouv.desc": "Pas Auto UV standaard toe",
"settings.clampuv": "UV Begrenzen",
"settings.clampuv.desc": "UV-coördinaten standaard begrenzen tot de texturegrenzen",
"settings.create_rename": "Geef Nieuwe Kubus Een Naam",
"settings.create_rename.desc": "Focus naam veld bij het creëren van een nieuw element of groep",
"settings.edit_size": "Rooster Resolutie",
Expand Down
2 changes: 2 additions & 0 deletions lang/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"settings.paint_side_restrict.desc": "Ogranicz działanie szczotek aby tylko malować na aktualnej stronie",
"settings.autouv": "Automatyczne UV",
"settings.autouv.desc": "Domyślnie włącz automatyczne UV",
"settings.clampuv": "Ograniczanie UV",
"settings.clampuv.desc": "Domyślnie włączaj ograniczanie współrzędnych UV do krawędzi tekstury",
"settings.create_rename": "Nazwij nową kostkę",
"settings.create_rename.desc": "Wpisz nazwę po stworzeniu nowego elementu lub grupy",
"settings.edit_size": "Rozdzielczość siatki",
Expand Down
Loading