Forum Replies Created
-
AuthorPosts
-
Oops, sorry, forget than when I uploaded it I became the owner.
I’ve deleted it for now so please upload again.
I’m in the process of adding something like this – new version should be up today some time.
This is because MinSize and MaxSize are really only ‘hints’ (they are applied after OnMeasure) and can be override by some Layout modes, eg: the ‘fill’ modes.
In this case, the default layout mode for a PushButton is ‘fill-x’, so the button ends up filling all the width available, regardless of min/max width. min/max width is still used to help layouts work out where everything goes, but if you ask for ‘fill-x’ you get ‘fill-x’!
You can fix it in this case by making button2 float, eg:
button2.Layout=”float”
button2.Gravity=New Vec2f( .5,.5 )(perhaps PushButton should default to this?)
Making min/max size hard constraints even in the case of ‘fill’ layouts is a possiblity I guess, but I vaguely remember there being a good reason for having it work the way it does…
Scramble?!? Loved that entity system version you did…
I ended up adding them to the “Top” view and made the DockingView layout “float” which doesn’t seem correct.
It’s completely correct!
DockingView has turned out to be a super-versatile thing that can be used in place of ‘row view’, ‘column view’ etc (I’ve been reluctant to add RowView and ColumnView for this reason).
DockingView is also used internally by many view types like toolbar, menu, dialog etc (which probably seem more suitable to ‘float’) but in some cases all these really add is a different style, default layout etc.
Using DockingView on its own however you want is fine.
Also I could not figure out how to center-align the text inside the button.
It’s a mojox bug in label.monkey2 – fixed now at github.
Nice first attempt!
It’s a bit overcomplicated, probably because you based it on Label which actually does quite a bit these days! I’ve attached a simplified version below, with the text and event stuff ripped out for clarity. If you do want text/events on your PBar, it’s probably best to just extend Label…in which case you can ditch OnMeasure and just call Super.OnRender at the end of OnRender.
Some notes:
It’s a good idea to set preferred Layout, TextGravity (now fixed!) etc for a view in it’s ctor to increase the chances of it working as expected by users!
I’d recommend ‘fill-x’ layout for view’s like this – ‘stretch’ will cause rendering to be scaled which can look wonky/ugly and distorts borders, skins etc. Also, by using ‘fill-x’ you don’t have to worry about the width returned by OnMeasure, as it will be effectively thrown away. So in the code below, I just return (16,16) from OnMeasure, of which only the height is actually used. However, it’s always a good idea to return something non-0 in OnMeasure just in case the user sets some weird Layout mode. For example, setting my PBar’s Layout to “float” means it will end up being 16 x 16, which wont look ideal but at least it will work. In this case, the user will probably have to use MinSize etc to make it look any good, but that’s OK, you’re not pyschic and can’t be expected to know how wide they want their floating PBars!
A view’s Frame rect is in ‘parent’ coords (parents use it to layout children) so it’s not really much use to children and you don’t want to use it inside OnRender. Unless you’re writing a layout view, you can probably ignore frame altogether. Instead, just use Rect, Width and Height inside OnRender (just like a game). Rect.X and Rect.Y are always (0,0) so Rect discribes the view’s local coordinate system. This makes my PBar’s OnRender very simple!
I’ve also added a custome style to the PBar that adds a dark grey border, just to show how it’s done. Styles can actually be stored in a theme ‘.json’ file, but more on that later. Note that adding/changing a view’s style doesn’t affect anything in terms of OnMeasure/OnRender – this is automatically handled for you by the system.
Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104#import "<std>"#import "<mojo>"#import "<mojox>"Using std..Using mojo..Using mojox..Class PBar Extends ViewMethod New( value:Float=0 )Layout="fill-x"Style=New Style( Style )Style.Border=New Recti( -4,-4,4,4 )Style.BorderColor=Color.DarkGreyValue=valueEndProperty Value:Float()Return _valueSetter( value:Float )value=Clamp( value,0.0,1.0 )If value=_value Return_value=valueRequestRender()EndProtectedMethod OnMeasure:Vec2i() OverrideReturn New Vec2i( 16,16 )EndMethod OnRender( canvas:Canvas ) OverrideLocal t:=Int( Width*_value )canvas.Color=Color.Greycanvas.DrawRect( 0,0,t,Height )canvas.Color=Color.Redcanvas.DrawRect( t,0,Width-t,Height )EndPrivateField _value:FloatEndClass MyWindow Extends WindowGlobal pb:PBar,label:LabelGlobal timer:TimerGlobal counter:IntGlobal bvalue:Float=0.1Method New()Super.New( "Pbar Demo",640,480,WindowFlags.Resizable )label=New Label( "Idle" )label.Gravity=New Vec2f( .5,0 )pb=New PBar(bvalue)timer=New Timer(2,OnUpdate)Local dockingView:=New DockingViewdockingView.AddView( label,"top" )dockingView.AddView( pb,"top" )ContentView=dockingViewEndMethod OnUpdate()counter+=1Print "Tick: "+counterbvalue=bvalue+.1pb.Value=bvaluelabel.Text="Value "+bvalueEndEndFunction Main()New AppInstanceNew MyWindowApp.Run()EndThe TreeView itself is not a node, but contains a single root node that you get at with the RootNode property:
Monkey123456789Local treeView:=New TreeView'Print treewView.RootNode.NumChildren '0''Add a child to root node!'Local child:TreeView.Node=New TreeView.Node( "Child1",treeView.RootNode )Print treeView.RootNode.NumChildren '1That’s cool, I wasn’t getting at you or anything, but it *is* an interesting problem IMO.
The traditional way to solve this would almost inevitably involve a dynamic downcast somewhere, possibly eventually in quite a few places (that’s why I wanted to see your solution, perhaps there’s a way to do it without..?) and downcasts are both dangerous and slow.
I think what fascinates me about generics and problems like this is that they can provide ‘almost dynamic’ like typing behaviour, but with 0 runtime overhead since everything’s done at compile time.
Are they confusing? Perhaps, although I think I presented the fundamental problem pretty clearly above. Aand perhaps by messing around with problems like this we can come up ways to make generics easier to use? Maybe not though…
And I’d still be interested to see what people could come up with in terms of a non-generic solution – perhaps there’s a non-generic way to solve this too?
Danilo tried to wrap the c++ interface, but that gets complex as you need a fair bit of glue to take care of the differences between mx2 and c++.
There is however a plain ‘c’ interface/wrapper that should be much easier to mx2-ify. I think this is what most/all other SFML wrappers user.
I wont be doing much with audio until I at least have it working everywhere.
You are of course free to create your own audio module though, perhaps publish it via module manager?
Such as?
To simplify things a bit, is this more or less what you’re after?
It doesn’t compile due to cyclic declaration error, but I *think* it should be possible:
(Just added some hypothetial ‘Wheres’ that wont work yet, but I think they make it clearer!)
Monkey1234567891011121314151617181920212223242526272829303132333435#Import "<std>"Using std..Class Entity<T> Where T Extends ComponentField components:=New Stack<T>EndClass Component<T> Where T Extends EntityField entity:TEndClass AdvancedEntity Extends Entity<AdvancedComponent>EndClass AdvancedComponent Extends Component<AdvancedEntity>EndFunction Main()Local entity:=New AdvancedEntityLocal component:=New AdvancedComponententity.components.Push( component )component.entity=entityEndI think you need to make Component generic too – I tried this but the compiler complained about cyclic declarations, which I don’t think is quite right. Will look into it a bit later.
Rect and Frame are only valid after GUI layout is updated, which will happen just before the next render if you’ve just added a view. In this way, Rect really reflects what the user sees on the screen.
You can use MinSize/MaxSize to clamp a view’s size to a range, but these can be overriden in some cases, eg: if the view’s layout is set to ‘fill’ and it’s the content of a docking view.
You can manually control a view’s layout by using the low-level AddChildView() and modifying it’s ‘Frame’ property directly – in which case you may also need to call view.RequestRender(). You are totally in control of the view in this case, ie: no layout will be performed at all. This is pretty much how the container views like DockingView etc work, except they only modify Frame during OnLayout() (which is the recommended way/time to set a child view’s frame).
You can also use the (currently hidden I think) MeasureLayoutSize() method on a view. However this is not generally recommended, as measuring a view can be expensive, ie: a treeview with thousands of nodes in it etc. But in some cases, eg: for measuring a dialog just before it’s opens, this is kind of unavoidable.
What are you trying to do might be the better question?
I like the ‘Playhead’ addition, will definitely add that although I think I might use ‘SampleIndex:Int’, just a bit more descriptive I think. You can apparently write to it too!
And it’s cool that you managed to implement the whole thing by simply extending View and TedDocument, nice work.
-
AuthorPosts