About Monkey 2 › Forums › Monkey 2 Code Library › mojox app featuring left right top and bottom docks
This topic contains 2 replies, has 1 voice, and was last updated by
Simon Armstrong 11 months, 2 weeks ago.
-
AuthorPosts
-
April 9, 2018 at 6:02 am #14301
Before starting a monkey2 scene editor I need to learn mojox. It is the bomb!
I will be refining the following as I go but first parse is a quick copy and paste from a bunch of stuff found in the /modules/mojox/tests folder.
todo – save and restore state
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164' docks mojox template for monkey2#Import "<std>"#Import "<mojo>"#Import "<mojox>"#Import "<mojolabs>"#Import "modular.theme.json"Using std..Using mojo..Using mojox..Struct PrefsField top:int=25Field bottom:int=120Field left:int=250Field right:Int=250EndGlobal prefs:=New PrefsClass ModularWindow Extends WindowField docks:DockingViewField topView:ViewField bottomView:TabViewField leftView:ViewField rightView:TabViewField content:ViewMethod Close()prefs.top=topView.Heightprefs.bottom=bottomView.HeightEndMethod AddDocks()topView=New Button( "Top" )bottomView=CreateTabs()leftView=CreateFileTree()content=CreateTabs()rightView=CreateTabs()docks=New DockingViewdocks.AddView(topView,"top",prefs.top)docks.AddView(bottomView,"bottom",prefs.bottom,True)docks.AddView(leftView,"left",prefs.left,True)docks.AddView(rightView,"right",prefs.right,True)docks.ContentView=contentLocal sceneTree:=CreateTree()AddTab(rightView,"Scene",sceneTree)AddTab(bottomView,"Help",New HtmlView())'New TextView( "ContentView" )ContentView=docksdocks.ContentView.MakeKeyView()EndFunction DirectoryTree( path:String,parent:TreeView.Node )For Local f:=Eachin LoadDir( path )Local p:=path+"/"+fLocal node:=New TreeView.Node( f,parent )If GetFileType( p )=FileType.Directory DirectoryTree( p,node )NextEndMethod AddTab(tabView:TabView, title:String, content:View)tabView.AddTab( title,content )tabView.CurrentIndex=0EndMethod CreateTabs:TabView()Local tabView:=New TabView( TabViewFlags.ClosableTabs|TabViewFlags.DraggableTabs )tabView.RightClicked=Lambda()Local menu:=New Menumenu.AddAction( "Action 1" )menu.AddAction( "Action 2" )menu.AddAction( "Action 3" )menu.Open()EndtabView.CloseClicked=Lambda( index:Int )tabView.RemoveTab( index )If tabView.CurrentView Or Not tabView.NumTabs ReturnIf index=tabView.NumTabs index-=1tabView.CurrentIndex=indexEndReturn tabViewEndMethod CreateTree:TreeView()Local treeView:=New TreeViewtreeView.NodeClicked+=Lambda( node:TreeView.Node )Alert( "Node clicked: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeExpanded+=Lambda( node:TreeView.Node )' Alert( "Node expanded: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeCollapsed+=Lambda( node:TreeView.Node )' Alert( "Node collapsed: node.Text=~q"+node.Text+"~q" )EndtreeView.RootNode.Text="Origin"' DirectoryTree( dir,treeView.RootNode )Return treeViewEndMethod CreateFileTree:TreeView()Local treeView:=New TreeViewtreeView.NodeClicked+=Lambda( node:TreeView.Node )Alert( "Node clicked: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeExpanded+=Lambda( node:TreeView.Node )' Alert( "Node expanded: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeCollapsed+=Lambda( node:TreeView.Node )' Alert( "Node collapsed: node.Text=~q"+node.Text+"~q" )EndtreeView.RootNode.Text=CurrentDir()DirectoryTree( CurrentDir(),treeView.RootNode )Return treeViewEndMethod AddUI()Local list:=New ListViewlist.AddItem( "listview" )list.ItemClicked+=Lambda( item:ListView.Item )Local index:=list.IndexOfItem( item )Print "Item "+index+" clicked"EndContentView=listEndMethod AddTheme()App.Theme.Load( "modular.theme.json" )App.Theme.Scale=New Vec2f( 1.5,1.5 )EndMethod New()Super.New( "Modular",1800,720,WindowFlags.Resizable|WindowFlags.HighDPI )AddTheme()AddDocks()EndEndFunction Main()' mojolabs.EnableHighDPI()New AppInstanceNew ModularWindowApp.Run()EndApril 10, 2018 at 8:33 am #14308This code in development (super smooth mojo) adds some simple grid lines using rectangles with big fat alpha 0 gutters in an attempt at sub pixel scrolling.
Attachments:
May 6, 2018 at 7:16 pm #14581Fixed some issues with my super smooth scrolling involving moving texture coordinate from outside to inside the gutters. Now adding some drawing primitives with same large gutter attribute.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690#Import "<std>"#Import "<mojo>"#Import "<mojox>"#Import "<mojolabs>"#Import "modular.theme.json"Using std..Using mojo..Using mojox..Alias DRect:Rect<Double>Const MinZoom:Double=0.5Const MinWidth:=32Const MinHeight:=24Const DefaultWindowFlags:WindowFlags=WindowFlags.HighDPI|WindowFlags.ResizableAlias JsonFields:StringMap<JsonValue>Struct PrefsField skin:="asset::modular.theme.json"Field top:Int=35Field bottom:int=120Field left:int=250Field right:Int=250Field menuwidth:Int=200Field toolswidth:Int=480Field scale:Double=1.0Field frame:Recti=New Recti(100,100,1720,1280)Field fullscreen:BoolMethod Invalid:Bool()Return frame.Width < MinWidth Or frame.Height<MinHeightEndFunction JsonRect:JsonObject(rect:Recti)Local json:=New JsonObject()json["top"]=New JsonNumber(rect.Top)json["bottom"]=New JsonNumber(rect.Bottom)json["left"]=New JsonNumber(rect.Left)json["right"]=New JsonNumber(rect.Right)Return jsonEndFunction RectJson:Recti(obj:JsonFields)Local x0:=obj["left"].ToNumber()Local y0:=obj["top"].ToNumber()Local x1:=obj["right"].ToNumber()Local y1:=obj["bottom"].ToNumber()Return New Recti(x0,y0,x1,y1)EndMethod ToJson:JsonObject()Local json:=New JsonObject()json["skin"]=New JsonString(skin)json["top"]=New JsonNumber(top)json["bottom"]=New JsonNumber(bottom)json["left"]=New JsonNumber(left)json["right"]=New JsonNumber(right)json["menuwidth"]=New JsonNumber(menuwidth)json["toolswidth"]=New JsonNumber(toolswidth)json["scale"]=New JsonNumber(scale)json["frame"]=JsonRect(frame)json["fullscreen"]=New JsonBool(fullscreen)Return jsonEndMethod FromJson:Prefs(json:JsonObject)skin=json["skin"].ToString()top=json["top"].ToNumber()bottom=json["bottom"].ToNumber()left=json["left"].ToNumber()right=json["right"].ToNumber()menuwidth=json["menuwidth"].ToNumber()toolswidth=json["toolswidth"].ToNumber()scale=json["scale"].ToNumber()If json.Contains("fullscreen")fullscreen=json["fullscreen"].ToBool()EndifIf json.Contains("frame")frame=RectJson(json["frame"].ToObject())EndifReturn SelfEndEndFunction AlphaRing:Image()Local d:=512Local r:=32Local pix:=New Pixmap(d,d,PixelFormat.A8)For Local y:=0 Until dFor Local x:=0 Until dLocal dx:=x-d/2Local dy:=y-d/2Local rr:Double=(dx*dx+dy*dy)-r*rLocal a:=0If rr<0a=255Elseif rr<512a=11.2*Sqrt(512-rr)EndifLocal p:=pix.PixelPtr(x,y)p[0]=aNextNextLocal texture:=New Texture(pix,TextureFlags.FilterMipmap)Return New Image(texture)EndAlias XY:Vec2<Double>Alias Quad:RectfAlias Radius:DoubleClass ShapeMethod Plot(xy:XY,r:Radius)EndEndClass TubeConst MaxCount:=64Field verts:=New Float[MaxCount*4]Field uv:=New Float[MaxCount*4]Field indices:=New Int[MaxCount*6]Field pos:XYField pos1:XYField gutter:DoubleField thick:DoubleField count:IntMethod New()For Local i:=0 Until MaxCountindices[i*6+0]=i*2+0indices[i*6+1]=i*2+2indices[i*6+2]=i*2+1indices[i*6+3]=i*2+1indices[i*6+4]=i*2+2indices[i*6+5]=i*2+3NextEndMethod start(xy:XY,width:Double)pos=xythick=widthgutter=0.25count=1EndMethod move(xy:XY)Local dir:=(xy-pos).Normalize()If count=1uv[0]=0.0+gutteruv[1]=0.0+gutteruv[2]=0.0+gutteruv[3]=1.0-gutterverts[0]=pos.X+(dir.Y-dir.X)*thickverts[1]=pos.Y-(dir.X+dir.Y)*thickverts[2]=pos.X-(dir.Y+dir.X)*thickverts[3]=pos.Y+(dir.X-dir.Y)*thickuv[4]=0.5uv[5]=0.0+gutteruv[6]=0.5uv[7]=1.0-gutterverts[4]=pos.X+dir.Y*thickverts[5]=pos.Y-dir.X*thickverts[6]=pos.X-dir.Y*thickverts[7]=pos.Y+dir.X*thickcount=2Endifuv[count*4+0]=0.5uv[count*4+1]=0.0+gutteruv[count*4+2]=0.5uv[count*4+3]=1.0-gutterverts[count*4+0]=xy.X+dir.Y*thickverts[count*4+1]=xy.Y-dir.X*thickverts[count*4+2]=xy.X-dir.Y*thickverts[count*4+3]=xy.Y+dir.X*thickpos1=pospos=xycount+=1EndMethod finish(canvas:Canvas,circle:Image)Local dir:=(pos-pos1).Normalize()verts[count*4+0]=pos.X+(dir.Y+dir.X)*thickverts[count*4+1]=pos.Y-(dir.X-dir.Y)*thickverts[count*4+2]=pos.X-(dir.Y-dir.X)*thickverts[count*4+3]=pos.Y+(dir.X+dir.Y)*thickuv[count*4+0]=1.0-gutteruv[count*4+1]=0.0+gutteruv[count*4+2]=1.0-gutteruv[count*4+3]=1.0-gutterLocal order:=3Local primCount:=count*2Local verts0:=Varptr verts[0]Local uv0:=Varptr uv[0]Local indices0:=Varptr indices[0]canvas.DrawPrimitives(order,primCount,verts0,8,uv0,8,Null,4,circle,indices0)EndEndClass ContextField circle:=AlphaRing()Field vrect3:=New Recti(256-64,256,256+64,256)Field hrect3:=New Recti(256,256-64,256,256+64)Field target:CanvasField tube:TubeMethod BeginPaint(canvas:Canvas)target=canvastarget.BlendMode=BlendMode.Alphatarget.Translate(0,0)tube=New TubeEndMethod VLin(quad:Quad)target.DrawRect(quad,circle,vrect3)EndMethod HLin(quad:Quad)target.DrawRect(quad,circle,hrect3)EndMethod Origin(xy:XY)target.Translate(xy.X,xy.Y)EndMethod Zoom(z:Float)target.Scale(z,z)EndMethod Plot(xy:XY,r:Radius)Local quad:=New Quad(xy.X-r,xy.y-r,xy.X+r,xy.y+r)target.DrawRect(quad,circle)EndMethod Line(p0:XY,p1:XY,r0:Radius)tube.start(p0,r0)tube.move(p1)tube.finish(target,circle)EndMethod Draw(shape:Shape)EndMethod EndPaint()target=NullEndEndGlobal prefs:=New Prefs()Global PrefsPath:=(AppPath()+".prefs")Class Grid Extends ViewField bg:=Color.SilverField fg:=Color.GreyField shape:=New ShapeField context:=New ContextField org:XYField vel:XYField grid:=32Field zoom:=2.5Method New()shape.Plot(New XY(0,0),10)EndMethod OnUpdate()org+=velvel*=0.972EndField mouseXY:Vec2iMethod OnMouseEvent( event:MouseEvent ) OverrideLocal xy:=event.LocationIf event.Type=EventType.MouseWheelzoom+=event.Wheel.y/16.0ReturnEndifIf event.Type=EventType.MouseDownvel*=0mouseXY=xyEndifIf event.Type=EventType.MouseUpEndifIf event.Type=EventType.MouseMove And event.ButtonLocal delta:=xy-mouseXYvel=vel*0.5+deltaEndifmouseXY=xyEndMethod OnKeyEvent( event:KeyEvent ) OverrideLocal mask:=event.ModifiersIf mask&Modifier.Control And event.Type=EventType.KeyDown' Select event.Key' EndEndifSuper.OnKeyEvent(event)EndMethod OnRender(canvas:Canvas) OverrideOnUpdate()context.BeginPaint(canvas)Local w:=canvas.Viewport.WidthLocal h:=canvas.Viewport.Heightcanvas.Clear(bg)canvas.Color=fgLocal thick:=Abs(zoom)Local g:=grid*thickLocal wide:Int=1+w/gLocal hi:Int=1+h/gLocal oy:=((org.Y Mod g)-g)Mod gLocal ox:=((org.X Mod g)-g)Mod gLocal iy:Int=math.Floor(-org.y/g)For Local y:=oy To h Step gLocal th:=thick * ((iy&3) ? 1 Else 2)Local rect:=New Rectf(0,y-th,w,y+th)' canvas.DrawRect(rect)' canvas.DrawRect(rect,circle,hrect2)context.HLin(rect)iy+=1NextLocal ix:Int=math.Floor(-org.x/g)For Local x:=ox To w Step gLocal th:=thick * ((ix&3) ? 1 Else 2)Local rect:=New Rectf(x-th,0,x+th,h)' canvas.DrawRect(rect)' canvas.DrawRect(rect,circle,vrect2)context.VLin(rect)ix+=1Nextcontext.Origin(org)context.Zoom(zoom)context.Plot(New XY(50,50),20)context.Line(New XY(150,150),New XY(250,200),10)' for each layercontext.Draw(shape)context.EndPaint()RequestRender()EndEndClass ModularWindow Extends WindowField docks:DockingViewField topView:DockingViewField bottomView:TabViewField leftView:ViewField rightView:TabViewField content:TabViewField menubar:MenuBarField toolbar:GridViewField commandline:TextFieldField scale:DoubleField frame:RectiMethod New()Super.New("Modular",prefs.frame,DefaultWindowFlags)Fullscreen=prefs.fullscreenSetTheme(prefs.skin)AddDocks()SetZoom(prefs.scale)EndFunction Reset()libc.rename(PrefsPath,PrefsPath+".old")libc.remove(PrefsPath)App.Terminate()EndMethod Save()prefs.top=topView.Heightprefs.bottom=bottomView.Heightprefs.left=leftView.Widthprefs.right=rightView.Widthprefs.menuwidth=menubar.Widthprefs.scale=scaleprefs.frame=frameprefs.fullscreen=FullscreenLocal obj:=prefs.ToJson()Local str:=obj.ToJson()SaveString(str,PrefsPath)EndMethod OnWindowEvent( event:WindowEvent ) OverrideSelect event.TypeCase EventType.WindowCloseSave()Case EventType.WindowMovedIf Not Fullscreen And Not Maximized And Not Minimizedframe=FrameEndifCase EventType.WindowResizedIf Not Fullscreen And Not Maximized And Not MinimizedPrint "Size"frame=FrameSetZoom(scale)EndifEndSuper.OnWindowEvent(event)End' triggersMethod Cut()EndMethod Copy()EndMethod Paste()EndMethod Create()EndMethod Open()EndMethod Close()Save()EndMethod Quit()Save()App.Terminate()EndMethod ToggleFullscreen()If Not Fullscreen frame=FrameFullscreen=Not FullscreenEndMethod ToggleMaximized()If Not FullscreenIf MaximizedRestore()ElseMaximize()EndifEndifEndMethod SetZoom(zoom:Double)scale=Max(zoom,MinZoom)prefs.scale=scaleApp.Theme.Scale=New Vec2f( scale,scale )EndMethod CreateCommandLine:TextField()Return New TextField(">",8192)EndMethod AddDocks()menubar=CreateMenu()toolbar=CreateTools()topView=New DockingViewcommandline=CreateCommandLine()topView.ContentView=commandlinetopView.AddView(menubar,"left",prefs.menuwidth,true)topView.AddView(toolbar,"right",prefs.toolswidth,True)bottomView=CreateTabs()leftView=CreateFileTree()content=CreateTabs()rightView=CreateTabs()docks=New DockingViewdocks.AddView(topView,"top",prefs.top, True)docks.AddView(bottomView,"bottom",prefs.bottom,True)docks.AddView(leftView,"left",prefs.left,True)docks.AddView(rightView,"right",prefs.right,True)docks.ContentView=contentLocal grid:=New Grid()Local sceneTree:=CreateTree()AddTab(rightView,"Scene",sceneTree)AddTab(bottomView,"Help",New HtmlView())AddTab(content,"Grid",grid)ContentView=docksdocks.ContentView.MakeKeyView()EndFunction DirectoryTree( path:String,parent:TreeView.Node )For Local f:=Eachin LoadDir( path )Local p:=path+"/"+fLocal node:=New TreeView.Node( f,parent )If GetFileType( p )=FileType.Directory DirectoryTree( p,node )NextEndMethod CreateTools:GridView()Local bar:=New GridView(8,2)bar.AddView(New Button("Grab"),0,0)bar.AddView(New Button("Select"),0,0)bar.AddView(New Button("Plot"),1,0)bar.AddView(New Button("Edit"),2,0)Return barEndMethod CreateMenu:MenuBar()Local fileMenu:=New Menu( "File" )Local recentFiles:=New Menu( "Recent Files..." )Local editMenu:=New Menu( "Edit" )AddAction(editMenu,"Cut",Key.X,Modifier.Control).Triggered=CutAddAction(editMenu,"Copy",Key.C,Modifier.Control).Triggered=CopyAddAction(editMenu,"Paste",Key.V,Modifier.Control).Triggered=PasteLocal viewMenu:=New Menu( "View" )AddAction(fileMenu,"New",Key.N,Modifier.Control).Triggered=CreateAddAction(fileMenu,"Open",Key.O,Modifier.Control).Triggered=OpenAddAction(fileMenu,"Close",Key.W,Modifier.Control).Triggered=CloseAddAction(fileMenu,"Quit",Key.Q,Modifier.Alt).Triggered=QuitAddAction(viewMenu,"Fullscreen",Key.F11).Triggered=ToggleFullscreenAddAction(viewMenu,"Maximized",Key.F12).Triggered=ToggleMaximizedAddAction(viewMenu,"Zoom In",Key.Equals,Modifier.Control).Triggered=ZoomInAddAction(viewMenu,"Zoom Out",Key.Minus,Modifier.Control).Triggered=ZoomOutLocal helpMenu:=New Menu( "Help" )AddAction(helpMenu,"Reset to Factory Defaults").Triggered=ResetLocal menuBar:=New MenuBarmenuBar.AddMenu( fileMenu )menuBar.AddMenu( editMenu )menuBar.AddMenu( viewMenu )menuBar.AddMenu( helpMenu )Return menuBarEndFunction AddAction:Action(menu:Menu,name:String,hotkey:Key=Key.None,modifiers:Modifier=Modifier.None)Local action:=New Action(name)action.HotKey=hotkeyaction.HotKeyModifiers=modifiersmenu.AddAction(action)Return actionEndMethod AddTab(tabView:TabView, title:String, content:View)tabView.AddTab( title,content )tabView.CurrentIndex=0EndMethod CreateTabs:TabView()Local tabView:=New TabView( TabViewFlags.ClosableTabs|TabViewFlags.DraggableTabs )tabView.RightClicked=Lambda()Local menu:=New Menumenu.AddAction( "Action 1" )menu.AddAction( "Action 2" )menu.AddAction( "Action 3" )menu.Open()EndtabView.CloseClicked=Lambda( index:Int )tabView.RemoveTab( index )If tabView.CurrentView Or Not tabView.NumTabs ReturnIf index=tabView.NumTabs index-=1tabView.CurrentIndex=indexEndReturn tabViewEndMethod CreateTree:TreeView()Local treeView:=New TreeViewtreeView.NodeClicked+=Lambda( node:TreeView.Node )Alert( "Node clicked: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeExpanded+=Lambda( node:TreeView.Node )' Alert( "Node expanded: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeCollapsed+=Lambda( node:TreeView.Node )' Alert( "Node collapsed: node.Text=~q"+node.Text+"~q" )EndtreeView.RootNode.Text="Origin"' DirectoryTree( dir,treeView.RootNode )Return treeViewEndMethod CreateFileTree:TreeView()Local treeView:=New TreeViewtreeView.NodeClicked+=Lambda( node:TreeView.Node )Alert( "Node clicked: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeExpanded+=Lambda( node:TreeView.Node )' Alert( "Node expanded: node.Text=~q"+node.Text+"~q" )EndtreeView.NodeCollapsed+=Lambda( node:TreeView.Node )' Alert( "Node collapsed: node.Text=~q"+node.Text+"~q" )EndtreeView.RootNode.Text=CurrentDir()DirectoryTree( CurrentDir(),treeView.RootNode )Return treeViewEndMethod AddUI()Local list:=New ListViewlist.AddItem( "listview" )list.ItemClicked+=Lambda( item:ListView.Item )Local index:=list.IndexOfItem( item )Print "Item "+index+" clicked"EndContentView=listEndMethod SetTheme(path:String)App.Theme.Load( path )EndMethod ZoomIn()SetZoom(prefs.scale+0.0625)EndMethod ZoomOut()SetZoom(prefs.scale-0.0625)EndEndFunction Main()' mojolabs.EnableHighDPI()New AppInstanceLocal filePrefs:=JsonObject.Load(PrefsPath)If filePrefsprefs.FromJson(filePrefs)If prefs.Invalid()ModularWindow.Reset()Print "Invalid Prefs - invoked Factory Reset"ReturnEndifEndifNew ModularWindowApp.Run()End -
AuthorPosts
You must be logged in to reply to this topic.
