function ActivationView(key) { return UMG(SizeBox, { WidthOverride: 400, HeightOverride: 100 }, UMG(Border,{BrushColor:{A:0.4}}, UMG(compile(Activations), { $link: elem => { bindings[key] = data => elem.data = data } }) ) ) }
return async function() { let bye = make_widget( {}, UMG(SizeBox,{WidthOverride:200}, UMG.div({}, UMG.text({HorizontalAlignment:'EHTA_Center'},what), UMG(Button,{},"Click me") ) ) ) await delay(1000) bye() }
function detail() { let alive = true, elem let bye = make_widget({ Pivot:{Y:0}, Location:{Z:-100}, DrawSize:{X:300,Y:300} }, UMG.div({}, UMG.text({ Font:font, $link:_elem => elem = _elem },"test!"), UMG(PropertyEditor,{$link:elem => elem.SetObject(controller.GetPathFollowingComponent())}) ) ) function loop() { if (!alive || !character.IsValid()) return if (elem) { let loc = character.GetActorLocation() elem.SetText(`${loc.X.toFixed(2)}, ${loc.Y.toFixed(2)}, ${loc.Z.toFixed(2)}`) } process.nextTick(loop) } loop() return function () { alive = false bye() } }
function test() { var design = UMG(Button,{id:'button'}, UMG.text({},'Reset') ) var widget = instantiate(design) vbox.AddChild(widget) return widget }
function dt_dd(x,y) { return UMG(Border,{ BrushColor:{A:0.2}, Padding:{Top:8,Left:16,Bottom:8,Right:16}, Slot:{Padding:{Top:2,Bottom:2}}}, UMG.span({Slot:{Size:{SizeRule:'Fill'}}}, UMG.text({Slot:{Size:{Value:0.2}}},x), y ) ) }
static createUmgElement(element, instantiator) { let declaration = UMG(Button, { OnClicked: _ => { if (element.props.onClick) element.props.onClick(); } }); let elem = instantiator(declaration); return elem; }
function makeWindow(key,opts) { const _ = require('lodash') const UMG = require('UMG') const I = require('instantiator') if (!global[key]) { let window let container let widget = I( UMG(JavascriptWindow,_.extend( { $link:elem => window = elem },opts), UMG(SizeBox,{$link:elem => container = elem}) ) ) widget.TakeWidget().AddWindow() let prev function add(child) { if (prev) { container.remove_child(prev) } prev = container.add_child(child(finish)) process.nextTick(_ => window.BringToFront()) } global[key] = add function finish() { if (window) { window.RequestDestroyWindow() window = null global[key] = null } } } return global[key] }
contextMenu : () => I( UMG(JavascriptMultiBox,{ CommandList : commandList, OnHook : __ => { JavascriptMenuLibrary.CreateMenuBuilder(commandList,true,builder => { opts.Commands.forEach((v,k) => { builder.AddToolBarButton(commands.CommandInfos[k]) }) JavascriptMultiBox.Bind(builder) }) } }) )
function dialog(resolve) { let design = UMG.div({}, UMG(Border,{ BrushColor:{A:0.4}, Padding:{Left:20,Top:10,Right:20,Bottom:20} }, UMG.span({}, UMG.text({},"Demo scenes"), scenes.map(x => UMG(Button,{OnClicked:_ => resolve(x)},UMG.text({Font:font},x))) ) ) ) return design }
async function demo(defer) { let alive = true let elem = viewport_widget() defer(_ => { alive = false elem.destroy() }) let inner = elem.add_child( UMG(Border,{ BrushColor:{A:0.4}, Padding:{Left:100,Top:100,Right:100} }) ) await deeplearning_demo(inner, _ => alive) }
function packageList(opts) { return UMG.div( { Slot:opts.Slot }, UMG(JavascriptListView,{ ItemHeight:20, OnContextMenuOpening: packages.contextMenu, OnGenerateRowEvent:(item,column) => { const isName = column == 'Name' return I( UMG.text( { Font:font, ToolTipText: isName && item ? item.package.details : '' }, isName ? (item ? item.package.name : 'Package name') : (item ? item.installed ? "Installed" : "" : 'Status') ) ) }, Columns:[ { Id: 'Name', Width: 0.7 }, { Id: 'Status', Width: 0.3 } ], $link:elem => { elem.JavascriptContext = Context elem.alive = true elem.proxy = { OnDoubleClick : item => item.actions.install(), OnSelectionChanged: item => packages.setCurrent(item) } function refresh() { throbber.SetVisibility('Visible') registry.fetch().then(packages => { if (!elem.alive) throw new Error("interrupted") // root.Items = ... is necessary to keep these items not to be collected by GC // because JavascriptObject has a JS object attached. root.Items = elem.Items = packages.map(x => packageToObject(x,E)) throbber.SetVisibility('Hidden') elem.RequestListRefresh() }) } process.nextTick(refresh) elem.refresh = refresh E.on('refreshPackages',elem.refresh) }, $unlink:elem => { elem.alive = false E.removeListener('refreshPackages',elem.refresh) } }), UMG(Throbber,{ 'Slot.HorizontalAlignment':'HAlign_Center', $link:elem => throbber = elem }) ) }
function contextList() { return UMG(JavascriptListView,{ ItemHeight:20, Columns:[ { Id: 'Name', Width: 0.7 }, { Id: 'Status', Width: 0.3 } ], OnContextMenuOpening: contexts.contextMenu, OnGenerateRowEvent:(item,column) => I( UMG.text({Font:font},column == 'Name' ? item ? item.target : 'Context' : item ? item.status : 'Status' ) ), $link:elem => { elem.JavascriptContext = Context elem.alive = true elem.proxy = { OnSelectionChanged: item => contexts.setCurrent(item) } let old function refresh() { function fetch() { let out { out = JavascriptLibrary.GetObjectsOfClass(JavascriptContext, [], false, 0x10).Results out = out.map(x => [x.GetDisplayName(),x.IsDebugContext() ? 'Debug' : '']) let cur = _.flatten(out).join(',') if (cur != old) { old = cur out = out.map(x => { let y = new JavascriptObject() let [a,b] = x y.target = x[0] y.status = x[1] function find() { let out = JavascriptLibrary.GetObjectsOfClass(JavascriptContext, [], false, 0x10).Results let x = _.filter(out,x => x.GetDisplayName() == y.target) if (x.length) { return Promise.resolve(x[0]) } else { return Promise.reject(new Error('not found')) } } function refreshContexts() { E.refreshContexts() return Promise.resolve() } y.actions = { debug : _ => find().then(obj=>obj.SetAsDebugContext()).then(gc).then(refreshContexts), undebug : _ => find().then(obj=>obj.ResetAsDebugContext()).then(gc).then(refreshContexts), } if (y.status == 'Debug') { delete y.actions.debug } else { delete y.actions.undebug } return y }) } else { out = null } } gc() return out } let cur = fetch() if (cur) { root.Contexts = elem.Items = cur elem.RequestListRefresh() } } function tick() { if (!elem.alive) return refresh() setTimeout(tick,1000) } elem.refresh = refresh tick() E.on('refreshContexts',elem.refresh) }, $unlink:elem => { elem.alive = false E.removeListener('refreshContexts',elem.refresh) } }) }
})(finish => { let E = new EventEmitter() E.refreshPackages = _ => E.emit('refreshPackages') E.refreshContexts = _ => E.emit('refreshContexts') let root = {} function contextList() { return UMG(JavascriptListView,{ ItemHeight:20, Columns:[ { Id: 'Name', Width: 0.7 }, { Id: 'Status', Width: 0.3 } ], OnContextMenuOpening: contexts.contextMenu, OnGenerateRowEvent:(item,column) => I( UMG.text({Font:font},column == 'Name' ? item ? item.target : 'Context' : item ? item.status : 'Status' ) ), $link:elem => { elem.JavascriptContext = Context elem.alive = true elem.proxy = { OnSelectionChanged: item => contexts.setCurrent(item) } let old function refresh() { function fetch() { let out { out = JavascriptLibrary.GetObjectsOfClass(JavascriptContext, [], false, 0x10).Results out = out.map(x => [x.GetDisplayName(),x.IsDebugContext() ? 'Debug' : '']) let cur = _.flatten(out).join(',') if (cur != old) { old = cur out = out.map(x => { let y = new JavascriptObject() let [a,b] = x y.target = x[0] y.status = x[1] function find() { let out = JavascriptLibrary.GetObjectsOfClass(JavascriptContext, [], false, 0x10).Results let x = _.filter(out,x => x.GetDisplayName() == y.target) if (x.length) { return Promise.resolve(x[0]) } else { return Promise.reject(new Error('not found')) } } function refreshContexts() { E.refreshContexts() return Promise.resolve() } y.actions = { debug : _ => find().then(obj=>obj.SetAsDebugContext()).then(gc).then(refreshContexts), undebug : _ => find().then(obj=>obj.ResetAsDebugContext()).then(gc).then(refreshContexts), } if (y.status == 'Debug') { delete y.actions.debug } else { delete y.actions.undebug } return y }) } else { out = null } } gc() return out } let cur = fetch() if (cur) { root.Contexts = elem.Items = cur elem.RequestListRefresh() } } function tick() { if (!elem.alive) return refresh() setTimeout(tick,1000) } elem.refresh = refresh tick() E.on('refreshContexts',elem.refresh) }, $unlink:elem => { elem.alive = false E.removeListener('refreshContexts',elem.refresh) } }) } function packageList(opts) { return UMG.div( { Slot:opts.Slot }, UMG(JavascriptListView,{ ItemHeight:20, OnContextMenuOpening: packages.contextMenu, OnGenerateRowEvent:(item,column) => { const isName = column == 'Name' return I( UMG.text( { Font:font, ToolTipText: isName && item ? item.package.details : '' }, isName ? (item ? item.package.name : 'Package name') : (item ? item.installed ? "Installed" : "" : 'Status') ) ) }, Columns:[ { Id: 'Name', Width: 0.7 }, { Id: 'Status', Width: 0.3 } ], $link:elem => { elem.JavascriptContext = Context elem.alive = true elem.proxy = { OnDoubleClick : item => item.actions.install(), OnSelectionChanged: item => packages.setCurrent(item) } function refresh() { throbber.SetVisibility('Visible') registry.fetch().then(packages => { if (!elem.alive) throw new Error("interrupted") // root.Items = ... is necessary to keep these items not to be collected by GC // because JavascriptObject has a JS object attached. root.Items = elem.Items = packages.map(x => packageToObject(x,E)) throbber.SetVisibility('Hidden') elem.RequestListRefresh() }) } process.nextTick(refresh) elem.refresh = refresh E.on('refreshPackages',elem.refresh) }, $unlink:elem => { elem.alive = false E.removeListener('refreshPackages',elem.refresh) } }), UMG(Throbber,{ 'Slot.HorizontalAlignment':'HAlign_Center', $link:elem => throbber = elem }) ) } return UMG(SizeBox,{WidthOverride:400}, UMG.div({Size:{Rule:'Fill'}}, UMG.span({}, UMG.text({},"Unreal.js"), UMG.text({ Font:font, 'Slot.Size.Rule':'Fill', 'Slot.HorizontalAlignment':'HAlign_Right', 'Slot.VerticalAlignment':'VAlign_Center', $link:elem => { elem.alive = true fetchGithub().then(json => { const {stargazers_count} = json elem.SetText(`${stargazers_count} stars`) }) }, $unlink:elem => { elem.alive = false contexts.destroy() packages.destroy() } }) ), UMG.text({AutoWrapText:true,Font:font,'Slot.Padding':{Left:20,Top:10}}, `Unreal.js is a plug-in which brings V8-powered Javascript into UnrealEngine4. Copyright (c) 2016 NCSOFT Corporation ${getNumClassesExported()} classes exported` ), UMG(SizeBox,{HeightOverride:20}), UMG(SizeBox,{HeightOverride:100}, contextList() ), UMG(SizeBox,{HeightOverride:200}, packageList({Slot:{ HorizontalAlignment:'HAlign_Fill', VerticalAlignment:'VAlign_Fill'}}) ), UMG(Spacer,{'Slot.Size.Rule' : 'Fill'}), UMG(Button, { WidgetStyle: style.GetButtonStyle("Credits.Button"), OnClicked: _ => { JavascriptProcess.LaunchURL(homepageUrl) } }, UMG.text({Font:font},"Visit project page") ), UMG(Button, { WidgetStyle: style.GetButtonStyle("FlatButton.Dark"), OnClicked: finish }, UMG.text({Font:font},"Close this window!") ) ) ) })
function training_monitor(bindings,classes) { function bind(target,key,fn) { return {$link:elem => { bindings[key] = data => elem["Set"+target](fn(data)) }} } let brushAsset = new SlateBrushAsset class Activations extends JavascriptWidget { OnPaint(_context) { let context = PaintContext.C(_context) const b = 16 const s = b + 4 function p(x,y) { return {X:x*s,Y:y*s} } function clamp(v) { return Math.max(0,Math.min(1,v)) } if (!this.data) return let xs = _.max(this.data.map(l => l.length)) this.data.forEach((layer,y) => { let offset = (xs - layer.length) / 2 layer.forEach((value,x) => context.DrawBox( p(x+offset,y), {X:b,Y:b}, brushAsset, {R:clamp(1-value),G:clamp(value),A:clamp(Math.abs(value)*4)}) ) }) } } class Graph extends JavascriptWidget { ctor() { // exponential moving average of (max) this.ema = 1 } OnPaint(context) { let max = _.max(this.data) this.ema = max = this.ema * 0.95 + max * 0.05 const sx = 1 const sy = 100 function p(x,y) { return {X:x*sx + sx,Y:-y/(max+1e-3)*sy + sy} } let py this.data.forEach((y,x) => { if (py != undefined) { PaintContext.C(context).DrawLine( p(x-1,py), p(x,y), {R:1,G:0.7,B:0,A:1}, true) } py = y }) } } function dt_dd(x,y) { return UMG(Border,{ BrushColor:{A:0.2}, Padding:{Top:8,Left:16,Bottom:8,Right:16}, Slot:{Padding:{Top:2,Bottom:2}}}, UMG.span({Slot:{Size:{SizeRule:'Fill'}}}, UMG.text({Slot:{Size:{Value:0.2}}},x), y ) ) } function ActivationView(key) { return UMG(SizeBox, { WidthOverride: 400, HeightOverride: 100 }, UMG(Border,{BrushColor:{A:0.4}}, UMG(compile(Activations), { $link: elem => { bindings[key] = data => elem.data = data } }) ) ) } let design = UMG.div({}, UMG.text({},"convnetjs"), dt_dd('Iteration', UMG.text(bind('Text', 'iter', iter => iter))), dt_dd('Loss', UMG.text(bind('Text', 'loss', loss => loss.toFixed(3)))), dt_dd('Chart', UMG(SizeBox, { WidthOverride: 400, HeightOverride: 100 }, UMG(Border,{BrushColor:{A:0.4}}, UMG(compile(Graph), { $link: elem => { let data = [] bindings.loss = sample => { data.push(sample) if (data.length > 400) { data.shift() } elem.data = data } } }) ) ) ), _.range(classes).map(index => dt_dd(`Activations ${index}`, ActivationView(`activations_${index}`))) ) return design }
scenes.map(x => UMG(Button,{OnClicked:_ => resolve(x)},UMG.text({Font:font},x)))
module.exports = () => { let alive = true let brushAsset = new SlateBrushAsset() brushAsset.Brush.ResourceObject = TextureRenderTarget2D.Load('/Game/Camera.Camera') brushAsset.Brush.ImageSize = {X:512,Y:512} let whiteBrushAsset = new SlateBrushAsset() let annotations = [] // create a widget class TestWidget2 extends JavascriptWidget { OnPaint(context) { PaintContext.C(context).DrawBox({X:0,Y:0},{X:512,Y:512},brushAsset,{R:1,G:1,B:1,A:1}) } } let TestWidget2_C = require('uclass')()(global,TestWidget2) class TestWidget extends JavascriptWidget { OnPaint(context) { let start = {X:0,Y:0} let r = 512 let t = (new Date() | 0) / 1000 let end = {X:Math.cos(t)*r,Y:Math.sin(t)*r} // PaintContext.C(context).DrawBox({X:0,Y:0},{X:512,Y:512},brushAsset,{R:1,G:1,B:1,A:1}) PaintContext.C(context).DrawLine(start,end,{R:1,A:1},true) annotations.forEach(a => { PaintContext.C(context).DrawBox( {X:a.xmin * 512,Y:a.ymin * 512}, {X:(a.xmax - a.xmin) * 512,Y:(a.ymax - a.ymin) * 512}, whiteBrushAsset, {R:1,G:1,B:1,A:a.prob}) PaintContext.C(context).DrawText( `${a.id} ${a.prob}`, {X:a.xmin * 512,Y:a.ymin * 512}, GEngine.TinyFont, 16, 'Regular', {R:1,G:1,B:1,A:1} ) }) } } let TestWidget_C = require('uclass')()(global,TestWidget) let instantiator = require('instantiator') let UMG = require('UMG') let design = UMG.div({'slot.size.size-rule':'Fill'}, UMG.text({},"YOLO / darknet / Unreal.js / UnrealEngine"), UMG.span({'slot.size.size-rule':'Fill'}, UMG(SizeBox,{ 'slot.size.size-rule':'Fill', WidthOverride:512, HeightOverride:512}, UMG(TestWidget_C,{}) ), UMG(TestWidget2_C,{'slot.size.size-rule':'Fill'}) ) ) let page = instantiator(design) let widget = GWorld.CreateWidget(JavascriptWidget) widget.JavascriptContext = Context widget.SetRootWidget(page) widget.AddToViewport() // if (0) process.nextTick(__ => { let cfgfile = Context.GetDir('Game')+'/ThirdParty/darknet/cfg/yolo-tiny.cfg' let weightfile = Context.GetDir('GameContent')+'/Weights/yolo-tiny.weights' let net = DarknetNetwork.parse_network_cfg(cfgfile) net.load_weights(weightfile) net.set_batch_network(1) $memaccess(net,'self',net_raw => { $memaccess(net,`layer_${net_raw.n-1}`,l => { let cam = _.find(GWorld.GetAllActorsOfClass(CameraActor).OutActors,actor => actor.GetDisplayName() == 'CAPTURE') let target = cam.SceneCaptureComponent2D.TextureTarget const thresh = 0.05 let nms = 0.5 let iou_thresh = 0.5 function tick() { if (!alive) return let image = DarknetImage.load_image(0, target) let sized = image.resize_image(net_raw.w, net_raw.h) let prediction = net.network_predict_image(sized) let boxes = _.range(l.side * l.side * l.n).map(__ => ({})) let probs = _.range(l.side * l.side * l.n).map(__ => _.range(l.classes).map(_ => 0)) $memaccess(prediction,ab => { let data = new Float32Array(ab[0]) convert_yolo_detections(data, l.classes, l.n, l.square, l.side, 1, 1, thresh, probs, boxes, 0) if (nms) do_nms_sort(boxes, probs, l.side*l.side*l.n, l.classes, nms); annotations.length = 0 function dump(id,prob,xmin,ymin,xmax,ymax) { annotations.push({id:id,prob:prob,xmin:xmin,ymin:ymin,xmax:xmax,ymax:ymax}) } print_yolo_detections(dump,boxes, probs, l.side*l.side*l.n, l.classes, 1, 1); }) process.nextTick(tick) } tick() }) }) }) return () => { widget.RemoveFromViewport() alive = false } }