automatically reload images when they change on disk

This commit is contained in:
Jeremy Penner 2011-02-01 08:31:41 -08:00
parent 710ea0e879
commit fe0e8713a9
9 changed files with 180 additions and 58 deletions

View file

@ -1,5 +1,7 @@
package
{
import flash.display.BitmapData;
import flash.filesystem.File;
import net.flashpunk.Entity;
import net.flashpunk.Graphic;
import net.flashpunk.graphics.Image;
@ -19,6 +21,14 @@ package
super(sidebar, img.scaledHeight, img);
}
public function OnImgReload(bmp:BitmapData, file:File): void
{
var imgNew:Image = new Image(bmp);
imgNew.scale = sidebar.width / imgNew.width;
imgNew.alpha = img.alpha;
img = imgNew;
graphic = img;
}
override public function Fade(pct:Number):void
{
super.Fade(pct);

View file

@ -9,11 +9,11 @@ package
*/
public class EvNewImg extends Event
{
public var rel: String;
public var urp: String;
public var bmp: BitmapData;
public function EvNewImg(type: String, rel: String, bmp: BitmapData)
public function EvNewImg(type: String, urp: String, bmp: BitmapData)
{
this.rel = rel;
this.urp = urp;
this.bmp = bmp;
super(type);
}

View file

@ -1,6 +1,8 @@
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.filesystem.File;
import flash.geom.Point;
import net.flashpunk.Entity;
import net.flashpunk.Graphic;
@ -15,19 +17,35 @@ package
public class Factory extends EntitySidebarImg
{
private var bmp: BitmapData;
private var relf: String;
public function Factory(sidebar: Sidebar, relf: String, bmp:BitmapData)
private var urpf: String;
private var filewatcher: FileWatcher;
public function Factory(sidebar: Sidebar, urpf: String, bmp:BitmapData)
{
super(sidebar, bmp);
this.bmp = bmp;
this.relf = relf;
this.urpf = urpf;
}
override public function added():void
{
super.added();
var stage: WorldStage = WorldStage(world);
filewatcher = FileWatcher.Get(stage.UabFromUrf(stage.UrfFromUrp(urpf)));
filewatcher.Register(function(bmpNew:BitmapData, file:File):void {
bmp = bmpNew;
OnImgReload(bmpNew, file);
}, this);
}
override public function removed():void
{
super.removed();
filewatcher.Unregister(this);
}
override public function OnClick():void
{
var worldStage: WorldStage = WorldStage(world);
var posMouseReal: Point = worldStage.PointRealFromScreen(new Point(Input.mouseX, Input.mouseY));
var relfBmp: String = worldStage.RelFull(relf);
var tok: Token = new Token(bmp, relfBmp, posMouseReal.x - this.bmp.width / 2, posMouseReal.y - this.bmp.height / 2);
var urffBmp: String = worldStage.UrfFromUrp(urpf);
var tok: Token = new Token(bmp, urffBmp, posMouseReal.x - this.bmp.width / 2, posMouseReal.y - this.bmp.height / 2);
world.add(tok);
worldStage.tokSelected = tok;
}

64
src/FileWatcher.as Normal file
View file

@ -0,0 +1,64 @@
package
{
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.filesystem.File;
/**
* ...
* @author jjp
*/
public class FileWatcher
{
private var file: File;
private var dateModified: Date;
private var size: Number;
private var rgobj_dgOnChange: Array;
private static var mpabsf_filewatcher:Object = { };
public function FileWatcher(file: File)
{
this.file = file;
this.dateModified = file.modificationDate;
this.size = file.size;
this.rgobj_dgOnChange = [];
}
public static function Get(absf: String): FileWatcher
{
var filewatcher:FileWatcher = mpabsf_filewatcher[absf];
if (filewatcher === null)
{
filewatcher = new FileWatcher(new File(absf));
mpabsf_filewatcher[absf] = filewatcher;
}
return filewatcher;
}
public static function CheckAll():void
{
for each(var filewatcher:FileWatcher in mpabsf_filewatcher)
filewatcher.Check();
}
public function Register(dgOnChange: Function, obj:*):void {
rgobj_dgOnChange.push([obj, dgOnChange]);
}
public function Unregister(obj:*):void {
rgobj_dgOnChange = rgobj_dgOnChange.filter(function(obj_dgOnChange:Array, _:*, __:*):Boolean { return (obj_dgOnChange[0] !== obj); } );
if (rgobj_dgOnChange.length == 0)
delete mpabsf_filewatcher[file.nativePath];
}
public function Check():void
{
if (this.dateModified !== file.modificationDate || this.size !== file.size)
{
this.dateModified = file.modificationDate;
this.size = file.size;
Imgdir.LoadBmp(file, function(bmp:BitmapData, fileT:File):void {
for each(var obj_dgOnChange:Array in rgobj_dgOnChange)
obj_dgOnChange[1](bmp, fileT);
}, null);
}
}
}
}

View file

@ -17,21 +17,21 @@ package
[Embed(source = '../assets/folder.png')]
private const bmpFolder:Class;
private var reld: String;
private var urpd: String;
private var text: Text;
public function Folder(sidebar: Sidebar, reld: String)
public function Folder(sidebar: Sidebar, urpd: String)
{
super(sidebar, bmpFolder);
text = new Text(reld, 2, (img.scaledHeight / 2) - 6);
text = new Text(urpd, 2, (img.scaledHeight / 2) - 6);
text.color = 0x4444FF;
addGraphic(text);
this.reld = reld;
this.urpd = urpd;
}
override public function OnClick():void
{
WorldStage(world).Chdir(this.reld);
WorldStage(world).Chdir(this.urpd);
}
override public function Fade(pct:Number):void
{

View file

@ -18,15 +18,15 @@ package
{
public static const LOADED: String = "ImgLoaded";
private var dir: File;
private var mprelf_bmp: Object;
private var rgreld: Object;
private var mpurpf_bmp: Object;
private var rgurpd: Object;
public function Imgdir(url: String)
{
trace("imgdir: " + url);
this.dir = new File(url);
this.dir.addEventListener(FileListEvent.DIRECTORY_LISTING, OnDirUpdate);
this.mprelf_bmp = { };
this.rgreld = { };
this.mpurpf_bmp = { };
this.rgurpd = { };
}
public function Update() : void
@ -38,13 +38,13 @@ package
{
for each (var file: File in ev.files)
{
var rel: String = file.name;
if (file.isDirectory && !rgreld[rel])
var urp: String = file.name;
if (file.isDirectory && !rgurpd[urp])
{
rgreld[rel] = true;
dispatchEvent(new EvNewImg(LOADED, rel, null));
rgurpd[urp] = true;
dispatchEvent(new EvNewImg(LOADED, urp, null));
}
else if (!file.isDirectory && /\.(png|gif|jpg|jpeg)$/i.test(rel) && !mprelf_bmp[rel])
else if (!file.isDirectory && /\.(png|gif|jpg|jpeg)$/i.test(urp) && !mpurpf_bmp[urp])
LoadBmp(file, OnBmpLoaded);
}
}
@ -67,7 +67,7 @@ package
}
private function OnBmpLoaded(bmp: BitmapData, file: File) : void
{
mprelf_bmp[file.name] = bmp;
mpurpf_bmp[file.name] = bmp;
this.dispatchEvent(new EvNewImg(LOADED, file.name, bmp));
}
}

View file

@ -1,10 +1,13 @@
package
{
import flash.display.BitmapData;
import flash.filesystem.File;
import flash.geom.Point;
import flash.geom.Rectangle;
import net.flashpunk.Entity;
import net.flashpunk.graphics.Image;
import net.flashpunk.Tween;
import net.flashpunk.tweens.misc.Alarm;
import net.flashpunk.utils.Draw;
import net.flashpunk.utils.Input;
import net.flashpunk.utils.Key;
@ -17,16 +20,18 @@ package
{
private var drag: Drag;
public var posReal: Point;
private var relf: String;
private var urff: String;
private var xml: XML;
public function Token(source:BitmapData, relf: String, x: int, y: int, xml:XML = null)
private var filewatcher: FileWatcher;
public function Token(source:BitmapData, urff: String, x: int, y: int, xml:XML = null)
{
this.posReal = new Point(x, y);
super(x, y, new Image(source));
this.type = "Token";
this.layer = WorldStage.LAYER_TOKENS;
this.drag = null;
this.relf = relf;
this.urff = urff;
if (xml === null)
this.xml = XML("<token/>");
else
@ -36,6 +41,13 @@ package
{
return WorldStage(this.world).tokSelected === this;
}
override public function added():void
{
super.added();
FixupZoom();
filewatcher = FileWatcher.Get(WorldStage(world).UabFromUrf(urff));
filewatcher.Register(OnFileChanged, this);
}
override public function removed():void
{
super.removed();
@ -44,11 +56,11 @@ package
drag.Done();
drag = null;
}
filewatcher.Unregister(this);
}
override public function added():void
public function OnFileChanged(bmp: BitmapData, file: File): void
{
super.added();
FixupZoom();
graphic = new Image(bmp);
}
private function FixupZoom(): Number
{
@ -99,9 +111,9 @@ package
{
drag = Drag.Claim();
if (drag !== null)
trace("drag claimed for " + relf);
trace("drag claimed for " + urff);
else
trace("drag failed for " + relf);
trace("drag failed for " + urff);
}
if (drag !== null)
@ -129,7 +141,7 @@ package
var xml: XML = this.xml.copy();
xml.@x = int(posReal.x);
xml.@y = int(posReal.y);
xml.@path = relf;
xml.@path = urff;
return xml;
}
}

View file

@ -33,9 +33,8 @@ package
private var imgdir: Imgdir;
private var drag: Drag;
private var absd: String;
private var relf: String;
private var rgreld: Array;
private var urff: String;
private var rgurpd: Array;
private var alarmImgdir: Tween;
private var rgsidebar: Vector.<Sidebar>;
@ -46,14 +45,15 @@ package
public var tokSelected: Token;
public var zoom: Number;
public var pointView: Point;
public var uabd: String;
public function WorldStage(absf: String)
public function WorldStage(uabf: String)
{
super();
var match:* = /(.*\/)([^\/]*)$/.exec(absf);
this.absd = match[1];
this.relf = match[2];
this.rgreld = [];
var match:* = /(.*\/)([^\/]*)$/.exec(uabf);
this.uabd = match[1];
this.urff = match[2];
this.rgurpd = [];
this.rgsidebar = new Vector.<Sidebar>();
var sidebarSave: Sidebar = AddSidebar(new Sidebar(FP.width - 32, FP.width, 0, 0, 32, 32, LAYER_SAVE, false, false));
@ -69,6 +69,7 @@ package
Chdir(null);
ToggleUI();
Load();
addTween(new Alarm(3, FileWatcher.CheckAll, Tween.LOOPING), true);
}
public function KillToken(tok: Token): void
@ -90,18 +91,23 @@ package
{
var entity: Entity;
if (ev.bmp === null)
entity = new Folder(SidebarFind(LAYER_SIDEBAR), ev.rel);
entity = new Folder(SidebarFind(LAYER_SIDEBAR), ev.urp);
else
entity = new Factory(SidebarFind(LAYER_SIDEBAR), ev.rel, ev.bmp);
entity = new Factory(SidebarFind(LAYER_SIDEBAR), ev.urp, ev.bmp);
}
public function RelFull(relf:String = null): String
public function UabFromUrf(urf:String): String
{
var rel:String = rgreld.join(File.separator);
if (relf !== null)
rel = rel + File.separator + relf;
return rel;
return uabd + urf;
}
public function Chdir(reld: String): void
public function UrfFromUrp(urp:String): String
{
return Urfd() + urp;
}
public function Urfd(): String
{
return rgurpd.join("/") + "/";
}
public function Chdir(urpd: String): void
{
if (alarmImgdir !== null)
{
@ -115,19 +121,19 @@ package
entity.active = false;
}
}
if (reld === "..")
rgreld = rgreld.slice(0, rgreld.length - 1);
else if (reld !== null)
rgreld.push(reld);
if (urpd === "..")
rgurpd = rgurpd.slice(0, rgurpd.length - 1);
else if (urpd !== null)
rgurpd.push(urpd);
imgdir = new Imgdir(absd + RelFull());
imgdir = new Imgdir(UabFromUrf(Urfd()));
imgdir.addEventListener(Imgdir.LOADED, OnNewImg);
imgdir.Update();
alarmImgdir = this.addTween(new Alarm(3, imgdir.Update, Tween.LOOPING), true);
AddSidebar(new Sidebar(0, -32, 0, 0, 32, FP.height, LAYER_SIDEBAR, reld !== null /*fStartShown*/, true));
AddSidebar(new Sidebar(0, -32, 0, 0, 32, FP.height, LAYER_SIDEBAR, urpd !== null /*fStartShown*/, true));
if (rgreld.length > 0)
if (rgurpd.length > 0)
OnNewImg(new EvNewImg(Imgdir.LOADED, "..", null));
}
private function SidebarFind(layer: int):Sidebar
@ -242,14 +248,14 @@ package
public function Save(): void
{
var stream: FileStream = new FileStream();
stream.open(new File(absd + File.separator + relf), FileMode.WRITE);
stream.open(new File(UabFromUrf(urff)), FileMode.WRITE);
stream.writeUTFBytes(GenXML().toXMLString());
stream.close();
ShowMsg("Saved.");
}
public function Load(): void
{
var file: File = new File(absd + File.separator + relf);
var file: File = new File(UabFromUrf(urff));
if (file.exists)
{
var stream: FileStream = new FileStream();
@ -268,7 +274,7 @@ package
private function LoadToken(xml: XML, itoken: int, rgtoken:Object): void
{
trace("loading " + xml.@path);
Imgdir.LoadBmp(new File(absd + File.separator + xml.@path),
Imgdir.LoadBmp(new File(UabFromUrf(xml.@path)),
function(bmp: BitmapData, file: File):void {
trace("loadtoken: " + xml.@path);
var token: Token = new Token(bmp, xml.@path.toString(), int(xml.@x), int(xml.@y), xml);

12
todo.txt Normal file
View file

@ -0,0 +1,12 @@
- fix scrollwheel sensitivity
- zoom to 100% (magnifying glass icon?)
- show 0,0, maybe some other griddy options
- finalize "library" notion
- text objects
- tilemap
- layers
DONE:
- auto image reloading