PageRenderTime 61ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/mstandio/HotSpotPlacer/HotSpotPlacer.as

http://universalmap.googlecode.com/
ActionScript | 475 lines | 392 code | 67 blank | 16 comment | 33 complexity | fc710e8ff201038ea14ed386f4f41ff2 MD5 | raw file
  1. package plugins.mstandio.HotSpotPlacer{
  2. import adobe.utils.ProductManager;
  3. import flash.display.Sprite;
  4. import flash.text.TextField;
  5. import flash.text.TextFormat;
  6. import flash.events.Event;
  7. import flash.events.MouseEvent;
  8. import flash.display.Bitmap;
  9. import flash.display.Loader;
  10. import gs.TweenLite;
  11. import flash.net.URLRequest;
  12. import flash.events.IOErrorEvent;
  13. import flash.system.ApplicationDomain;
  14. import flash.utils.Dictionary;
  15. import flash.utils.getDefinitionByName;
  16. import zephyr.BroadcastEvent;
  17. import plugins.mstandio.HotSpotPlacer.configure.*;
  18. import plugins.mstandio.HotSpotPlacer.hotspot.Hotspotdata;
  19. import plugins.mstandio.utils.combobox.ComboBox;
  20. import plugins.mstandio.utils.combobox.ComboBoxEvent;
  21. import plugins.mstandio.utils.imageloader.ImageLoader;
  22. /**
  23. * Simple tool, helpfull for placing SpaceHotspots
  24. * @author mstandio
  25. */
  26. public class HotSpotPlacer extends Sprite{
  27. private var txtPan:TextField;
  28. private var txtTilt:TextField;
  29. private var txtZoom:TextField;
  30. private var txtFormat:TextFormat;
  31. private var box:Sprite;
  32. private var cross:Sprite;
  33. private var toggleCrossButton:Sprite;
  34. private var toggleXmlButton:Sprite;
  35. private var showChangesButton:Sprite;
  36. [Embed(source="images/cross.png")]
  37. public var Bitmap_crossIcon:Class;
  38. [Embed(source="images/cross_v.png")]
  39. public var Bitmap_crossvIcon:Class;
  40. [Embed(source="images/cross_h.png")]
  41. public var Bitmap_crosshIcon:Class;
  42. [Embed(source="images/xml_v.png")]
  43. public var Bitmap_xmlvIcon:Class;
  44. [Embed(source="images/xml_h.png")]
  45. public var Bitmap_xmlhIcon:Class;
  46. [Embed(source="images/play.png")]
  47. public var Bitmap_playIcon:Class;
  48. private var hotspotBar:Sprite;
  49. private var hotspotAddButton:Sprite;
  50. private var hotspotRemoveButton:Sprite;
  51. private var hotspotEditButton:Sprite;
  52. [Embed(source="images/add_enabled.png")]
  53. public var Bitmap_addenabled:Class;
  54. [Embed(source="images/add_disabled.png")]
  55. public var Bitmap_adddisabled:Class;
  56. [Embed(source="images/remove_enabled.png")]
  57. public var Bitmap_removeenabled:Class;
  58. [Embed(source="images/remove_disabled.png")]
  59. public var Bitmap_removedisabled:Class;
  60. [Embed(source="images/edit_enabled.png")]
  61. public var Bitmap_editenabled:Class;
  62. [Embed(source="images/edit_disabled.png")]
  63. public var Bitmap_editdisabled:Class;
  64. private var configurationWindow:ConfigurationWindow;
  65. private var comboBox:ComboBox;
  66. private var files:Array;
  67. private var imagefield:Sprite;
  68. private var hotSpotImage:Loader; // External image
  69. private var statistics:Boolean;
  70. private var pan:Number;
  71. private var tilt:Number;
  72. private var zoom:Number;
  73. private var cameraFocus:Number;
  74. private var SpaceHotspots:Array;
  75. private var currentSpace:String = "";
  76. private var BroadcastEvent:Class;
  77. private var ModuleLoader:Class;
  78. private var moduleLoader:Object;
  79. private var PanoSalado:Class;
  80. private var layerByName:Dictionary;
  81. private var panoSalado:Object;
  82. private var txtLog:TextField;
  83. public function HotSpotPlacer() {
  84. if (stage) stageReady();
  85. else addEventListener(Event.ADDED_TO_STAGE, stageReady, false, 0, true);
  86. }
  87. private function stageReady(e:Event = null):void {
  88. removeEventListener(Event.ADDED_TO_STAGE, stageReady);
  89. BroadcastEvent = ApplicationDomain.currentDomain.getDefinition("zephyr.BroadcastEvent") as Class;
  90. ModuleLoader = ApplicationDomain.currentDomain.getDefinition("ModuleLoader") as Class;
  91. moduleLoader = ModuleLoader(this.root.parent);
  92. this.stage.addEventListener(Event.RESIZE, this.handleStageResize);
  93. moduleLoader.addEventListener(BroadcastEvent.ALL_LAYERS_LOADED, layersReady, false, 0, true);
  94. moduleLoader.addEventListener(BroadcastEvent.SPACE_LOADED, spaceLoaded, false, 0, true);
  95. moduleLoader.addEventListener(BroadcastEvent.CAMERA_INIT, camInit, false, 0, true);
  96. moduleLoader.addEventListener(BroadcastEvent.CAMERA_SPIN, camSpin, false, 0, true);
  97. moduleLoader.addEventListener(BroadcastEvent.CAMERA_ZOOM, camZoom, false, 0, true);
  98. }
  99. private function layersReady(e:zephyr.BroadcastEvent):void {
  100. PanoSalado = ApplicationDomain.currentDomain.getDefinition("PanoSalado") as Class;
  101. layerByName = Dictionary( moduleLoader["layerByName"] );
  102. panoSalado = PanoSalado( layerByName["PanoSalado"] );
  103. this.getSettings();
  104. this.buildAll();
  105. this.handleStageResize();
  106. this.setImage();
  107. }
  108. private function getSettings():void{
  109. var settings:XML = moduleLoader.xmlByName["HotSpotPlacer"];
  110. this.files = new Array();
  111. this.files.push( { label:"[default]" } );
  112. for each(var file:XML in settings.elements()) {
  113. this.files.push({ label:file }); // urls of files
  114. }
  115. settings = moduleLoader.xmlByName["PanoSalado"];
  116. // gets from settings, after space loaded it can be overwritten by space
  117. this.cameraFocus = (settings.spaces.@cameraFocus != undefined) ? Number(settings.spaces.@cameraFocus) : 100;
  118. // it can not be overwritten by space, it should though
  119. this.statistics = (settings.spaces.@statistics != undefined) ? settings.spaces.@statistics == "true" : false;
  120. }
  121. private function buildAll():void {
  122. this.cross = new Sprite();
  123. this.cross.mouseEnabled = false;
  124. this.cross.mouseChildren = false;
  125. this.hotspotBar = new Sprite();
  126. this.hotspotBar.graphics.beginFill(0x000000);
  127. this.hotspotBar.graphics.drawRect(0, 0, 78, 28);
  128. this.cross.addChild(this.hotspotBar);
  129. this.hotspotAddButton = new Sprite();
  130. var a_d:Bitmap = new Bitmap(new Bitmap_adddisabled().bitmapData);
  131. this.hotspotAddButton.addChild(a_d);
  132. this.hotspotBar.addChild(this.hotspotAddButton);
  133. this.hotspotAddButton.x = 3;
  134. this.hotspotAddButton.y = 3;
  135. this.hotspotRemoveButton = new Sprite();
  136. var r_d:Bitmap = new Bitmap(new Bitmap_removedisabled().bitmapData);
  137. this.hotspotRemoveButton.addChild(r_d);
  138. this.hotspotBar.addChild(this.hotspotRemoveButton);
  139. this.hotspotRemoveButton.x = 28;
  140. this.hotspotRemoveButton.y = 3;
  141. this.hotspotEditButton = new Sprite();
  142. var e_d:Bitmap = new Bitmap(new Bitmap_editdisabled().bitmapData);
  143. this.hotspotEditButton.addChild(e_d);
  144. this.hotspotBar.addChild(this.hotspotEditButton);
  145. this.hotspotEditButton.x = 53;
  146. this.hotspotEditButton.y = 3;
  147. this.imagefield = new Sprite();
  148. this.imagefield.name = "imagefield";
  149. this.cross.addChild(this.imagefield);
  150. this.addChild(this.cross);
  151. this.txtFormat = new TextFormat();
  152. this.txtFormat.size = 14;
  153. this.txtFormat.color = "0xffffff"
  154. this.txtFormat.blockIndent = 0;
  155. this.txtFormat.font = "Arial";
  156. this.box = new Sprite();
  157. this.box.graphics.beginFill(0x000000);
  158. this.box.graphics.drawRect(0, 0, 191, 60);
  159. this.box.graphics.endFill();
  160. this.addChild(this.box);
  161. this.txtPan = new TextField();
  162. this.txtPan.defaultTextFormat = this.txtFormat;
  163. this.txtPan.height = 18;
  164. this.txtPan.width = 100;
  165. this.box.addChild(this.txtPan);
  166. this.txtTilt = new TextField();
  167. this.txtTilt.defaultTextFormat = this.txtFormat;
  168. this.txtTilt.y = 18;
  169. this.txtTilt.height = 18;
  170. this.txtTilt.width = 100;
  171. this.box.addChild(this.txtTilt);
  172. this.txtZoom = new TextField();
  173. this.txtZoom.defaultTextFormat = this.txtFormat;
  174. this.txtZoom.y = 36;
  175. this.txtZoom.height = 18;
  176. this.txtZoom.width = 100;
  177. this.box.addChild(this.txtZoom);
  178. this.toggleCrossButton = new Sprite();
  179. var c_i:Bitmap = new Bitmap(new Bitmap_crossvIcon().bitmapData);
  180. this.toggleCrossButton.addChild(c_i);
  181. this.box.addChild(this.toggleCrossButton);
  182. this.toggleCrossButton.x = 166;
  183. this.toggleCrossButton.y = 35;
  184. this.toggleCrossButton.addEventListener(MouseEvent.CLICK, toggleCross);
  185. this.toggleXmlButton = new Sprite();
  186. var x_i:Bitmap = new Bitmap(new Bitmap_xmlhIcon().bitmapData);
  187. this.toggleXmlButton.addChild(x_i);
  188. this.box.addChild(this.toggleXmlButton);
  189. this.toggleXmlButton.x = 140;
  190. this.toggleXmlButton.y = 35;
  191. this.toggleXmlButton.addEventListener(MouseEvent.CLICK, toggleXml);
  192. this.showChangesButton = new Sprite();
  193. var p_i:Bitmap = new Bitmap(new Bitmap_playIcon().bitmapData);
  194. this.showChangesButton.addChild(p_i);
  195. this.box.addChild(this.showChangesButton);
  196. this.showChangesButton.x = 114;
  197. this.showChangesButton.y = 35;
  198. this.showChangesButton.addEventListener(MouseEvent.CLICK, showchanges);
  199. this.txtLog = new TextField();
  200. this.txtLog.text = "###";
  201. this.txtLog.defaultTextFormat = this.txtFormat;
  202. this.txtLog.y = 52;
  203. this.txtLog.height = 18;
  204. this.txtLog.width = 100;
  205. this.box.addChild(this.txtLog);
  206. if(this.files.length>1){
  207. this.comboBox = new ComboBox(this.files);
  208. this.comboBox.y = 65;
  209. this.addChild(this.comboBox);
  210. this.addEventListener(ComboBoxEvent.LABEL_CHANGED, comboBoxLabelChanged);
  211. }
  212. this.configurationWindow = new ConfigurationWindow();
  213. this.addChild(this.configurationWindow);
  214. //this.configurationWindow.setText(panoSalado.settings);
  215. }
  216. private function comboBoxLabelChanged(e:ComboBoxEvent):void {
  217. this.setImage(e.info.label);
  218. }
  219. /**
  220. *
  221. * @param e
  222. */
  223. private function spaceLoaded(e:zephyr.BroadcastEvent):void {
  224. this.currentSpace = e.info.spaceLoaded;
  225. var spaces:XML= XML(moduleLoader.xmlByName["PanoSalado"].spaces);
  226. var space:XML = this.getSpaceById(spaces, this.currentSpace);
  227. this.cameraFocus = (space.@cameraFocus != undefined) ? Number(space.@cameraFocus) :
  228. ((spaces.@cameraFocus != undefined)? Number(spaces.@cameraFocus): 100); // 100 default
  229. this.zoom = (space.@cameraZoom != undefined) ? Number(space.@cameraZoom) :
  230. ((spaces.@cameraZoom != undefined)? Number(spaces.@cameraZoom): 12); // 12 default
  231. this.rescaleImage();
  232. this.zoom = 0; // couse initial zoom wont be displayed in txtZoom
  233. this.getCurrentHotspots();
  234. }
  235. private var imgLoader:ImageLoader;
  236. private function getCurrentHotspots():void {
  237. // get list of SpaceHotspots in current space
  238. var space:XML = this.getSpaceById(XML((XML(panoSalado.settings)).spaces), this.currentSpace);
  239. this.SpaceHotspots = new Array();
  240. var imgSrcs:Array = new Array();
  241. for each(var hotspot:XML in space.elements()) {
  242. if (String(hotspot.name()).toLowerCase() == "hotspot") {
  243. this.SpaceHotspots.push(new Hotspotdata(hotspot.@id, hotspot.@pan, hotspot.@tilt, hotspot.file.text()));
  244. imgSrcs.push(hotspot.file.text());
  245. }
  246. }
  247. // get size of used SpaceHotspots so it can be detected when center of screen is over hotspot
  248. imgLoader = new ImageLoader();
  249. imgLoader.addEventListener(ImageLoader.LOAD_ERROR,imageLoaderError);
  250. imgLoader.addEventListener(ImageLoader.IMGS_LOADED,imageLoaderDone);
  251. imgLoader.loadImgs(imgSrcs);
  252. }
  253. private function imageLoaderDone(e:Event):void{
  254. imgLoader.removeEventListener(ImageLoader.LOAD_ERROR,imageLoaderDone);
  255. imgLoader.removeEventListener(ImageLoader.IMGS_LOADED,imageLoaderError);
  256. // update SpaceHotspots list with actual sizes
  257. for (var i:Number = 0; i < imgLoader.bitmapsArray.length; i++ ) {
  258. (Hotspotdata(this.SpaceHotspots[i])).width = (Bitmap(imgLoader.bitmapsArray[i])).width;
  259. (Hotspotdata(this.SpaceHotspots[i])).height = (Bitmap(imgLoader.bitmapsArray[i])).height;
  260. this.configurationWindow.append((Hotspotdata(this.SpaceHotspots[i])).id);
  261. }
  262. this.imgLoader = null;
  263. }
  264. private function imageLoaderError(e:Event):void {
  265. imgLoader.removeEventListener(ImageLoader.LOAD_ERROR,imageLoaderDone);
  266. imgLoader.removeEventListener(ImageLoader.IMGS_LOADED,imageLoaderError);
  267. // dunno what now -_-'
  268. // when it fails, how it shows ? is bitmap null or it fails loading rest of them
  269. }
  270. private function toggleCross(e:Event):void {
  271. this.toggleCrossButton.removeChildAt(0);
  272. var c_i:Bitmap;
  273. if (this.cross.visible) {
  274. c_i = new Bitmap(new Bitmap_crosshIcon().bitmapData);
  275. this.cross.visible = false;
  276. this.comboBox.visible = false;
  277. }else {
  278. c_i = new Bitmap(new Bitmap_crossvIcon().bitmapData);
  279. this.cross.visible = true;
  280. this.comboBox.visible = true;
  281. }
  282. this.toggleCrossButton.addChild(c_i);
  283. }
  284. private function toggleXml(e:Event):void {
  285. this.toggleXmlButton.removeChildAt(0);
  286. var x_i:Bitmap;
  287. if (this.configurationWindow.visible) {
  288. x_i = new Bitmap(new Bitmap_xmlhIcon().bitmapData);
  289. this.configurationWindow.visible = false;
  290. }else {
  291. x_i = new Bitmap(new Bitmap_xmlvIcon().bitmapData);
  292. this.configurationWindow.visible = true;
  293. }
  294. this.toggleXmlButton.addChild(x_i);
  295. }
  296. private function showchanges(e:Event):void {
  297. panoSalado.settings = XML(this.configurationWindow.getText());
  298. this.configurationWindow.setText(panoSalado.settings);
  299. panoSalado.loadSpace("reloadSpaces");
  300. }
  301. private function centerImageField() :void{
  302. this.imagefield.x = this.stage.stageWidth * 0.5 - this.imagefield.width * 0.5;
  303. this.imagefield.y = this.stage.stageHeight * 0.5 - this.imagefield.height * 0.5;
  304. }
  305. private function handleStageResize(e:Event=null):void {
  306. this.cross.x = this.cross.y = 0;
  307. var bigCrossWidth:Number = 2;
  308. this.cross.graphics.clear();
  309. this.cross.graphics.beginFill(0x000000, 1);
  310. this.cross.graphics.drawRect(this.stage.stageWidth * 0.5 - bigCrossWidth * 0.5, 0, bigCrossWidth, this.stage.stageHeight)
  311. this.cross.graphics.drawRect(0, this.stage.stageHeight * 0.5 - bigCrossWidth * 0.5, this.stage.stageWidth, bigCrossWidth);
  312. this.cross.graphics.endFill();
  313. this.centerImageField();
  314. this.comboBox.y = 5;
  315. this.comboBox.x = 200;
  316. this.box.x = 0
  317. this.box.y = this.statistics ? 80 : 0;
  318. this.hotspotBar.x = this.stage.stageWidth - this.hotspotBar.width ;
  319. this.hotspotBar.y = this.stage.stageHeight *0.5 - this.hotspotBar.height;
  320. }
  321. private function setImage(label:String = null):void {
  322. while(this.imagefield.numChildren>0) {
  323. this.imagefield.removeChildAt(0);
  324. }
  325. if (label == null || label == "[default]") {
  326. var c_i:Bitmap = new Bitmap(new Bitmap_crossIcon().bitmapData);
  327. this.imagefield.addChild(c_i);
  328. this.centerImageField();
  329. }else {
  330. this.hotSpotImage = new Loader();
  331. var request:URLRequest = new URLRequest(label);
  332. this.hotSpotImage.load(request);
  333. this.hotSpotImage.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
  334. this.hotSpotImage.addEventListener(IOErrorEvent.IO_ERROR, imageNotLoaded);
  335. }
  336. }
  337. private function imageLoaded(e:Event):void {
  338. this.hotSpotImage.removeEventListener(Event.COMPLETE, imageLoaded);
  339. this.hotSpotImage.removeEventListener(IOErrorEvent.IO_ERROR, imageLoaded);
  340. this.imagefield.addChild(this.hotSpotImage);
  341. this.centerImageField();
  342. }
  343. private function imageNotLoaded(e:Event):void {
  344. this.imagefield.removeEventListener(IOErrorEvent.IO_ERROR, imageLoaded);
  345. this.imagefield.removeEventListener(Event.COMPLETE, imageLoaded);
  346. TweenLite.killDelayedCallsTo(setImage);
  347. TweenLite.delayedCall(5, setImage);
  348. }
  349. private function updateTxtFields(pan:Number, tilt:Number, zoom:Number):void {
  350. if (pan != this.pan) this.txtPan.text = "pan: " + this.roundToN(this.validatePan(pan),3);
  351. if (tilt != this.tilt) this.txtTilt.text= "tilt: " + -this.roundToN(tilt,3);
  352. if (zoom != this.zoom) this.txtZoom.text= "zoom: " + this.roundToN(zoom,3);
  353. }
  354. private function detectOverHotspot():void {
  355. }
  356. private function camInit(e:zephyr.BroadcastEvent):void {
  357. this.updateTxtFields(e.info.pan, e.info.tilt, e.info.zoom);
  358. this.pan = e.info.pan;
  359. this.tilt = e.info.tilt;
  360. this.zoom = e.info.zoom;
  361. }
  362. private function camSpin(e:zephyr.BroadcastEvent):void {
  363. this.updateTxtFields(e.info.spin.split(",")[1], e.info.spin.split(",")[0], this.zoom);
  364. if (this.checkHotspots(e.info.spin.split(",")[1], e.info.spin.split(",")[0])) {
  365. this.txtLog.text = "!- " + overHotspotId;
  366. }else {
  367. this.txtLog.text = "nope";
  368. }
  369. }
  370. private var overHotspot:Boolean;
  371. private var overHotspotId:String;
  372. private function checkHotspots(pan:Number, tilt:Number):Boolean {
  373. for (var i:Number; i < this.SpaceHotspots.length; i++) {
  374. if ((Hotspotdata(SpaceHotspots[i])).crossInside(pan, tilt)) {
  375. this.overHotspot = true;
  376. this.overHotspotId = (Hotspotdata(SpaceHotspots[i])).id;
  377. return true;
  378. }
  379. }
  380. this.overHotspot = false;
  381. return false;
  382. }
  383. private function camZoom(e:zephyr.BroadcastEvent):void {
  384. this.updateTxtFields(this.pan, this.tilt, e.info.zoom);
  385. this.zoom = e.info.zoom;
  386. this.rescaleImage();
  387. }
  388. private function rescaleImage():void {
  389. this.imagefield.scaleX = this.zoom * (this.cameraFocus/100) / 10;
  390. this.imagefield.scaleY = this.zoom * (this.cameraFocus/100) / 10;
  391. this.centerImageField();
  392. }
  393. private function roundToN(n:Number,m:Number):Number{
  394. return Math.round((n*Math.pow(10,m)))/Math.pow(10,m)
  395. }
  396. private function validatePan(pan:Number):Number {
  397. return pan - this.roundToN((pan / 360),0)* 360;
  398. }
  399. public function getSpaceById(spaces:XML, id:String):XML{
  400. for each(var space:XML in spaces.elements()) {
  401. if (space.@id == id){
  402. return space;
  403. }
  404. }
  405. return null;
  406. }
  407. }
  408. }