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",