From 4084fec92c514477a228b5f6cbc52512f5ad2f55 Mon Sep 17 00:00:00 2001 From: JannisX11 Date: Thu, 5 Apr 2018 17:11:29 +0200 Subject: [PATCH] v1.11.1 --- index.html | 9 ++- js/app.js | 11 ++- js/blockbench.js | 119 +++++++++++++-------------- js/canvas.js | 16 ++-- js/display.js | 8 +- js/elements.js | 29 ++++++- js/interface.js | 13 --- js/io.js | 2 +- js/painter.js | 203 +++++++++++++++++++++++++---------------------- js/settings.js | 131 +++++++++++++++++++++--------- js/textures.js | 6 +- js/tools.js | 9 ++- js/transform.js | 75 ++++++++++------- js/util.js | 3 + js/uv.js | 84 ++++++++++++++++++-- js/web.js | 5 -- package.json | 4 +- 17 files changed, 451 insertions(+), 276 deletions(-) diff --git a/index.html b/index.html index f88626978..2da6d949d 100644 --- a/index.html +++ b/index.html @@ -428,7 +428,7 @@

Project

- +
clear
@@ -649,7 +649,7 @@

About

Up
Down
-

Input

+

UV Editor

@@ -1045,7 +1045,8 @@

Textures

v-for="texture in textures" v-bind:class="{ selected: texture.selected }" v-bind:texid="texture.id" - class="texture" v-on:click.stop="texture.select()" + class="texture" + v-on:click.stop="texture.select()" v-on:dblclick="texture.openMenu($event)" @contextmenu.prevent.stop="texture.showContextMenu($event)" > @@ -1073,7 +1074,7 @@

Textures

Rotation

