Rex Rhino Posted November 25, 2013 Share Posted November 25, 2013 Hey all, Right now, Ludei Cocoonjs doesn't load and parse XML files... Which means that we can't load bitmap font data. I am wondering if anyone else has figured out a workaround to this issue? Link to comment Share on other sites More sharing options...
benny! Posted November 25, 2013 Share Posted November 25, 2013 Yup, I did a hacky workaround. I replaced the BitmapFont XML Loader logic with JSON Loader logic. In order to make this work with the xml code exported from AngelCodes Font Generator I converted the XML bitmap font data into a json array using a tool like this http://www.freeformatter.com/xml-to-json-converter.html (if I remember it correctly - I used the default settings of the tool). The hacky workaround code for the BitmapFont Loader looks like this:/** * Loads the XML font data * * @method load */PIXI.BitmapFontLoader.prototype.load = function(){ this.ajaxRequest = new AjaxRequest(); var scope = this; this.ajaxRequest.onreadystatechange = function () { scope.onJSONLoaded(); }; this.ajaxRequest.open("GET", this.url, true); if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType("application/json"); this.ajaxRequest.send(null);};/** * Invoked when XML file is loaded, parses the data * * Modified method to use json instead for CocoonJS * with json conversion seen here: * http://www.freeformatter.com/xml-to-json-converter.htm * * @method onXMLLoaded * @private */PIXI.BitmapFontLoader.prototype.onJSONLoaded = function(){ if (this.ajaxRequest.readyState == 4) { if (this.ajaxRequest.status == 200 || window.location.href.indexOf("http") == -1) { this.json = JSON.parse(this.ajaxRequest.responseText); var textureUrl = "assets/" + this.json.pages[0]['@file']; var image = new PIXI.ImageLoader(textureUrl, this.crossorigin); this.texture = image.texture.baseTexture; var data = {}; data.font = this.json.info[ '@face' ]; data.size = parseInt( this.json.info[ '@size' ], 10 ); data.lineHeight = parseInt( this.json.common[ '@lineHeight' ], 10 ); data.chars = {}; var letters = this.json.chars.char; for (var i = 0; i < letters.length; i++) { var charCode = parseInt(letters[i]["@id"], 10); var textureRect = { x: parseInt(letters[i]["@x"], 10), y: parseInt(letters[i]["@y"], 10), width: parseInt(letters[i]["@width"], 10), height: parseInt(letters[i]["@height"], 10) }; PIXI.TextureCache[charCode] = new PIXI.Texture(this.texture, textureRect); data.chars[charCode] = { xOffset: parseInt(letters[i]["@xoffset"], 10), yOffset: parseInt(letters[i]["@yoffset"], 10), xAdvance: parseInt(letters[i]["@xadvance"], 10), kerning: {}, texture:new PIXI.Texture(this.texture, textureRect) }; } if ( this.json.kernings && this.json.kernings.kerning ) { var kernings = this.json.kernings.kerning; for (i = 0; i < kernings.length; i++) { var first = parseInt(kernings[i]["@first"], 10); var second = parseInt(kernings[i]["@second"], 10); var amount = parseInt(kernings[i]["@amount"], 10); data.chars[second].kerning[first] = amount; } } PIXI.BitmapText.fonts[data.font] = data; var scope = this; image.addEventListener("loaded", function() { scope.onLoaded(); }); image.load(); } else { this.onError(); } } };/** * Invoked when all files are loaded (xml/fnt and texture) * * @method onLoaded * @private */PIXI.BitmapFontLoader.prototype.onLoaded = function(){ this.dispatchEvent({type: "loaded", content: this});};Hope this helps you. At least this way worked for me with my game Yummy Plate . I tried out different approaches (like using an javascript XML parser) - but nothing really seems to work. This is really hacky - but it works. So, basically what you need to do is: 1.) Replace PIXI's original BitmapFontLoader code with code above2.) Convert XML bitmap font data into json structure with online tool3.) Important - keep the suffix as .xml in order to trigger the correct loader code4.) Cross your fingers that nothing explodes ;-) Let me know if you need any more info. Best,benny! Link to comment Share on other sites More sharing options...
Rex Rhino Posted November 25, 2013 Author Share Posted November 25, 2013 Thanks for your help Benny! I am using the dev version of Phaser, which has a different version of PIXI, so it doesn't map perfectly to your functions, but hopefully I can figure it out. Link to comment Share on other sites More sharing options...
benny! Posted November 25, 2013 Share Posted November 25, 2013 Ah, sorry - forget that you are using Phaser. My game was PIXI only. I used a dev version from github (round about V1.3). Hope you can sort this out. Best of luck. Link to comment Share on other sites More sharing options...
rich Posted November 26, 2013 Share Posted November 26, 2013 I'm genuinely surprised why Cocoon can't parse XML files. There must be plenty of xml parsers ready available for Objective C I would have thought. Oh well benny! 1 Link to comment Share on other sites More sharing options...
sergil Posted November 26, 2013 Share Posted November 26, 2013 I have a post with the same problems: http://www.html5gamedevs.com/topic/2141-cocoonjs-launcher/ Is there any way to use BitmapFonts with json without hacking? Link to comment Share on other sites More sharing options...
benny! Posted November 26, 2013 Share Posted November 26, 2013 @sergil:Cleanest solution would be to add somekind of polyfill for XML parsing and not to hack around in the core libs (like Phaser, PIXI). Unfortunately, it did not worked in my tests. Mostly it seems that the js-xml parsers couldnt handle large xml files. But if you find a clean solution - please let me know. As I said above - this way is really hacky and definately not something I would recommend to do in general. Link to comment Share on other sites More sharing options...
GregP Posted November 26, 2013 Share Posted November 26, 2013 Hi guys,I was playing with this topic last weekend and came out with small hack.Basically, the idea is to recognize the environment using navigator.isCocoonJS and depending on that:- override window.DOMParser with own parser implementation- load bitmap font data from JSON instead of XML Ladies and gents, let me introduce to you.. DOMishParser if (navigator.isCocoonJS) { window.DOMParser = DOMishParser;}function DOMishParser() {}DOMishParser.prototype.parseFromString = function (data) { return new DOMishObject(JSON.parse(data));};function DOMishAttributes() {}DOMishAttributes.prototype.getNamedItem = function (name) { return { nodeValue: this[name] || null };};function makeDOMishObject(data) { return new DOMishObject(data);}function DOMishObject(data) { this.attributes = this.convertContent(data); this.length = Object.keys(this.attributes).length;}DOMishObject.prototype.documentElement = document;DOMishObject.prototype.convertContent = function (obj) { var attributes = new DOMishAttributes(), prop; for (prop in obj) { if (obj[prop] !== null && typeof obj[prop] === 'object') { attributes[prop] = Array.isArray(obj[prop]) ? obj[prop].map(makeDOMishObject) : new DOMishObject(obj[prop]); } else { attributes[prop] = obj[prop]; } } return attributes;};DOMishObject.prototype.getElementsByTagName = function(name) { return this.attributes[name] ? Array.isArray(this.attributes[name]) ? this.attributes[name] : [this.attributes[name]] : [];};Looks a bit ugly but does the trick - you can check it on my simple blocks game http://gpabian.pl/blocks/ (still under development).On browsers it loads bitmap font data from XML, on Cocoon uses JSON... Forgot to mention - the JSON file was made of BMFont's XML output using xml2js library and node.js. luckylooke, Rex Rhino and benny! 3 Link to comment Share on other sites More sharing options...
Rex Rhino Posted November 26, 2013 Author Share Posted November 26, 2013 GregP, that is really cool! I am hoping to test this later today! Link to comment Share on other sites More sharing options...
sergil Posted November 27, 2013 Share Posted November 27, 2013 Ludei guys told me that at the moment the DOMParser is not implemented in cocoonjs. This feature is in the backlog but didn't exists for the moment. Right now, the solution is to implement a window.DOMParser from JavaScript like the one posted in this post. It should work without problems. Link to comment Share on other sites More sharing options...
benny! Posted November 27, 2013 Share Posted November 27, 2013 @GregP:This sounds pretty clever. Will try it out. Thanks for sharing! Link to comment Share on other sites More sharing options...
rich Posted November 27, 2013 Share Posted November 27, 2013 Forgive me if I'm wrong, but doesn't Cocoon offer a WebView as well? Doesn't the DOMParser exist in that? Link to comment Share on other sites More sharing options...
benny! Posted November 27, 2013 Share Posted November 27, 2013 Forgive me if I'm wrong, but doesn't Cocoon offer a WebView as well? Doesn't the DOMParser exist in that? They definately offer a WebView, that's true. However, I cannot say how communication works between both environments. But it might be also worthwhile to check out. Link to comment Share on other sites More sharing options...
dTb Posted November 28, 2013 Share Posted November 28, 2013 It's not too difficult, we have a lot of functions to call stuff in the other context, (from webview to canvas and vice-versa) with callbacks where you don't have to care much from which context are coming the data. You cannot transfer functions/prototypes I think, you can transfer just text based info, but that's enough in most of the cases I think. On my side I'm using it to access the photo roll via an <input type="file"> and to send the photo data as a string to the canvas. See the 3 CocoonJs_App files here :https://bitbucket.org/ludei/cocoon_cocoonjsextensions/src Link to comment Share on other sites More sharing options...
sch5 Posted November 30, 2013 Share Posted November 30, 2013 Forgive me if I'm wrong, but doesn't Cocoon offer a WebView as well? Doesn't the DOMParser exist in that? Yes it does, but it will only be available if one is initialized the webview by loading a html file into it. Here is an webview example how can it be done https://cocoonjsservice.ludei.com/cocoonjslaunchersvr/demo-list/ ). Until then, there's not much functionality available at the 'dark side', however a fancy proxy thing can be build up this way that comes handy later -> They definately offer a WebView, that's true. However, I cannot say how communication works between both environments. But it might be also worthwhile to check out. That would be a JSON-ish thing, and it works synchronously as well as asynchronously. I prefer the synchronous way this time.- First, one have to pass the XML document (as a plain string) to the webview environment by using the provided var retObject = CocoonJS.App.forward() method.- Next, at the webview side pick a new DOMParser() and feed it with the XML content, or just create a new xhtml document ( document.implementation.createDocument() ) and inject the received XML document into it by passing it to the innerHTML property. It's up to you which method you prefer, since both ways the XML will be translated immediately and can be traversed to pick the needed childNodes and attributes which both have to be saved into an js object.- Then, this js object have to be JSONified as a string before passed back to the - let's call it - gaming environment there it is received as an decoded object (into the retObject), so no need to parse at the receiver end.By traversing the received object a new object can be build up that will mimic the document's behavior, including the methods that will be essential for Phaser to access the content. Since a user-defined DOMParser() class can also be defined (it wont do any bad, since it is completely missing on the gaming side) in order to provide the needed functionalities for Phaser, therefore the engine can be left completely intact and no need to subclass/hijack/overwrite etc any parts of it (that's what i prefer imo ) - Just think something that GregP shown us a little up here (that example gave me the idea as well, thanks! ) Still a hacky one i admit, but not that bad since it uses the native methods of webview to parse the XML, jsonify the thing etc. (the whole thing takes only a moment for my yet oldie 2.3.7 android vodafone smart ii - and boy this is a veeery slow handy) Anyway, the above solution is the only i found so far to get rid the XML problems in the cocoon js environment. I hope however they will come up with a less ugly way that would be the good solution. Link to comment Share on other sites More sharing options...
Rex Rhino Posted December 8, 2013 Author Share Posted December 8, 2013 GregP: Would you mind including an example font JSON that you are using? I am having trouble with the code, and want to see if I am converting the JSON incorrectly. Link to comment Share on other sites More sharing options...
GregP Posted December 11, 2013 Share Posted December 11, 2013 Hi Rex, here's my sample JSON:http://gpabian.pl/blocks/fonts/Komika.json Cheers Link to comment Share on other sites More sharing options...
sergil Posted December 12, 2013 Share Posted December 12, 2013 It would be nice to let Phaser to be cocoonjs compatible by default... Link to comment Share on other sites More sharing options...
rich Posted December 12, 2013 Share Posted December 12, 2013 It's part of the roadmap. We want to bed down the features (and we're very nearly there) and then will start making it seamless for Cocoon, Firefox OS, etc. Q1 2014 is our target for starting this work. Link to comment Share on other sites More sharing options...
haden Posted December 17, 2013 Share Posted December 17, 2013 Had a hard time using converted xml JSON files to work with Phaser on CocoonJS. Either there is an exception when loading the .json or the bitmapfont text is not visible at all. The solution I'm using includes DOMishParser (thanks GregP) and the following nodejs script I hacked (based on the following blog post):var fs = require('fs'), eyes = require('eyes'), xml2js = require('xml2js');var parser = new xml2js.Parser({ explicitRoot: false, mergeAttrs: true, explicitArray: false });parser.on('end', function(result) { result.char = result.chars.char; delete result.chars; var json = JSON.stringify(result); fs.writeFile(__dirname + "/output.json", json, function(err) { if(err) { console.log(err); } else { console.log("The file was saved!"); } });});fs.readFile(__dirname + '/font.xml', function(err, data) { parser.parseString(data); });Do you know an easier solution to generate working .json files from .xml font descriptors ? Link to comment Share on other sites More sharing options...
sergil Posted January 15, 2014 Share Posted January 15, 2014 It's part of the roadmap. We want to bed down the features (and we're very nearly there) and then will start making it seamless for Cocoon, Firefox OS, etc. Q1 2014 is our target for starting this work. Have you started working in Cocoon full integration for Phaser? Thanks Pert 1 Link to comment Share on other sites More sharing options...
lukaszwojciak Posted February 13, 2014 Share Posted February 13, 2014 This issue is directly related to what pixi.js does under the hood. Run in it 2 days ago and quickly brew a dead-simple xml parser:https://github.com/GoodBoyDigital/pixi.js/pull/565/filesNow Ejecta and CocoonJS haz bitmapfonts plicatibu 1 Link to comment Share on other sites More sharing options...
rich Posted February 13, 2014 Share Posted February 13, 2014 Yeah I saw that patch come in - very nice Hopefully they'll merge it in! Link to comment Share on other sites More sharing options...
rkpuri Posted March 3, 2014 Share Posted March 3, 2014 Hi All, I am new to Phaser. I have build one game using this framework which is working fine on browser. But I now am trying to load on Cocoonjs, the only problem I am facing is showing any text using bitmap font. I have tried the hack of using "DOMishParser" with json which is suggested in this post but I am not able to see the text rendered on the screen.There is no error in console as well. Can someone help me out please, as this is getting very difficult for me now to figure out what could be the issue. Link to comment Share on other sites More sharing options...
Agnostic Posted April 21, 2014 Share Posted April 21, 2014 Hi All, I am new to Phaser. I have build one game using this framework which is working fine on browser. But I now am trying to load on Cocoonjs, the only problem I am facing is showing any text using bitmap font. I have tried the hack of using "DOMishParser" with json which is suggested in this post but I am not able to see the text rendered on the screen.There is no error in console as well. Can someone help me out please, as this is getting very difficult for me now to figure out what could be the issue. I have the same issue, I am loading a json file in CocoonJS for bitmap fonts instead of XML using the DOMishParser too (no errors in console), the other sprites are displayed correctly, I have to add an empty sprite at the end to show the last sprite, all it's working, except Bitmap Fonts =/ Solved, the json file was converted incorrectly... Link to comment Share on other sites More sharing options...
Recommended Posts