From 85e2f3a1ba1b093448e483f354987cb0d92768e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ruben=20M=C3=BCller?= Date: Wed, 3 Apr 2013 21:02:06 +0200 Subject: [PATCH] Updated impact engine lib from 1.20 to 1.22 --- .gitignore | 1 + dev/lib/impact/animation.js | 2 +- dev/lib/impact/background-map.js | 29 ++++--- dev/lib/impact/debug/menu.js | 2 +- dev/lib/impact/entity.js | 2 +- dev/lib/impact/font.js | 11 +-- dev/lib/impact/image.js | 11 +-- dev/lib/impact/impact.js | 100 ++++++++++++++++++---- dev/lib/impact/input.js | 57 ++++++------ dev/lib/impact/sound.js | 6 ++ dev/lib/impact/system.js | 28 +++++- dev/lib/impact/timer.js | 2 +- dev/lib/weltmeister/collisiontiles-64.png | Bin 19656 -> 10274 bytes dev/lib/weltmeister/config.js | 4 +- dev/lib/weltmeister/edit-entities.js | 32 +++++-- dev/lib/weltmeister/entities.js | 4 +- dev/lib/weltmeister/evented-input.js | 7 +- dev/lib/weltmeister/weltmeister.js | 5 ++ dev/media/04b03.font.png | Bin 3500 -> 484 bytes dev/tools/bake.bat | 8 +- 20 files changed, 215 insertions(+), 96 deletions(-) diff --git a/.gitignore b/.gitignore index 2725941..d61fb76 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ design/design-layout.psd +.DS_Store \ No newline at end of file diff --git a/dev/lib/impact/animation.js b/dev/lib/impact/animation.js index 37f7bc7..5557242 100755 --- a/dev/lib/impact/animation.js +++ b/dev/lib/impact/animation.js @@ -50,7 +50,7 @@ ig.Animation = ig.Class.extend({ rewind: function() { - this.timer.reset(); + this.timer.set(); this.loopCount = 0; this.tile = this.sequence[0]; return this; diff --git a/dev/lib/impact/background-map.js b/dev/lib/impact/background-map.js index 619e371..b4d7b0f 100755 --- a/dev/lib/impact/background-map.js +++ b/dev/lib/impact/background-map.js @@ -47,6 +47,10 @@ ig.BackgroundMap = ig.Map.extend({ preRenderMapToChunks: function() { var totalWidth = this.width * this.tilesize * ig.system.scale, totalHeight = this.height * this.tilesize * ig.system.scale; + + // If this layer is smaller than the chunkSize, adjust the chunkSize + // accordingly, so we don't have as much overdraw + this.chunkSize = Math.min( Math.max(totalWidth, totalHeight), this.chunkSize ); var chunkCols = Math.ceil(totalWidth / this.chunkSize), chunkRows = Math.ceil(totalHeight / this.chunkSize); @@ -133,8 +137,11 @@ ig.BackgroundMap = ig.Map.extend({ if( this.repeat ) { - dx %= this.width * this.tilesize * ig.system.scale; - dy %= this.height * this.tilesize * ig.system.scale; + var w = this.width * this.tilesize * ig.system.scale; + dx = (dx%w + w) % w; + + var h = this.height * this.tilesize * ig.system.scale; + dy = (dy%h + h) % h; } var minChunkX = Math.max( Math.floor(dx / this.chunkSize), 0 ), @@ -168,18 +175,18 @@ ig.BackgroundMap = ig.Map.extend({ ig.system.context.strokeRect( x, y, this.chunkSize, this.chunkSize ); } - // If we repeat in X and this chunks width wasn't the full chunk size + // If we repeat in X and this chunk's width wasn't the full chunk size // and the screen is not already filled, we need to draw anohter chunk // AND nudge it to be flush with the last chunk - if( this.repeat && chunk.width < this.chunkSize && x + chunk.width < ig.system.realWidth ) { - nudgeX = this.chunkSize - chunk.width; + if( this.repeat && chunk.width < this.chunkSize && x + chunk.width < ig.system.realWidth ) { + nudgeX += this.chunkSize - chunk.width; maxChunkX++; } } // Same as above, but for Y - if( this.repeat && chunk.height < this.chunkSize && y + chunk.height < ig.system.realHeight ) { - nudgeY = this.chunkSize - chunk.height; + if( this.repeat && chunk.height < this.chunkSize && y + chunk.height < ig.system.realHeight ) { + nudgeY += this.chunkSize - chunk.height; maxChunkY++; } } @@ -209,9 +216,7 @@ ig.BackgroundMap = ig.Map.extend({ // Repeat Y? if( tileY >= this.height || tileY < 0 ) { if( !this.repeat ) { continue; } - tileY = tileY > 0 - ? tileY % this.height - : ((tileY+1) % this.height) + this.height - 1; + tileY = (tileY%this.height + this.height) % this.height; } for( var mapX = -1, pxX = pxMinX; pxX < pxMaxX; mapX++, pxX += this.tilesize ) { @@ -220,9 +225,7 @@ ig.BackgroundMap = ig.Map.extend({ // Repeat X? if( tileX >= this.width || tileX < 0 ) { if( !this.repeat ) { continue; } - tileX = tileX > 0 - ? tileX % this.width - : ((tileX+1) % this.width) + this.width - 1; + tileX = (tileX%this.width + this.width) % this.width; } // Draw! diff --git a/dev/lib/impact/debug/menu.js b/dev/lib/impact/debug/menu.js index cf827f6..4bb44d6 100755 --- a/dev/lib/impact/debug/menu.js +++ b/dev/lib/impact/debug/menu.js @@ -39,7 +39,7 @@ ig.Debug = ig.Class.extend({ var style = ig.$new('link'); style.rel = 'stylesheet'; style.type = 'text/css'; - style.href = 'lib/impact/debug/debug.css'; + style.href = ig.prefix + 'lib/impact/debug/debug.css'; ig.$('body')[0].appendChild( style ); // Create the Debug Container diff --git a/dev/lib/impact/entity.js b/dev/lib/impact/entity.js index c733085..3fa961c 100755 --- a/dev/lib/impact/entity.js +++ b/dev/lib/impact/entity.js @@ -64,7 +64,7 @@ ig.Entity = ig.Class.extend({ this.last.x = this.pos.x; this.last.y = this.pos.y; this.vel.y += ig.game.gravity * ig.system.tick * this.gravityFactor; - + this.vel.x = this.getNewVelocity( this.vel.x, this.accel.x, this.friction.x, this.maxVel.x ); this.vel.y = this.getNewVelocity( this.vel.y, this.accel.y, this.friction.y, this.maxVel.y ); diff --git a/dev/lib/impact/font.js b/dev/lib/impact/font.js index eee24ed..f30d290 100755 --- a/dev/lib/impact/font.js +++ b/dev/lib/impact/font.js @@ -121,21 +121,16 @@ ig.Font = ig.Image.extend({ this.widthMap = []; this.indices = []; - var canvas = ig.$new('canvas'); - canvas.width = image.width; - canvas.height = image.height; - var ctx = canvas.getContext('2d'); - ctx.drawImage( image, 0, 0 ); - var px = ctx.getImageData(0, image.height-1, image.width, 1); + var px = ig.getImagePixels( image, 0, image.height-1, image.width, 1 ); var currentChar = 0; var currentWidth = 0; for( var x = 0; x < image.width; x++ ) { var index = x * 4 + 3; // alpha component of this pixel - if( px.data[index] != 0 ) { + if( px.data[index] > 127 ) { currentWidth++; } - else if( px.data[index] == 0 && currentWidth ) { + else if( px.data[index] < 128 && currentWidth ) { this.widthMap.push( currentWidth ); this.indices.push( x-currentWidth ); currentChar++; diff --git a/dev/lib/impact/image.js b/dev/lib/impact/image.js index 64023a3..47d124a 100755 --- a/dev/lib/impact/image.js +++ b/dev/lib/impact/image.js @@ -86,16 +86,11 @@ ig.Image = ig.Class.extend({ // and copied into another offscreen canvas with the new size. // The scaled offscreen canvas becomes the image (data) of this object. + var origPixels = ig.getImagePixels( this.data, 0, 0, this.width, this.height ); + var widthScaled = this.width * scale; var heightScaled = this.height * scale; - - var orig = ig.$new('canvas'); - orig.width = this.width; - orig.height = this.height; - var origCtx = orig.getContext('2d'); - origCtx.drawImage( this.data, 0, 0, this.width, this.height, 0, 0, this.width, this.height ); - var origPixels = origCtx.getImageData(0, 0, this.width, this.height); - + var scaled = ig.$new('canvas'); scaled.width = widthScaled; scaled.height = heightScaled; diff --git a/dev/lib/impact/impact.js b/dev/lib/impact/impact.js index 3cc9854..4109a6c 100755 --- a/dev/lib/impact/impact.js +++ b/dev/lib/impact/impact.js @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------------- -// Impact Game Engine 1.20 +// Impact Game Engine 1.22 // http://impactjs.com/ // ----------------------------------------------------------------------------- @@ -56,14 +56,26 @@ Array.prototype.random = function() { return this[ Math.floor(Math.random() * this.length) ]; }; -Function.prototype.bind = Function.prototype.bind || function(bind) { - var self = this; - return function(){ - var args = Array.prototype.slice.call(arguments); - return self.apply(bind || null, args); - }; -}; +Function.prototype.bind = Function.prototype.bind || function (oThis) { + if( typeof this !== "function" ) { + throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); + } + var aArgs = Array.prototype.slice.call(arguments, 1), + fToBind = this, + fNOP = function () {}, + fBound = function () { + return fToBind.apply( + (this instanceof fNOP && oThis ? this : oThis), + aArgs.concat(Array.prototype.slice.call(arguments)) + ); + }; + + fNOP.prototype = this.prototype; + fBound.prototype = new fNOP(); + + return fBound; +}; // ----------------------------------------------------------------------------- @@ -72,7 +84,7 @@ Function.prototype.bind = Function.prototype.bind || function(bind) { window.ig = { game: null, debug: null, - version: '1.20', + version: '1.22', global: window, modules: {}, resources: [], @@ -163,7 +175,56 @@ window.ig = { return values; }, - + + // Ah, yes. I love vendor prefixes. So much fun! + setVendorAttribute: function( el, attr, val ) { + var uc = attr.charAt(0).toUpperCase() + attr.substr(1); + el[attr] = el['ms'+uc] = el['moz'+uc] = el['webkit'+uc] = el['o'+uc] = val; + }, + + + getVendorAttribute: function( el, attr ) { + var uc = attr.charAt(0).toUpperCase() + attr.substr(1); + return el[attr] || el['ms'+uc] || el['moz'+uc] || el['webkit'+uc] || el['o'+uc]; + }, + + + normalizeVendorAttribute: function( el, attr ) { + var prefixedVal = ig.getVendorAttribute( el, attr ); + if( !el[attr] && prefixedVal ) { + el[attr] = prefixedVal; + } + }, + + + // This function normalizes getImageData to extract the real, actual + // pixels from an image. The naive method recently failed on retina + // devices with a backgingStoreRatio != 1 + getImagePixels: function( image, x, y, width, height ) { + var canvas = ig.$new('canvas'); + canvas.width = image.width; + canvas.height = image.height; + var ctx = canvas.getContext('2d'); + + // Try to draw pixels as accurately as possible + ig.System.SCALE.CRISP(canvas, ctx); + + var ratio = ig.getVendorAttribute( ctx, 'backingStorePixelRatio' ) || 1; + ig.normalizeVendorAttribute( ctx, 'getImageDataHD' ); + + var realWidth = image.width / ratio, + realHeight = image.height / ratio; + + canvas.width = Math.ceil( realWidth ); + canvas.height = Math.ceil( realHeight ); + + ctx.drawImage( image, 0, 0, realWidth, realHeight ); + + return (ratio === 1) + ? ctx.getImageData( x, y, width, height ) + : ctx.getImageDataHD( x, y, width, height ); + }, + module: function( name ) { if( ig._current ) { @@ -324,8 +385,10 @@ window.ig = { ig.ua.iPhone4 = (ig.ua.iPhone && ig.ua.pixelRatio == 2); ig.ua.iPad = /iPad/i.test(navigator.userAgent); ig.ua.android = /android/i.test(navigator.userAgent); + ig.ua.winPhone = /Windows Phone/i.test(navigator.userAgent); ig.ua.iOS = ig.ua.iPhone || ig.ua.iPad; - ig.ua.mobile = ig.ua.iOS || ig.ua.android; + ig.ua.mobile = ig.ua.iOS || ig.ua.android || ig.ua.winPhone; + ig.ua.touchDevice = (('ontouchstart' in window) || (window.navigator.msMaxTouchPoints)); }, @@ -355,13 +418,8 @@ window.ig = { // Provide ig.setAnimation and ig.clearAnimation as a compatible way to use // requestAnimationFrame if available or setInterval otherwise -// Find vendor prefix, if any -var vendors = ['ms', 'moz', 'webkit', 'o']; -for( var i = 0; i < vendors.length && !window.requestAnimationFrame; i++ ) { - window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame']; -} - // Use requestAnimationFrame if available +ig.normalizeVendorAttribute( window, 'requestAnimationFrame' ); if( window.requestAnimationFrame ) { var next = 1, anims = {}; @@ -481,13 +539,19 @@ window.ig.Class.extend = function(prop) { } Class.prototype = prototype; - Class.constructor = Class; + Class.prototype.constructor = Class; Class.extend = window.ig.Class.extend; Class.inject = inject; return Class; }; +// Merge the ImpactMixin - if present - into the 'ig' namespace. This gives other +// code the chance to modify 'ig' before it's doing any work. +if( window.ImpactMixin ) { + ig.merge(ig, window.ImpactMixin); +} + })(window); diff --git a/dev/lib/impact/input.js b/dev/lib/impact/input.js index e7819c8..4025313 100755 --- a/dev/lib/impact/input.js +++ b/dev/lib/impact/input.js @@ -125,9 +125,18 @@ ig.Input = ig.Class.extend({ ig.system.canvas.addEventListener('mouseup', this.keyup.bind(this), false ); ig.system.canvas.addEventListener('mousemove', this.mousemove.bind(this), false ); - ig.system.canvas.addEventListener('touchstart', this.keydown.bind(this), false ); - ig.system.canvas.addEventListener('touchend', this.keyup.bind(this), false ); - ig.system.canvas.addEventListener('touchmove', this.mousemove.bind(this), false ); + if( ig.ua.touchDevice ) { + // Standard + ig.system.canvas.addEventListener('touchstart', this.keydown.bind(this), false ); + ig.system.canvas.addEventListener('touchend', this.keyup.bind(this), false ); + ig.system.canvas.addEventListener('touchmove', this.mousemove.bind(this), false ); + + // MS + ig.system.canvas.addEventListener('MSPointerDown', this.keydown.bind(this), false ); + ig.system.canvas.addEventListener('MSPointerUp', this.keyup.bind(this), false ); + ig.system.canvas.addEventListener('MSPointerMove', this.mousemove.bind(this), false ); + ig.system.canvas.style.msTouchAction = 'none'; + } }, @@ -157,25 +166,20 @@ ig.Input = ig.Class.extend({ event.preventDefault(); } }, - - mousemove: function( event ) { - var el = ig.system.canvas; + + mousemove: function( event ) { + var internalWidth = parseInt(ig.system.canvas.offsetWidth) || ig.system.realWidth; + var scale = ig.system.scale * (internalWidth / ig.system.realWidth); + var pos = {left: 0, top: 0}; - while( el != null ) { - pos.left += el.offsetLeft; - pos.top += el.offsetTop; - el = el.offsetParent; - } - var tx = event.pageX; - var ty = event.pageY; - if( event.touches ) { - tx = event.touches[0].clientX; - ty = event.touches[0].clientY; + if( ig.system.canvas.getBoundingClientRect ) { + pos = ig.system.canvas.getBoundingClientRect(); } - this.mouse.x = (tx - pos.left) / ig.system.scale; - this.mouse.y = (ty - pos.top) / ig.system.scale; + var ev = event.touches ? event.touches[0] : event; + this.mouse.x = (ev.clientX - pos.left) / scale; + this.mouse.y = (ev.clientY - pos.top) / scale; }, @@ -188,7 +192,8 @@ ig.Input = ig.Class.extend({ keydown: function( event ) { - if( event.target.type == 'text' ) { return; } + var tag = event.target.tagName; + if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; } var code = event.type == 'keydown' ? event.keyCode @@ -212,7 +217,8 @@ ig.Input = ig.Class.extend({ keyup: function( event ) { - if( event.target.type == 'text' ) { return; } + var tag = event.target.tagName; + if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; } var code = event.type == 'keyup' ? event.keyCode @@ -243,13 +249,10 @@ ig.Input = ig.Class.extend({ var element = ig.$( selector ); var that = this; - element.addEventListener('touchstart', function(ev) { - that.touchStart( ev, action ); - }, false); - - element.addEventListener('touchend', function(ev) { - that.touchEnd( ev, action ); - }, false); + element.addEventListener('touchstart', function(ev) {that.touchStart( ev, action );}, false); + element.addEventListener('touchend', function(ev) {that.touchEnd( ev, action );}, false); + element.addEventListener('MSPointerDown', function(ev) {that.touchStart( ev, action );}, false); + element.addEventListener('MSPointerUp', function(ev) {that.touchEnd( ev, action );}, false); }, diff --git a/dev/lib/impact/sound.js b/dev/lib/impact/sound.js index db46866..89fad8c 100755 --- a/dev/lib/impact/sound.js +++ b/dev/lib/impact/sound.js @@ -9,6 +9,12 @@ ig.SoundManager = ig.Class.extend({ format: null, init: function() { + // Quick sanity check if the Browser supports the Audio tag + if( !ig.Sound.enabled || !window.Audio ) { + ig.Sound.enabled = false; + return; + } + // Probe sound formats and determine the file extension to load var probe = new Audio(); for( var i = 0; i < ig.Sound.use.length; i++ ) { diff --git a/dev/lib/impact/system.js b/dev/lib/impact/system.js index d654de2..a5739ef 100755 --- a/dev/lib/impact/system.js +++ b/dev/lib/impact/system.js @@ -34,6 +34,13 @@ ig.System = ig.Class.extend({ this.context = this.canvas.getContext('2d'); this.getDrawPos = ig.System.drawMode; + + // Automatically switch to crisp scaling when using a scale + // other than 1 + if( this.scale != 1 ) { + ig.System.scaleMode = ig.System.SCALE.CRISP; + } + ig.System.scaleMode( this.canvas, this.context ); }, @@ -108,7 +115,7 @@ ig.System = ig.Class.extend({ }, - getDrawPos: null, // Set through constructor + getDrawPos: null // Set through constructor }); ig.System.DRAW = { @@ -118,4 +125,21 @@ ig.System.DRAW = { }; ig.System.drawMode = ig.System.DRAW.SMOOTH; -}); \ No newline at end of file +ig.System.SCALE = { + CRISP: function( canvas, context ) { + ig.setVendorAttribute( context, 'imageSmoothingEnabled', false ); + canvas.style.imageRendering = '-moz-crisp-edges'; + canvas.style.imageRendering = '-o-crisp-edges'; + canvas.style.imageRendering = '-webkit-optimize-contrast'; + canvas.style.imageRendering = 'crisp-edges'; + canvas.style.msInterpolationMode = 'nearest-neighbor'; // No effect on Canvas :/ + }, + SMOOTH: function( canvas, context ) { + ig.setVendorAttribute( context, 'imageSmoothingEnabled', true ); + canvas.style.imageRendering = ''; + canvas.style.msInterpolationMode = ''; + } +}; +ig.System.scaleMode = ig.System.SCALE.SMOOTH; + +}); diff --git a/dev/lib/impact/timer.js b/dev/lib/impact/timer.js index 7ff455c..d87747f 100755 --- a/dev/lib/impact/timer.js +++ b/dev/lib/impact/timer.js @@ -58,7 +58,7 @@ ig.Timer = ig.Class.extend({ }); ig.Timer._last = 0; -ig.Timer.time = 0; +ig.Timer.time = Number.MIN_VALUE; ig.Timer.timeScale = 1; ig.Timer.maxStep = 0.05; diff --git a/dev/lib/weltmeister/collisiontiles-64.png b/dev/lib/weltmeister/collisiontiles-64.png index 55efd3c974fc724316d8cc63b400e9f56d9b4c51..0409c7cd4b8c56c41c40cf52e2ce12d452d208bb 100755 GIT binary patch literal 10274 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 literal 19656 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 bj4{9E{%&D==I}N6RRqRoL%{lLbWYm8QLOM6 diff --git a/dev/lib/weltmeister/config.js b/dev/lib/weltmeister/config.js index 417b72d..95beaef 100755 --- a/dev/lib/weltmeister/config.js +++ b/dev/lib/weltmeister/config.js @@ -44,8 +44,8 @@ wm.config = { 'view': { 'zoom': 1, - 'zoomMax': 1, - 'zoomMin': 1, + 'zoomMax': 4, + 'zoomMin': 0.125, 'grid': false }, diff --git a/dev/lib/weltmeister/edit-entities.js b/dev/lib/weltmeister/edit-entities.js index 32fd24e..80322f9 100755 --- a/dev/lib/weltmeister/edit-entities.js +++ b/dev/lib/weltmeister/edit-entities.js @@ -147,17 +147,33 @@ wm.EditEntities = ig.Class.extend({ selectEntityAt: function( x, y ) { this.selector.pos = { x: x, y: y }; + // Find all possible selections + var possibleSelections = []; for( var i = 0; i < this.entities.length; i++ ) { - var ent = this.entities[i]; - if( ent.touches(this.selector) ) { - this.selector.offset = {x: (x - ent.pos.x + ent.offset.x), y: (y - ent.pos.y + ent.offset.y)}; - this.selectEntity( ent ); - this.wasSelectedOnScaleBorder = this.isOnScaleBorder( ent, this.selector ); - return ent; + if( this.entities[i].touches(this.selector) ) { + possibleSelections.push( this.entities[i] ); } } - this.selectEntity( null ); - return false; + + // Nothing found? Early out. + if( !possibleSelections.length ) { + this.selectEntity( null ); + return false; + } + + // Find the 'next' selection + var selectedIndex = possibleSelections.indexOf(this.selectedEntity); + var nextSelection = (selectedIndex + 1) % possibleSelections.length; + var ent = possibleSelections[nextSelection]; + + // Select it! + this.selector.offset = { + x: (x - ent.pos.x + ent.offset.x), + y: (y - ent.pos.y + ent.offset.y) + }; + this.selectEntity( ent ); + this.wasSelectedOnScaleBorder = this.isOnScaleBorder( ent, this.selector ); + return ent; }, diff --git a/dev/lib/weltmeister/entities.js b/dev/lib/weltmeister/entities.js index 97e99b0..68fa638 100755 --- a/dev/lib/weltmeister/entities.js +++ b/dev/lib/weltmeister/entities.js @@ -35,7 +35,9 @@ var req = $.ajax({ var moduleNames = []; var modules = {}; for( var i = 0; i < files.length; i++ ) { - var name = files[i].replace(/^lib\/|\.js$/g,'').replace(/\//g, '.'); + var name = files[i] + .replace(new RegExp("^"+ig.lib+"|\\.js$", "g"), '') + .replace(/\//g, '.'); moduleNames.push( name ); modules[name] = files[i]; } diff --git a/dev/lib/weltmeister/evented-input.js b/dev/lib/weltmeister/evented-input.js index e453b86..b3c9dc2 100755 --- a/dev/lib/weltmeister/evented-input.js +++ b/dev/lib/weltmeister/evented-input.js @@ -15,7 +15,8 @@ wm.EventedInput = ig.Input.extend({ keydown: function( event ) { - if( event.target.type == 'text' ) { return; } + var tag = event.target.tagName; + if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; } var code = event.type == 'keydown' ? event.keyCode @@ -35,7 +36,9 @@ wm.EventedInput = ig.Input.extend({ keyup: function( event ) { - if( event.target.type == 'text' ) { return; } + var tag = event.target.tagName; + if( tag == 'INPUT' || tag == 'TEXTAREA' ) { return; } + var code = event.type == 'keyup' ? event.keyCode : (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1); diff --git a/dev/lib/weltmeister/weltmeister.js b/dev/lib/weltmeister/weltmeister.js index 2ef2f26..cddc002 100755 --- a/dev/lib/weltmeister/weltmeister.js +++ b/dev/lib/weltmeister/weltmeister.js @@ -114,6 +114,11 @@ wm.Weltmeister = ig.Class.extend({ $('input#toggleSidebar').toggleClass('active'); }); + // Always unfocus current input field when clicking the canvas + $('#canvas').mousedown(function(){ + $('input:focus').blur(); + }); + this.undo = new wm.Undo( wm.config.undoLevels ); diff --git a/dev/media/04b03.font.png b/dev/media/04b03.font.png index 3e137af2840cee5acf0a5637a0c41d45761ca202..846aa2c2365e827f825bb549fc9000c8dcb00219 100755 GIT binary patch delta 470 zcmV;{0V)2h8{`9!7=Ho-00004B48f?000b7OjJbx00960|A2si|NsArYC~uM000AY zQchC<008=S#NGe^0fb3JK~#8Ny-_i$9We|Xm{#Dc2-F&sBcyrv2;_Ka1ZoXFLat!g zGKT#Y|Gl3O2&4#^Wi=Yf>p?3#zUrW87n1H=ge#EbPgjmvr5+` zsV3}b%T5nc-T(jq M07*qoM6N<$f`Q4^ivR!s literal 3500 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