-
Rotation +
Angle
diff --git a/js/app.js b/js/app.js index 762bfd716..e2a4b083d 100644 --- a/js/app.js +++ b/js/app.js @@ -223,6 +223,7 @@ function findEntityTexture(mob, return_path) { 'geometry.enderman': 'enderman/enderman', 'geometry.zombie': 'zombie/zombie', 'geometry.zombie.husk': 'zombie/husk', + 'geometry.zombie.drowned': 'zombie/drowned', 'geometry.pigzombie': 'pig/pigzombie', 'geometry.pigzombie.baby': 'pig/pigzombie', 'geometry.skeleton': 'skeleton/skeleton', @@ -244,6 +245,7 @@ function findEntityTexture(mob, return_path) { 'geometry.vindicator': 'vindicator', 'geometry.wolf': 'wolf/wolf', 'geometry.ocelot': 'cat/ocelot', + 'geometry.trident': 'trident', 'geometry.guardian': 'guardian', 'geometry.polarbear': 'polarbear', 'geometry.villager': 'villager/villager', @@ -255,7 +257,14 @@ function findEntityTexture(mob, return_path) { 'geometry.bed': 'bed/white', 'geometry.player_head': 'steve', 'geometry.mob_head': 'skeleton/skeleton', - 'geometry.dragon_head': 'dragon/dragon' + 'geometry.dragon_head': 'dragon/dragon', + 'geometry.cod': 'fish/fish', + 'geometry.pufferfish.small': 'fish/pufferfish', + 'geometry.pufferfish.mid': 'fish/pufferfish', + 'geometry.pufferfish.large': 'fish/pufferfish', + 'geometry.salmon': 'fish/salmon', + 'geometry.tropicalfish_a': 'fish/tropical_a', + 'geometry.tropicalfish_b': 'fish/tropical_b' } var path = textures[mob.split(':')[0]] if (path) { diff --git a/js/blockbench.js b/js/blockbench.js index 4303cb29c..704a5d2f8 100644 --- a/js/blockbench.js +++ b/js/blockbench.js @@ -1,4 +1,4 @@ -var appVersion = '1.11.0' +var appVersion = '1.11.1' var osfs = '/' var File, i; var browser_name = 'electron' @@ -75,8 +75,6 @@ function initializeApp() { } Toolbox.updateBar() - updateMenu() - if (isApp) { updateRecentProjects() } @@ -321,26 +319,6 @@ function setupVue() { }) project_vue._data.Project = Project -/* - var displaypresets_vue = new Vue({ - el: '#display_presets', - data: {display_presets}, - methods: { - applyPreset: function(preset, event) { - var index = display_presets.indexOf(preset) - applyDisplayPreset(display_presets[index]) - }, - deletePreset: function(preset, event) { - var index = display_presets.indexOf(preset) - if (display_presets[index].fixed == true) return; - display_presets.splice(index, 1) - localStorage.setItem('display_presets', JSON.stringify(display_presets)) - } - } - }) - displaypresets_vue._data.display_presets = display_presets -*/ - var stats_bar_vue = new Vue({ el: '#status_bar', data: {Prop} @@ -954,6 +932,9 @@ var Undo = { history: [], add: function(action, isTextureEdit) { + if (settings.show_actions.value === true) { + showStatusMessage(action) + } if (isTextureEdit) { var entry = new Undo.textureHistoryEntry(action) } else { @@ -1057,7 +1038,7 @@ var Undo = { tex.iconpath = arr.join('?') } - tex.load() + tex.load(true, true) textures.push(tex) }) texturelist.$forceUpdate(); @@ -1097,12 +1078,7 @@ var Undo = { }) } } -function setUndo(action) { - if (settings.show_actions.value === true) { - showStatusMessage(action) - } - Undo.add(action) -} +var setUndo = Undo.add //Misc var Screencam = { normalCanvas: function(options, cb) { @@ -1168,7 +1144,7 @@ var Screencam = { }) }); }) - }, 20) + }, 40) }, returnScreenshot: function(dataUrl, cb) { if (cb) { @@ -1211,35 +1187,21 @@ var clipbench = { var p = Prop.active_panel if (open_dialog == 'uv_dialog') { uv_dialog.copy(event) - } else if (p == 'uv') { - main_uv.copy(event) } else if (display_mode) { copyDisplaySlot() + } else if (p == 'uv' || p == 'preview') { + main_uv.copy(event) } else if (p == 'textures' && isApp) { if (textures.selected) { - cl('test') - if (textures.selected.mode === 'bitmap') { - var img = nativeImage.createFromDataURL(textures.selected.iconpath) - } else { - var img = nativeImage.createFromPath(textures.selected.iconpath.split('?')[0]) - } - clipboard.writeImage(img) + clipbench.setTexture(textures.selected) } - } else if (p == 'outliner' || p == 'preview') { - clipbench.cubes = [] - clipbench.group = undefined + } else if (p == 'outliner') { + clipbench.setCubes() + clipbench.setGroup() if (selected_group) { - clipbench.group = selected_group.duplicate('cache') - if (isApp) { - clipboard.writeHTML(JSON.stringify({type: 'group', content: clipbench.group})) - } + clipbench.setGroup(selected_group) } else { - selected.forEach(function(obj) { - var base_cube = new Cube(obj) - base_cube.display.mesh = undefined; - clipbench.cubes.push(base_cube) - }) - clipboard.writeHtml(JSON.stringify({type: 'cubes', content: clipbench.cubes})) + clipbench.setCubes(selected) } } }, @@ -1247,10 +1209,10 @@ var clipbench = { var p = Prop.active_panel if (open_dialog == 'uv_dialog') { uv_dialog.paste(event) - } else if (p == 'uv') { - main_uv.paste(event) } else if (display_mode) { pasteDisplaySlot() + } else if (p == 'uv' || p == 'preview') { + main_uv.paste(event) } else if (p == 'textures' && isApp) { var img = clipboard.readImage() if (img) { @@ -1260,7 +1222,7 @@ var clipbench = { texture.openMenu() },40) } - } else if (p == 'outliner' || p == 'preview') { + } else if (p == 'outliner') { //Group var group = 'root' if (selected_group) { @@ -1286,22 +1248,51 @@ var clipbench = { clipbench.group.duplicate(group) } else { clipbench.cubes.forEach(function(obj) { - var base_cube = new Cube() - base_cube.extend(obj) - base_cube.uuid = guid() - base_cube.display.mesh = undefined; - - elements.push(base_cube) - base_cube.addTo(group) - Canvas.addCube(elements[elements.length-1]) + var base_cube = new Cube(obj) + + base_cube.addTo(group).init() selected.push(elements[elements.length-1]) }) updateSelection() setUndo('Pasted Cubes') } } + }, + setTexture: function(texture) { + //Sets the raw image of the texture + if (!isApp) return; + if (texture.mode === 'bitmap') { + var img = nativeImage.createFromDataURL(texture.iconpath) + } else { + var img = nativeImage.createFromPath(texture.iconpath.split('?')[0]) + } + clipboard.writeImage(img) }, + setGroup: function(group) { + if (!group) { + clipbench.group = undefined + return; + } + clipbench.group = group.duplicate('cache') + if (isApp) { + clipboard.writeHTML(JSON.stringify({type: 'group', content: clipbench.group})) + } + }, + setCubes: function(cubes) { + if (!cubes) { + clipbench.cubes = [] + return; + } + cubes.forEach(function(obj) { + var base_cube = new Cube(obj) + base_cube.display.mesh = undefined; + clipbench.cubes.push(base_cube) + }) + if (isApp) { + clipboard.writeHtml(JSON.stringify({type: 'cubes', content: clipbench.cubes})) + } + } } TextureAnimator = { isPlaying: false, diff --git a/js/canvas.js b/js/canvas.js index 5ced4c058..380580bd2 100644 --- a/js/canvas.js +++ b/js/canvas.js @@ -25,7 +25,7 @@ function initCanvas() { cameraOrtho.axis = null cameraPers.position.set(-20, 20, -20) - wireframeMaterial = new THREE.LineBasicMaterial({color: 0x74c2ff, linewidth: 1}) + wireframeMaterial = new THREE.LineBasicMaterial({color: 0x74c2ff}) controls = new THREE.OrbitControls(cameraPers, canvas1); controls.minDistance = 1; @@ -322,7 +322,6 @@ function buildGrid() { var size, step; var grid_color = new THREE.Color(parseInt('0x'+app_colors.grid.hex.replace('#', ''), 16)) var line_material = new THREE.LineBasicMaterial({color: grid_color}); - line_material.linewidth = 6; var material; northMarkMaterial.color = grid_color @@ -1017,12 +1016,15 @@ class CanvasController { //East+West var p = {} - p.from = face_list[1].from - p.to = face_list[1].to + + p.from = face_list[1].from.slice() + p.to = face_list[1].to.slice() + face_list[1].from = face_list[3].from.slice() face_list[1].to = face_list[3].to.slice() - p.from = face_list[3].from.slice() - p.to = face_list[3].to.slice() + + face_list[3].from = p.from.slice() + face_list[3].to = p.to.slice() } face_list.forEach(function(f) { @@ -1109,7 +1111,7 @@ class CanvasController { var geo = new THREE.EdgesGeometry(object.geometry); var outline_color = '0x'+app_colors.accent.hex.replace('#', '') - var mat = new THREE.LineBasicMaterial({color: parseInt(outline_color), linewidth: 50}) + var mat = new THREE.LineBasicMaterial({color: parseInt(outline_color), linewidth: 2}) var wireframe = new THREE.LineSegments(geo, mat) wireframe.name = obj.uuid+'_outline' wireframe.position.set(object.position.x, object.position.y, object.position.z) diff --git a/js/display.js b/js/display.js index 11d5705a3..83dedf0e9 100644 --- a/js/display.js +++ b/js/display.js @@ -28,9 +28,9 @@ class refModel { if (id === 'player') { this.onload = function() { if (slot === 'thirdperson_righthand') { - setDisplayArea(-5, 8, -6, -90, 22.5, 90, 1, 1, 1) + setDisplayArea(-5.7, 7.5, -6, -90, 22.5, 90, 1, 1, 1) } else if (slot === 'thirdperson_lefthand') { - setDisplayArea(-5, 8, 6, -90, 22.5, 90, 1, 1, 1) + setDisplayArea(-5.7, 7.5, 6, -90, 22.5, 90, 1, 1, 1) } else if (slot === 'head') { setDisplayArea(0, 22, 0, 0, 90, 0, 0.625, 0.625, 0.625) } @@ -156,7 +156,7 @@ class refModel { buildPlayer() { var scope = this; var things = [ - {"size": [4, 12, 4], "pos": [0, 12, -6], "origin": [0, 16, 0], "angle": -20, + {"size": [4, 12, 4], "pos": [0, 12, -6], "origin": [0, 16, 0], "angle": -22.5, "north": {"uv": [10, 5, 11, 8], "texture": "#0"}, "east": {"uv": [13, 5, 14, 8], "texture": "#0"}, "south": {"uv": [12, 5, 13, 8], "texture": "#0"}, @@ -165,7 +165,7 @@ class refModel { "down": { "uv": [12, 4, 13, 5], "texture": "#0", "rotation": 270 } }, //Right Arm - {"size": [4, 12, 4], "pos": [0, 12, 6], "origin": [0, 16, 0], "angle": -20, + {"size": [4, 12, 4], "pos": [0, 12, 6], "origin": [0, 16, 0], "angle": -22.5, "north": {"uv": [8, 13, 9, 16], "texture": "#0"}, "east": {"uv": [11, 13, 12, 16], "texture": "#0"}, "south": {"uv": [10, 13, 11, 16], "texture": "#0"}, diff --git a/js/elements.js b/js/elements.js index fe01e0d62..6f7b83b88 100644 --- a/js/elements.js +++ b/js/elements.js @@ -149,7 +149,7 @@ class OutlinerElement { if (level === 'root') { i = 50 } else if (level === this) { - return; + return this; } else { level = group.display.parent } @@ -298,7 +298,7 @@ class Cube extends OutlinerElement { if (!scene.children.includes(this)) { Canvas.addCube(this) } - if (true) { + if (!this.display.parent) { this.addTo() } return this; @@ -434,6 +434,25 @@ class Cube extends OutlinerElement { {icon: 'pages', name: 'Inflate...', condition: Blockbench.entity_mode, click: function() { scope.inflateDialog() }}, + {icon: 'collections', condition: (!Blockbench.entity_mode), name: 'Texture', children: function() { + var arr = [ + {icon: 'clear', name: 'Transparent', click: function(event) { + scope.applyTexture(undefined, true) + setUndo('Removed texture') + }}, + ] + textures.forEach(function(t) { + arr.push({ + name: t.name, + icon: t.img, + click: function(event) { + scope.applyTexture(t, true) + setUndo('Applied texture') + } + }) + }) + return arr; + }} ]) } inflateDialog() { @@ -486,8 +505,12 @@ class Cube extends OutlinerElement { } else { var sides = faces } + var id = '$transparent' + if (texture && texture.id !== undefined) { + id = '#'+texture.id + } sides.forEach(function(side) { - scope.faces[side].texture = '#'+texture.id + scope.faces[side].texture = id }) if (this.display.isselected) { main_uv.loadData() diff --git a/js/interface.js b/js/interface.js index ab98b54aa..e33c5ccbc 100644 --- a/js/interface.js +++ b/js/interface.js @@ -428,19 +428,6 @@ function setInterfaceMode(mode) { setScreenRatio() } -//Menu -function updateMenu() { - //Settings Dependent - $('header .settings_dependent').each(function(i, o) { - var set = $(o).attr('setting') - if (settings[set] && settings[set].value === true) { - $(o).text('check_box') - } else { - $(o).text('check_box_outline_blank') - } - }) -} - //SplashScreen var splashScreen = { attempt: function(res) { diff --git a/js/io.js b/js/io.js index 831a1a875..a6f6f728a 100644 --- a/js/io.js +++ b/js/io.js @@ -584,7 +584,7 @@ function buildEntityModel(options) { cube.inflate = s.inflate } if (s.shade === false) { - bone.mirror = true + cube.mirror = true } bone.cubes.push(cube) } diff --git a/js/painter.js b/js/painter.js index a3c803d30..da58a345b 100644 --- a/js/painter.js +++ b/js/painter.js @@ -9,7 +9,7 @@ class BBPainter { if (typeof options !== 'object') { options = {} } - if (texture.type === 'link') { + if (texture.mode === 'link') { console.error('Cannot edit link texture') return; } @@ -22,6 +22,13 @@ class BBPainter { texture.iconpath = dataUrl texture.updateMaterial() main_uv.loadData() + if (open_dialog === 'uv_dialog') { + for (var editor in uv_dialog.editors) { + if (uv_dialog.editors.hasOwnProperty(editor)) { + uv_dialog.editors[editor].loadData() + } + } + } if (!options.noUndo) { Undo.add('Paint', true) } @@ -42,41 +49,20 @@ class BBPainter { }) } } - startBrush(data, x, event) { - if (event.altKey === false) { - Painter.brushChanges = false - document.addEventListener('mousemove', Painter.moveBrush, false ); - document.addEventListener('mouseup', Painter.stopBrush, false ); - Painter.moveBrush(true) - } else { - //Pick Color - var data = Canvas.raycast() - if (data) { - var texture = getTextureById(data.cube.faces[data.face].texture) - if (texture) { - var x = Math.floor( data.intersects[0].uv.x * texture.img.naturalWidth ) - var y = Math.floor( (1-data.intersects[0].uv.y) * texture.img.naturalHeight ) + startBrushCanvas(data, event) { - function getPxColor(image) { - var c = image.getPixelColor(x,y) - console.log(c) - c = tinycolor(Jimp.intToRGBA(c)) - console.log(c) - console.log(c.toHexString()) - $('#brush_color').spectrum('set', c.toHexString()) - } - if (texture.mode == 'bitmap') { - Jimp.read(Buffer.from(texture.iconpath.replace('data:image/png;base64,', ''), 'base64'), function() {}).then(getPxColor) - } else { - Jimp.read(texture.iconpath, function() {}).then(getPxColor) - } - } else { - - } - } + var texture = getTextureById(data.cube.faces[data.face].texture) + if (texture) { + var x = Math.floor( data.intersects[0].uv.x * texture.img.naturalWidth ) + var y = Math.floor( (1-data.intersects[0].uv.y) * texture.img.naturalHeight ) + Painter.startBrush(texture, x, y, data.cube.faces[data.face].uv, event) + } + if (event.altKey === false && texture.mode !== 'link') { + document.addEventListener('mousemove', Painter.moveBrushCanvas, false ); + document.addEventListener('mouseup', Painter.stopBrushCanvas, false ); } } - moveBrush(force) { + moveBrushCanvas(force) { var data = Canvas.raycast() if (data) { var texture = getTextureById(data.cube.faces[data.face].texture) @@ -88,61 +74,98 @@ class BBPainter { } else { var x = Math.floor( data.intersects[0].uv.x * texture.img.naturalWidth ) var y = Math.floor( (1-data.intersects[0].uv.y) * texture.img.naturalHeight ) - if ((Painter.currentPixel[0] !== x || Painter.currentPixel[1] !== y)) { - Painter.currentPixel = [x, y] - Painter.brushChanges = true + Painter.useBrush(texture, x, y, data.cube.faces[data.face].uv) + } + } + } + stopBrushCanvas() { + document.removeEventListener( 'mousemove', Painter.moveBrushCanvas, false ); + document.removeEventListener( 'mouseup', Painter.stopBrushCanvas, false ); + Painter.stopBrush() + } - Painter.edit(texture, function(image) { - var color = $('#brush_color').spectrum('get').toRgb() - var size = limitNumber(parseInt($('#brush_size').val()), 1, 20); - var softness = limitNumber(parseFloat($('#brush_softness').val()), 0, 1); - var brush_mode = $('select#brush_mode option:selected').attr('id') + startBrush(texture, x, y, uvTag, event) { + if (event.altKey === false) { + if (texture.mode !== 'bitmap') { + texture.highlightModeToggle() + Blockbench.showMessage('You can only paint on bitmap textures', 'center') + } else { + Painter.brushChanges = false + Painter.useBrush(texture, x, y, uvTag) + } + } else { + Painter.colorPicker(texture, x, y) + } + } + colorPicker(texture, x, y) { + function getPxColor(image) { + var c = image.getPixelColor(x,y) + c = tinycolor(Jimp.intToRGBA(c)) + $('#brush_color').spectrum('set', c.toHexString()) + } + if (texture.mode == 'bitmap') { + Jimp.read(Buffer.from(texture.iconpath.replace('data:image/png;base64,', ''), 'base64'), function() {}).then(getPxColor) + } else { + Jimp.read(texture.iconpath, function() {}).then(getPxColor) + } + } + useBrush(texture, x, y, uvTag) { + if ((Painter.currentPixel[0] !== x || Painter.currentPixel[1] !== y)) { + Painter.currentPixel = [x, y] + Painter.brushChanges = true - Painter.editing_area = [ - data.cube.faces[data.face].uv[0] / 16 * texture.img.naturalWidth, - data.cube.faces[data.face].uv[1] / 16 * texture.img.naturalHeight, - data.cube.faces[data.face].uv[2] / 16 * texture.img.naturalWidth, - data.cube.faces[data.face].uv[3] / 16 * texture.img.naturalHeight - ] - if (Painter.editing_area[0] > Painter.editing_area[2]) { - var sw = Painter.editing_area[2] - Painter.editing_area[2] = Painter.editing_area[0] - Painter.editing_area[0] = sw - } - if (Painter.editing_area[1] > Painter.editing_area[3]) { - var sw = Painter.editing_area[3] - Painter.editing_area[3] = Painter.editing_area[1] - Painter.editing_area[1] = sw - } + Painter.edit(texture, function(image) { + var color = $('#brush_color').spectrum('get').toRgb() + var size = limitNumber(parseInt($('#brush_size').val()), 1, 20); + var softness = limitNumber(parseFloat($('#brush_softness').val()), 0, 1); + var brush_mode = $('select#brush_mode option:selected').attr('id') - if (brush_mode === 'round') { - Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) { - var result_color = Painter.combineColors(pxcolor, color, opacity); - return result_color; - }) - } else if (brush_mode === 'noise') { - Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) { - var result_color = Painter.combineColors(pxcolor, color, opacity*Math.random()); - return result_color; - }) - } else if (brush_mode === 'eraser') { - Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) { - return {r: pxcolor.r, g: pxcolor.g, b: pxcolor.b, a: pxcolor.a*(1-opacity)}; - }) - } else if (brush_mode === 'fill') { - Painter.editFace(image, x, y, function(pxcolor) { - return Painter.combineColors(pxcolor, color, 1) - }) - } - Painter.editing_area = undefined - }, {noUndo: true, use_cache: true}) + if (uvTag) { + Painter.editing_area = [ + uvTag[0] / 16 * texture.img.naturalWidth, + uvTag[1] / 16 * texture.img.naturalHeight, + uvTag[2] / 16 * texture.img.naturalWidth, + uvTag[3] / 16 * texture.img.naturalHeight + ] + } else { + Painter.editing_area = [0, 0, texture.red, texture.red] } - } + + if (Painter.editing_area[0] > Painter.editing_area[2]) { + var sw = Painter.editing_area[2] + Painter.editing_area[2] = Painter.editing_area[0] + Painter.editing_area[0] = sw + } + if (Painter.editing_area[1] > Painter.editing_area[3]) { + var sw = Painter.editing_area[3] + Painter.editing_area[3] = Painter.editing_area[1] + Painter.editing_area[1] = sw + } + + if (brush_mode === 'round') { + Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) { + var result_color = Painter.combineColors(pxcolor, color, opacity); + return result_color; + }) + } else if (brush_mode === 'noise') { + Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) { + var result_color = Painter.combineColors(pxcolor, color, opacity*Math.random()); + return result_color; + }) + } else if (brush_mode === 'eraser') { + Painter.editCircle(image, x, y, size, softness, function(pxcolor, opacity) { + return {r: pxcolor.r, g: pxcolor.g, b: pxcolor.b, a: pxcolor.a*(1-opacity)}; + }) + } else if (brush_mode === 'fill') { + Painter.editFace(image, x, y, function(pxcolor) { + return Painter.combineColors(pxcolor, color, 1) + }) + } + Painter.editing_area = undefined + }, {noUndo: true, use_cache: true}) } } stopBrush() { - document.removeEventListener( 'mousemove', Painter.moveBrush, false ); - document.removeEventListener( 'mouseup', Painter.stopBrush, false ); if (Painter.brushChanges) { Undo.add('Paint', true) Painter.brushChanges = false @@ -325,12 +348,12 @@ class BBPainter { if (isNaN(options.res) || !options.res) { options.res = 16 } - console.log(options) if (options.color === undefined) { options.color = 0xffffffff } var texture = new Texture({ mode: 'bitmap', + keep_size: true, res: options.res, name: options.name ? options.name : 'texture', folder: options.folder ? options.folder : 'blocks' @@ -446,19 +469,8 @@ class BBPainter { } //Size var max_size = Math.max(max_x_pos, line_y_pos) - max_size = snap16(max_size) + max_size = snapNum(max_size, 16) var img_size = {x: max_size, y: max_size} - /* - if (max_x_pos <= max_size/2) { - //vert - img_size = {x: snap16(max_size/2), y: max_size} - } else if (line_y_pos <= max_size/2) { - //landscape - img_size = {x: max_size, y: snap16(max_size/2)} - } else { - //square - img_size = {x: max_size, y: max_size} - }*/ function drawTemplateRectangle(image, border_color, color, coords) { Painter.drawRectangle(image, border_color, { @@ -495,8 +507,7 @@ class BBPainter { }) image.getBase64("image/png", function(a, dataUrl){ cb(dataUrl) - Project.texture_width = img_size.x - Project.texture_height = img_size.y + entityMode.setResolution(img_size.x, img_size.y, true) }) }) } diff --git a/js/settings.js b/js/settings.js index 96448278d..563f80c82 100644 --- a/js/settings.js +++ b/js/settings.js @@ -45,11 +45,12 @@ function keybindSetup(get) { headline4: {is_title: true, title: "Textures"}, reload_tex: {shift: false, ctrl: true, alt: false, code: 82, name: 'Reload Textures', char: 'Ctrl + R'}, - headline6: {is_title: true, title: "Tool"}, - tool_translate:{shift: false, ctrl: false, alt: false, code: 86, name: 'Move Tool', char: 'V'}, - tool_scale: {shift: false, ctrl: false, alt: false, code: 83, name: 'Scale Tool', char: 'S'}, - tool_brush: {shift: false, ctrl: false, alt: false, code: 66, name: 'Brush', char: 'B'}, - tool_swap: {shift: false, ctrl: false, alt: false, code: 32, name: 'Swap Move and Scale', char: 'SPACE'}, + headline6: {is_title: true, title: "Tool"}, + tool_translate: {shift: false, ctrl: false, alt: false, code: 86, name: 'Move Tool', char: 'V'}, + tool_scale: {shift: false, ctrl: false, alt: false, code: 83, name: 'Scale Tool', char: 'S'}, + tool_brush: {shift: false, ctrl: false, alt: false, code: 66, name: 'Brush', char: 'B'}, + tool_vertexsnap:{shift: false, ctrl: false, alt: false, code: 66, name: 'Vertex Snap', char: 'X'}, + tool_swap: {shift: false, ctrl: false, alt: false, code: 32, name: 'Swap Move and Scale', char: 'SPACE'}, headline7: {is_title: true, title: "Movement"}, move_north: {shift: false, ctrl: false, alt: false, code: 38, name: 'Move South', char: 'ARROWUP'}, @@ -138,8 +139,8 @@ function settingSetup() { round_digits: {value: 4, is_number: true, name: 'Round numbers', desc: 'Round numbers'}, export_groups:{value: true, name: 'Export Groups', desc: 'Save groups in blockmodel files'}, obj_textures: {value: true, name: 'Export Textures', desc: 'Export textures when exporting OBJ file'}, - comment: {value: true, name: 'File Comment', desc: 'Add a credit comment to file'}, - comment_text: {value: 'Made with Blockbench, a free, modern block model editor by JannisX11', is_string: true}, + comment: {value: true, name: 'Credit Comment', desc: 'Add a credit comment to file'}, + comment_text: {value: 'Made with Blockbench', is_string: true}, default_path: {value: false, hidden: true} } if (localStorage.getItem('settings') != null) { @@ -305,11 +306,13 @@ $(document).keydown(function(e) { } if (open_dialog !== false) { - if (open_dialog === 'uv_dialog') { - if (compareKeys(e, keybinds.uv_copy)) { + if (open_dialog === 'uv_dialog') { + //Copy/Paste handling for UV dialog + //Can't use clipbench because that would preventDefault() all other copy/paste in dialogs + if (compareKeys(e, keybinds.copy)) { uv_dialog.copy(e) } - if (compareKeys(e, keybinds.uv_paste)) { + if (compareKeys(e, keybinds.paste)) { uv_dialog.paste(e) } } @@ -407,6 +410,8 @@ $(document).keydown(function(e) { Toolbox.set('scale') } else if (compareKeys(e, keybinds.tool_brush)) { Toolbox.set('paint_brush') + } else if (compareKeys(e, keybinds.tool_vertexsnap)) { + Toolbox.set('vertex_snap') } else if (compareKeys(e, keybinds.tool_swap)) { toggleTools() } @@ -493,36 +498,49 @@ function saveSettings(force_update) { function hasSettingChanged(id) { return (settings[id].value !== settings_old[id]) } - updateMenu() - for (var mat in Canvas.materials) { - if (Canvas.materials.hasOwnProperty(mat)) - Canvas.materials[mat].transparent = settings.transparency.value - } setScreenRatio() - canvasGridSize() - buildGrid() - if (settings.snapnslide.value === true) { - $('.nslide').draggable( "option", "grid", [ 50, 100 ] ); - } else { - $('.nslide').draggable( "option", "grid", false ); - } - if (settings.swap_sidebar.value === true) { - $('body').addClass('rtl') - } else { - $('body').removeClass('rtl') - } - if (settings.status_bar.value) { - $('body').css('grid-template-rows', '32px calc(100% - 58px) 26px') - } else { - $('body').css('grid-template-rows', '32px calc(100% - 32px) 0px') - } hideDialog() updateUIColor() updateSelection() - if (Blockbench.entity_mode) { - main_uv.setGrid() - if (uv_dialog.editors) { - uv_dialog.editors.single.setGrid() + + $('header .settings_dependent').each(function(i, o) { + var set = $(o).attr('setting') + if (settings[set] && settings[set].value === true) { + $(o).text('check_box') + } else { + $(o).text('check_box_outline_blank') + } + }) + + if (hasSettingChanged('status_bar')) { + if (settings.snapnslide.value === true) { + $('.nslide').draggable( "option", "grid", [ 50, 100 ] ); + } else { + $('.nslide').draggable( "option", "grid", false ); + } + } + if (hasSettingChanged('status_bar')) { + if (settings.status_bar.value) { + $('body').css('grid-template-rows', '32px calc(100% - 58px) 26px') + } else { + $('body').css('grid-template-rows', '32px calc(100% - 32px) 0px') + } + } + if (hasSettingChanged('swap_sidebar')) { + if (settings.swap_sidebar.value === true) { + $('body').addClass('rtl') + } else { + $('body').removeClass('rtl') + } + } + if (hasSettingChanged('base_grid') || hasSettingChanged('large_grid') || hasSettingChanged('full_grid') ||hasSettingChanged('large_box') || hasSettingChanged('display_grid')) { + buildGrid() + } + if (hasSettingChanged('transparency')) { + for (var mat in Canvas.materials) { + if (Canvas.materials.hasOwnProperty(mat)) { + Canvas.materials[mat].transparent = settings.transparency.value + } } } if (hasSettingChanged('shading')) { @@ -536,6 +554,16 @@ function saveSettings(force_update) { } Blockbench.dispatchEvent('update_settings') } +function saveProjectSettings() { + if (Blockbench.entity_mode) { + main_uv.setGrid() + if (uv_dialog.editors) { + uv_dialog.editors.single.setGrid() + } + entityMode.setResolution() + } + hideDialog() +} function toggleSetting(setting) { if (settings[setting].value === true) { settings[setting].value = false @@ -550,6 +578,7 @@ function toggleWireframe() { } var entityMode = { state: false, + old_res: {}, join: function() { if (display_mode) { exitDisplaySettings() @@ -620,5 +649,35 @@ var entityMode = { } } }) + }, + setResolution: function(x, y, lockUV) { + if (!Blockbench.entity_mode) return; + + if (x, y) { + entityMode.old_res.x = Project.texture_width + entityMode.old_res.y = Project.texture_height + } + if (x) { + Project.texture_width = x + } + + if (entityMode.old_res.x != Project.texture_width && !lockUV) { + elements.forEach(function(obj) { + obj.uv_offset[0] *= Project.texture_width/entityMode.old_res.x + }) + } + + if (y) { + Project.texture_height = y + } + if (entityMode.old_res.y != Project.texture_height && !lockUV) { + elements.forEach(function(obj) { + obj.uv_offset[1] *= Project.texture_height/entityMode.old_res.y + }) + } + + entityMode.old_res.x = Project.texture_width + entityMode.old_res.y = Project.texture_height + Canvas.updateAllUVs() } } \ No newline at end of file diff --git a/js/textures.js b/js/textures.js index be3c7c05f..137608de0 100644 --- a/js/textures.js +++ b/js/textures.js @@ -81,8 +81,7 @@ class Texture { } } if (Blockbench.entity_mode && textures.indexOf(scope) === 0 && !reloading && !scope.keep_size) { - Project.texture_width = img.naturalWidth - Project.texture_height = img.naturalHeight + entityMode.setResolution(img.naturalWidth, img.naturalHeight) if (selected.length) { main_uv.loadData() main_uv.setGrid() @@ -279,6 +278,7 @@ class Texture { textures.forEach(function(s) { s.selected = false; }) + Prop.active_panel = 'textures' this.selected = true textures.selected = this return this; @@ -363,7 +363,7 @@ class Texture { setUndo('Applied texture') } openFolder() { - if (!isApp) return; + if (!isApp || this.type !== 'link') return; shell.showItemInFolder(this.path) } remove() { diff --git a/js/tools.js b/js/tools.js index 93b611144..9d1ab62d1 100644 --- a/js/tools.js +++ b/js/tools.js @@ -78,9 +78,16 @@ var Toolbox = { label: 'Paint Brush', icon: 'fa-paint-brush', showTransformer: false, + paint_tool: true, optionBar: 'brush', onCanvasClick: function(data) { - Painter.startBrush(data.cube, data.intersects[0], data.event) + Painter.startBrushCanvas(data, data.event) + }, + onSelect: function() { + $('.UVEditor').find('#uv_size').hide() + }, + onUnselect: function() { + $('.UVEditor').find('#uv_size').show() } }), new Tool({ diff --git a/js/transform.js b/js/transform.js index 4f48ebb19..320e1d39d 100644 --- a/js/transform.js +++ b/js/transform.js @@ -26,38 +26,53 @@ function duplicateCubes() { setUndo('Duplicated cube'+pluralS(selected)) } function origin2geometry() { - selected.forEach(function(obj) { - var element_size = obj.size() - var element_center = new THREE.Vector3( - (element_size[0] / 2) + obj.from[0], - (element_size[1] / 2) + obj.from[1], - (element_size[2] / 2) + obj.from[2] - ) + if (Blockbench.entity_mode) { + if (!selected_group) return + var position = [0, 0, 0] + selected_group.children.forEach(function(obj) { + position[0] += obj.from[0] + obj.size(0)/2 + position[1] += obj.from[1] + obj.size(1)/2 + position[2] += obj.from[2] + obj.size(2)/2 + }) + position.forEach(function(p, pi) { + position[pi] = p / selected_group.children.length + }) + selected_group.origin = position + } else { + selected.forEach(function(obj) { - if (obj.rotation == undefined) { - obj.rotation = {origin:[8,8,8], axis: 'y', angle: 0} - } - element_center.x -= obj.rotation.origin[0] - element_center.y -= obj.rotation.origin[1] - element_center.z -= obj.rotation.origin[2] + var element_size = obj.size() + var element_center = new THREE.Vector3( + (element_size[0] / 2) + obj.from[0], + (element_size[1] / 2) + obj.from[1], + (element_size[2] / 2) + obj.from[2] + ) - if (obj.display.mesh) { - element_center.applyEuler(obj.display.mesh.rotation) - } - obj.rotation.origin[0] += element_center.x - obj.rotation.origin[1] += element_center.y - obj.rotation.origin[2] += element_center.z + if (obj.rotation == undefined) { + obj.rotation = {origin:[8,8,8], axis: 'y', angle: 0} + } + element_center.x -= obj.rotation.origin[0] + element_center.y -= obj.rotation.origin[1] + element_center.z -= obj.rotation.origin[2] - obj.to[0] = obj.rotation.origin[0] + element_size[0] / 2 - obj.to[1] = obj.rotation.origin[1] + element_size[1] / 2 - obj.to[2] = obj.rotation.origin[2] + element_size[2] / 2 + if (obj.display.mesh) { + element_center.applyEuler(obj.display.mesh.rotation) + } + obj.rotation.origin[0] += element_center.x + obj.rotation.origin[1] += element_center.y + obj.rotation.origin[2] += element_center.z - obj.from[0] = obj.rotation.origin[0] - element_size[0] / 2 - obj.from[1] = obj.rotation.origin[1] - element_size[1] / 2 - obj.from[2] = obj.rotation.origin[2] - element_size[2] / 2 - }) - Canvas.updatePositions() + obj.to[0] = obj.rotation.origin[0] + element_size[0] / 2 + obj.to[1] = obj.rotation.origin[1] + element_size[1] / 2 + obj.to[2] = obj.rotation.origin[2] + element_size[2] / 2 + + obj.from[0] = obj.rotation.origin[0] - element_size[0] / 2 + obj.from[1] = obj.rotation.origin[1] - element_size[1] / 2 + obj.from[2] = obj.rotation.origin[2] - element_size[2] / 2 + }) + } + Canvas.updatePositions() setUndo('Set origin to geometry') } function inflateCubes(val) { @@ -316,7 +331,7 @@ function moveIntoBox(list) { list.forEach(function(s, i) { //Push elements into 3x3 block box [0, 1, 2].forEach(function(ax) { - var overlap = s.from[ax] + s.to[ax] - 32 + var overlap = s.to[ax] - 32 if (overlap > 0) { //If positive site overlaps s.from[ax] -= overlap @@ -332,7 +347,7 @@ function moveIntoBox(list) { s.from[ax] -= overlap s.to[ax] -= overlap - if (s.from[ax] + s.to[ax] > 32) { + if (s.to[ax] > 32) { s.to[ax] = 32 } } @@ -760,7 +775,7 @@ function centerCubes(axis, update) { average += obj.to[axis] }) average = average / (selected.length * 2) - var difference = 8 - average + var difference = (Blockbench.entity_mode ? 0 : 8) - average selected.forEach(function(s) { executeNslide('pos_'+getAxisLetter(axis), s, difference) diff --git a/js/util.js b/js/util.js index d6ad2f24f..e3c188031 100644 --- a/js/util.js +++ b/js/util.js @@ -21,6 +21,9 @@ tinycolor.prototype.toInt = function() { var rgba = this.toRgb() return Jimp.rgbaToInt(rgba.r, rgba.g, rgba.b, rgba.a) } +Array.prototype.empty = function() { + this.length = 0; +} function guid() { function s4() { diff --git a/js/uv.js b/js/uv.js index 80d442564..a790b4cfc 100644 --- a/js/uv.js +++ b/js/uv.js @@ -63,6 +63,9 @@ class UVEditor { //dummy function, sets the global variable nslide.editor to the current uv editor nslide.editor = scope; }) + if (Toolbox.selected.paint_tool) { + this.jquery.size.hide() + } this.jquery.size.mouseenter(function() { scope.displayMappingOverlay() @@ -165,8 +168,60 @@ class UVEditor { this.jquery.frame.contextmenu(function(event) { scope.contextMenu() }) + + this.jquery.frame.mousedown(function(event) { + if (Toolbox.selected.id === 'paint_brush') { + scope.startBrush(event) + } + }) return this; } + getBrushCoordinates(event) { + var scope = this; + return { + x: Math.floor(event.offsetX/scope.getPixelSize()), + y: Math.floor(event.offsetY/scope.getPixelSize()) + } + } + + + + startBrush(event) { + var scope = this; + Painter.active_uv_editor = scope; + + var texture = scope.getTexture() + if (texture) { + var x = scope.getBrushCoordinates(event).x + var y = scope.getBrushCoordinates(event).y + Painter.startBrush(texture, x, y, undefined, event) + } + if (event.altKey === false && texture.mode !== 'link') { + scope.jquery.frame.get(0).addEventListener('mousemove', scope.moveBrush, false ); + document.addEventListener('mouseup', scope.stopBrush, false ); + } + } + moveBrush(event) { + var scope = Painter.active_uv_editor; + var texture = scope.getTexture() + if (!texture) { + Blockbench.showMessage('The surface does not have a texture', 'center') + } else if (texture.mode !== 'bitmap') { + texture.highlightModeToggle() + Blockbench.showMessage('You can only paint on bitmap textures', 'center') + } else { + var x = scope.getBrushCoordinates(event).x + var y = scope.getBrushCoordinates(event).y + Painter.useBrush(texture, x, y) + } + } + stopBrush(event) { + var scope = Painter.active_uv_editor; + scope.jquery.frame.get(0).removeEventListener( 'mousemove', scope.moveBrush, false ); + document.removeEventListener( 'mouseup', scope.stopBrush, false ); + Painter.stopBrush() + } + message(msg) { var box = $('
' + msg + '
') this.jquery.frame.append(box) @@ -196,6 +251,9 @@ class UVEditor { return obj.faces[this.face].uv; } } + getTexture() { + return getTextureById(selected[0].faces[this.face].texture) + } forCubes(cb) { var i = 0; while (i < selected.length) { @@ -1089,6 +1147,8 @@ var uv_dialog = { selection: [], selection_all: [], hoveredSide: false, + single_size: {}, + all_size: {}, setup: function() { uv_dialog.editors = { single:new UVEditor('single').appendTo('#uv_dialog_single'), @@ -1121,7 +1181,7 @@ var uv_dialog = { } } $('.dialog#uv_dialog').resizable({ - minWidth: 200, + minWidth: 202, minHeight: 464, resize: function() { uv_dialog.updateSize() @@ -1193,6 +1253,7 @@ var uv_dialog = { uv_dialog.centerDialog() }, openTab: function(tab) { + uv_dialog.saveSize() $('#uv_tab_bar .tab').removeClass('open') $('#uv_tab_bar .tab#'+tab).addClass('open') if (tab === 'all') { @@ -1207,6 +1268,8 @@ var uv_dialog = { uv_dialog.selection = uv_dialog.selection_all.splice(0, 10) uv_dialog.updateSelection() $('#uv_dialog_toolbar #grid_snap').val(uv_dialog.editors.north.gridSelectOption) + $('.dialog#uv_dialog').width(uv_dialog.all_size.x) + $('.dialog#uv_dialog').height(uv_dialog.all_size.y) } else { uv_dialog.single = true $('#uv_dialog_single').show() @@ -1222,10 +1285,21 @@ var uv_dialog = { uv_dialog.editors.single.setSize(max_size) uv_dialog.editors.single.jquery.main.css('margin-left', 'auto').css('margin-right', 'auto').css('width', max_size+'px') } + $('.dialog#uv_dialog').width(uv_dialog.single_size.x) + $('.dialog#uv_dialog').height(uv_dialog.single_size.y) } uv_dialog.hoveredSide = false; uv_dialog.updateSize() }, + saveSize: function() { + if (uv_dialog.single) { + uv_dialog.single_size.x = $('.dialog#uv_dialog').width() + uv_dialog.single_size.y = $('.dialog#uv_dialog').height() + } else { + uv_dialog.all_size.x = $('.dialog#uv_dialog').width() + uv_dialog.all_size.y = $('.dialog#uv_dialog').height() + } + }, updateSize: function() { var obj = $('.dialog#uv_dialog') var size = { @@ -1248,16 +1322,14 @@ var uv_dialog = { //2 x 3 0.83 - 7.2 if (size.y*1.4 > size.x) { var editor_size = limitNumber(size.x / 2 - 20, 80, $(window).height()/3-120) + editor_size = limitNumber(editor_size, 80, (size.y-64)/3-77) } else { var editor_size = size.y / 3 - 96 - 48 } } else { //4 x 2 - if (size.y - 250 > size.x / 2) { - var editor_size = size.x / 4 - 20 - } else { - var editor_size = size.y / 2 - 130 - } + var y_margin = ($('#uv_dialog_toolbar #uv_rotation').position().left>900 ? 122 : 150) + var editor_size = limitNumber(size.x/4-20, 16, size.y/2-y_margin) centerUp = true } editor_size = editor_size - (editor_size % 16) diff --git a/js/web.js b/js/web.js index d9c73ba0c..1dba9e02f 100644 --- a/js/web.js +++ b/js/web.js @@ -92,17 +92,13 @@ document.body.ondrop = (ev) => { function tryLoadPOSTModel() { if ($('#post_model').text() !== '') { - console.log('[P] Data in model tag found') if ($('#post_textures').text() !== '') { - console.log('[P] Data in texture tag found') Project.dataURLTextures = true } loadFile($('#post_model').text(), 'model', true) - console.log('[P] File Loaded') //$('#post_model').remove() if ($('#post_textures').text() !== '') { var data = JSON.parse( $('#post_textures').text() ) - console.log('[P] textures parsed', data) for (var key in data) { if (data.hasOwnProperty(key)) { var tex = getTextureById(key+''); @@ -115,7 +111,6 @@ function tryLoadPOSTModel() { textures.forEach(function(tex) { tex.load() }) - console.log('[P] '+textures.length+' textures loaded') } return true; } else { diff --git a/package.json b/package.json index b374bd7b9..e24ae4fcf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Blockbench", "description": "Minecraft Block Model Editor", - "version": "1.11.0", + "version": "1.11.1", "license": "MIT", "author": { "name": "JannisX11", @@ -61,7 +61,7 @@ }, "scripts": { "pack": "build --dir", - "dist": "build --publish onTagOrDraft" + "dist": "build --publish always" }, "devDependencies": { "async": "^2.4.1",