Skip to content
Permalink
Browse files

Merge pull request #6 from FuzzyWuzzie/master

Web Support ( #5 )
  • Loading branch information
Zielak committed Oct 23, 2015
2 parents a6db89b + 2ff2ed1 commit ab5fdc8f4f69cbfd07a2f995d085bb4c9403ab66
Showing with 301 additions and 9 deletions.
  1. +22 −0 custom_index.html
  2. +2 −0 jslibs/FileSaver.min.js
  3. +57 −0 jslibs/FireEvent.js
  4. +3 −0 jslibs/pako.min.js
  5. +16 −3 project.flow
  6. +36 −6 src/Main.hx
  7. +78 −0 src/js/BuildPNG.hx
  8. +87 −0 src/js/FileOpener.hx
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">

<head>

<link rel="icon" href="favicon.png"/>
<meta charset="utf-8">

<style> #window1 { margin: 0; padding: 0; } </style>

{{#each project.app.web.libs~}}
<script type="text/javascript" src="{{this}}"></script>
{{/each}}

</head>

<body style="padding: 0; margin: 0; background-color: #111111;">
<input type="file" id="filePicker" accept="image/*" hidden/>
<script type="text/javascript" src="./{{project.app.name}}{{#if project.app.web.min}}.min{{/if}}.js"></script>
</body>

</html>

Some generated files are not rendered by default. Learn more.

@@ -0,0 +1,57 @@
/**
* Fire an event handler to the specified node. Event handlers can detect that the event was fired programatically
* by testing for a 'synthetic=true' property on the event object
* @param {HTMLNode} node The node to fire the event handler on.
* @param {String} eventName The name of the event without the "on" (e.g., "focus")
*/
function fireEvent(node, eventName) {
// Make sure we use the ownerDocument from the provided node to avoid cross-window problems
var doc;
if (node.ownerDocument) {
doc = node.ownerDocument;
} else if (node.nodeType == 9){
// the node may be the document itself, nodeType 9 = DOCUMENT_NODE
doc = node;
} else {
throw new Error("Invalid node passed to fireEvent: " + node.id);
}

if (node.dispatchEvent) {
// Gecko-style approach (now the standard) takes more work
var eventClass = "";

// Different events have different event classes.
// If this switch statement can't map an eventName to an eventClass,
// the event firing is going to fail.
switch (eventName) {
case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead.
case "mousedown":
case "mouseup":
eventClass = "MouseEvents";
break;

case "focus":
case "change":
case "blur":
case "select":
eventClass = "HTMLEvents";
break;

default:
throw "fireEvent: Couldn't find an event class for event '" + eventName + "'.";
break;
}
var event = doc.createEvent(eventClass);

var bubbles = eventName == "change" ? false : true;
event.initEvent(eventName, bubbles, true); // All events created as bubbling and cancelable.

event.synthetic = true; // allow detection of synthetic events
node.dispatchEvent(event, true);
} else if (node.fireEvent) {
// IE-old school style
var event = doc.createEventObject();
event.synthetic = true; // allow detection of synthetic events
node.fireEvent("on" + eventName, event);
}
};

Large diffs are not rendered by default.

@@ -13,24 +13,37 @@

project : {
name : 'AutoTerrainGen',
version : '0.1.1',
version : '0.1.2',
author : 'Darek Greenly',

app : {
name : 'AutoTerrainGen',
package : 'com.darekgreenly.AutoTerrainGen'
package : 'com.darekgreenly.AutoTerrainGen',
web : {
libs : {
FileSaver: 'FileSaver.min.js',
pako: 'pako.min.js',
FireEvent: 'FireEvent.js'
}
}
},

build : {
dependencies : {
luxe : '*',
mint: '*',
format: '*',
FileSaver: '*',
pako: '*'
}
},

files : {
assets : 'input/'
assets : 'input/',
FileSaver : 'jslibs/FileSaver.min.js => FileSaver.min.js',
pako: 'jslibs/pako.min.js => pako.min.js',
FireEvent: 'jslibs/FireEvent.js => FireEvent.js',
index: { path:'custom_index.html => index.html', template:'project', not_listed:true }
}

}
@@ -60,6 +60,10 @@ class Main extends luxe.Game {
var export_bitmap_button:mint.Button;
var export_tsx_button:mint.Button;

#if web
var fileOpener:js.FileOpener;
#end


override public function config(config:luxe.AppConfig) {

@@ -82,6 +86,7 @@ class Main extends luxe.Game {
init_events();

#if web
fileOpener = new js.FileOpener();
load_tileset('/input/dirt16.gif');
load_tileset('/input/template16.gif');
load_tileset('/input/grass16.gif');
@@ -353,19 +358,17 @@ class Main extends luxe.Game {
closable: false,
});

#if desktop
path_input = new mint.TextEdit({
parent: window1,
#if desktop
text: 'input/',
#else
text: '/input/',
#end
text_size: 12,
name: 'path',
options: { view: { color:new Color().rgb(0x19191c) } },
x: 4, y: 35, w: 340, h: 28,
});
layout.margin(path_input, right, fixed, 58);
#end



@@ -374,11 +377,28 @@ class Main extends luxe.Game {
name: 'load',
text: 'LOAD',
options: { view: { color:new Color().rgb(0x008800) } },
#if desktop
x: 345, y: 35, w: 54, h: 28,
#elseif web
x: 4, y: 35, w: 340, h: 28,
#end
});
layout.anchor(load_button, right, right);
load_button.onmouseup.listen(function(e,_){
#if desktop
load_tileset( path_input.text );
#elseif web
fileOpener.open(function(e:Texture) {
// code taken from load_tileset
// TODO: abstract it out to keep things DRY
var ts:TileSet = new TileSet(e);
tilesets_list.add_item( create_tileset_li(ts) );

tilesets.push(ts);

generator.update_tilesets(tilesets);
});
#end
});


@@ -725,9 +745,11 @@ class Main extends luxe.Game {

function prepare_export(){

#if !web
if(!sys.FileSystem.exists(sys.FileSystem.absolutePath('output/'))){
sys.FileSystem.createDirectory(sys.FileSystem.absolutePath('output/'));
}
#end

}

@@ -736,12 +758,16 @@ class Main extends luxe.Game {

prepare_export();

var data = format.png.Tools.build32BGRA( generator.w, generator.h, generator.output_pixels.toBytes() );

#if desktop
var data = format.png.Tools.build32BGRA( generator.w, generator.h, generator.output_pixels.toBytes() );
var out = sys.io.File.write( sys.FileSystem.absolutePath('output/output.png'), true);
new format.png.Writer(out).write(data);
add_log('File saved in output/output.png');
#elseif web
var data:js.html.Uint8Array = js.BuildPNG.build(generator.w, generator.h, generator.output_pixels.toBytes());
var blob:js.html.Blob = new js.html.Blob([data], {type: 'image/png'});
js.html.FileSaver.saveAs(blob, "output.png");
add_log("File saved as output.png");
#end

}
@@ -754,6 +780,10 @@ class Main extends luxe.Game {
var out = sys.io.File.write( sys.FileSystem.absolutePath('output/output.tsx'), false);
sys.io.File.saveContent("output/output.tsx", generator.tsx.toString());
add_log('File saved in output/output.tsx');
#elseif web
var blob:js.html.Blob = new js.html.Blob([generator.tsx.toString()], {type: 'text/xml;charset=utf8'});
js.html.FileSaver.saveAs(blob, "output.tsx");
add_log('File saved as output.tsx');
#end

}
@@ -0,0 +1,78 @@
package js;

#if web

import haxe.io.Bytes;
import haxe.io.BytesData;
import haxe.io.BytesOutput;
import js.html.Uint8Array;
import js.pako.Pako;

class BuildPNG {
private static var o:BytesOutput;

// shamelessly stolen and adapted from https://github.com/HaxeFoundation/format/tree/master/format/png
public static function build(width:Int, height:Int, data:Bytes):Uint8Array {
// create a stream of bytes
o = new BytesOutput();
o.bigEndian = true;

// add the PNG front matter
for(b in [137,80,78,71,13,10,26,10])
o.writeByte(b);

// add the header
var b = new BytesOutput();
b.bigEndian = true;
b.writeInt32(width);
b.writeInt32(height);
b.writeByte(8);
b.writeByte(6);
b.writeByte(0);
b.writeByte(0);
b.writeByte(0);
writeChunk("IHDR", b.getBytes());

// format the data
var rgba = Bytes.alloc(width * height * 4 + height);
var w = 0, r = 0;
for(y in 0...height) {
rgba.set(w++, 0); // no filter for this scanline
for(x in 0...width) {
rgba.set(w++, data.get(r + 2)); // r
rgba.set(w++, data.get(r + 1)); // g
rgba.set(w++, data.get(r)); // b
rgba.set(w++, data.get(r + 3)); // a
r += 4;
}
}
// deflate the data
var bytesData:BytesData = rgba.getData();
var arrForm:Uint8Array = new Uint8Array(bytesData);
var deflated:Uint8Array = Pako.deflate(arrForm);
var d = Bytes.alloc(deflated.length);
for(i in 0...deflated.length) {
d.set(i, deflated[i]);
}
writeChunk("IDAT", d);

// write the end
writeChunk("IEND", Bytes.alloc(0));

// return the array of bytes!
return new Uint8Array(o.getBytes().getData());
}

private static function writeChunk(id:String, data:Bytes) {
o.writeInt32(data.length);
o.writeString(id);
o.write(data);
var crc = new haxe.crypto.Crc32();
for(i in 0...4)
crc.byte(id.charCodeAt(i));
crc.update(data, 0, data.length);
o.writeInt32(crc.get());
}
}

#end

0 comments on commit ab5fdc8

Please sign in to comment.
You can’t perform that action at this time.