ig.module( 'weltmeister.edit-entities' ) .requires( 'impact.game', 'impact.background-map', 'weltmeister.config', 'weltmeister.tile-select', 'weltmeister.entities' ) .defines(function(){ "use strict"; wm.EditEntities = ig.Class.extend({ visible: true, active: true, div: null, hotkey: -1, ignoreLastClick: false, name: 'entities', entities: [], namedEntities: {}, selectedEntity: null, entityClasses: {}, menuDiv: null, selector: {size:{x:2, y:2}, pos:{x:0,y:0}, offset:{x:0,y:0}}, wasSelectedOnScaleBorder: false, gridSize: wm.config.entityGrid, entityDefinitions: null, init: function( div ) { this.div = div; div.bind( 'mouseup', this.click.bind(this) ); this.div.children('.visible').bind( 'mousedown', this.toggleVisibilityClick.bind(this) ); this.menu = $('#entityMenu'); this.importEntityClass( wm.entityModules ); this.entityDefinitions = $('#entityDefinitions'); $('#entityKey').bind( 'keydown', function(ev){ if( ev.which == 13 ){ $('#entityValue').focus(); return false; } return true; }); $('#entityValue').bind( 'keydown', this.setEntitySetting.bind(this) ); }, clear: function() { this.entities = []; this.selectEntity( null ); }, sort: function() { this.entities.sort( ig.Game.SORT.Z_INDEX ); }, // ------------------------------------------------------------------------- // Loading, Saving fileNameToClassName: function( name ) { var typeName = '-' + name.replace(/^.*\/|\.js/g,''); typeName = typeName.replace(/-(\w)/g, function( m, a ) { return a.toUpperCase(); }); return 'Entity' + typeName; }, importEntityClass: function( modules ) { var unloadedClasses = []; for( var m in modules ) { var className = this.fileNameToClassName(modules[m]); var entityName = className.replace(/^Entity/, ''); // ig.global[className] should be the actual class object if( className && ig.global[className] ) { // Ignore entities that have the _wmIgnore flag if( !ig.global[className].prototype._wmIgnore ) { var a = $( '
', { 'id': className, 'href': '#', 'html': entityName, 'mouseup': this.newEntityClick.bind(this) }); this.menu.append( a ); this.entityClasses[className] = m; } } else { unloadedClasses.push( modules[m] + ' (expected name: ' + className + ')' ); } } if( unloadedClasses.length > 0 ) { var warning = 'The following entity classes were not loaded due to\n' + 'file and class name mismatches: \n\n' + unloadedClasses.join( '\n' ); alert( warning ); } }, getEntityByName: function( name ) { return this.namedEntities[name]; }, getSaveData: function() { var ents = []; for( var i = 0; i < this.entities.length; i++ ) { var ent = this.entities[i]; var type = ent._wmClassName; var data = {type:type,x:ent.pos.x,y:ent.pos.y}; var hasSettings = false; for( var p in ent._wmSettings ) { hasSettings = true; } if( hasSettings ) { data.settings = ent._wmSettings; } ents.push( data ); } return ents; }, // ------------------------------------------------------------------------- // Selecting 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++ ) { if( this.entities[i].touches(this.selector) ) { possibleSelections.push( this.entities[i] ); } } // 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; }, selectEntity: function( entity ) { if( entity && entity != this.selectedEntity ) { this.selectedEntity = entity; $('#entitySettings').fadeOut(100,(function(){ this.loadEntitySettings(); $('#entitySettings').fadeIn(100); }).bind(this)); } else if( !entity ) { $('#entitySettings').fadeOut(100); $('#entityKey').blur(); $('#entityValue').blur(); } this.selectedEntity = entity; $('#entityKey').val(''); $('#entityValue').val(''); }, // ------------------------------------------------------------------------- // Creating, Deleting, Moving deleteSelectedEntity: function() { if( !this.selectedEntity ) { return false; } ig.game.undo.commitEntityDelete( this.selectedEntity ); this.removeEntity( this.selectedEntity ); this.selectEntity( null ); return true; }, removeEntity: function( ent ) { if( ent.name ) { delete this.namedEntities[ent.name]; } this.entities.erase( ent ); }, cloneSelectedEntity: function() { if( !this.selectedEntity ) { return false; } var className = this.selectedEntity._wmClassName; var settings = ig.copy(this.selectedEntity._wmSettings); if( settings.name ) { settings.name = settings.name + '_clone'; } var x = this.selectedEntity.pos.x + this.gridSize; var y = this.selectedEntity.pos.y; var newEntity = this.spawnEntity( className, x, y, settings ); newEntity._wmSettings = settings; this.selectEntity( newEntity ); ig.game.undo.commitEntityCreate( newEntity ); return true; }, dragOnSelectedEntity: function( x, y ) { if( !this.selectedEntity ) { return false; } // scale or move? if( this.selectedEntity._wmScalable && this.wasSelectedOnScaleBorder ) { this.scaleSelectedEntity( x, y ); } else { this.moveSelectedEntity( x, y ) } ig.game.undo.pushEntityEdit( this.selectedEntity ); return true; }, moveSelectedEntity: function( x, y ) { x = Math.round( (x - this.selector.offset.x ) / this.gridSize ) * this.gridSize + this.selectedEntity.offset.x; y = Math.round( (y - this.selector.offset.y ) / this.gridSize ) * this.gridSize + this.selectedEntity.offset.y; // new position? if( this.selectedEntity.pos.x != x || this.selectedEntity.pos.y != y ) { $('#entityDefinitionPosX').text( x ); $('#entityDefinitionPosY').text( y ); this.selectedEntity.pos.x = x; this.selectedEntity.pos.y = y; } }, scaleSelectedEntity: function( x, y ) { var scale = this.wasSelectedOnScaleBorder; var w = Math.round( x / this.gridSize ) * this.gridSize - this.selectedEntity.pos.x; if( !this.selectedEntity._wmSettings.size ) { this.selectedEntity._wmSettings.size = {}; } if( scale == 'n' ) { var h = this.selectedEntity.pos.y - Math.round( y / this.gridSize ) * this.gridSize; if( this.selectedEntity.size.y + h <= this.gridSize ) { h = (this.selectedEntity.size.y - this.gridSize) * -1; } this.selectedEntity.size.y += h; this.selectedEntity.pos.y -= h; } else if( scale == 's' ) { var h = Math.round( y / this.gridSize ) * this.gridSize - this.selectedEntity.pos.y; this.selectedEntity.size.y = Math.max( this.gridSize, h ); } else if( scale == 'e' ) { var w = Math.round( x / this.gridSize ) * this.gridSize - this.selectedEntity.pos.x; this.selectedEntity.size.x = Math.max( this.gridSize, w ); } else if( scale == 'w' ) { var w = this.selectedEntity.pos.x - Math.round( x / this.gridSize ) * this.gridSize; if( this.selectedEntity.size.x + w <= this.gridSize ) { w = (this.selectedEntity.size.x - this.gridSize) * -1; } this.selectedEntity.size.x += w; this.selectedEntity.pos.x -= w; } this.selectedEntity._wmSettings.size.x = this.selectedEntity.size.x; this.selectedEntity._wmSettings.size.y = this.selectedEntity.size.y; this.loadEntitySettings(); }, newEntityClick: function( ev ) { this.hideMenu(); var newEntity = this.spawnEntity( ev.target.id, 0, 0, {} ); this.selectEntity( newEntity ); this.moveSelectedEntity( this.selector.pos.x, this.selector.pos.y ); ig.editor.setModified(); ig.game.undo.commitEntityCreate( newEntity ); }, spawnEntity: function( className, x, y, settings ) { settings = settings || {}; var entityClass = ig.global[ className ]; if( entityClass ) { var newEntity = new (entityClass)( x, y, settings ); newEntity._wmInEditor = true; newEntity._wmClassName = className; newEntity._wmSettings = {}; for( var s in settings ) { newEntity._wmSettings[s] = settings[s]; } this.entities.push( newEntity ); if( settings.name ) { this.namedEntities[settings.name] = newEntity; } this.sort(); return newEntity; } return null; }, isOnScaleBorder: function( entity, selector ) { var border = 2; var w = selector.pos.x - entity.pos.x; var h = selector.pos.y - entity.pos.y; if( w < border ) return 'w'; if( w > entity.size.x - border ) return 'e'; if( h < border ) return 'n'; if( h > entity.size.y - border ) return 's'; return false; }, // ------------------------------------------------------------------------- // Settings loadEntitySettings: function(ent) { if( !this.selectedEntity ) { return; } var html = '