havenphillip Posted June 14, 2018 Share Posted June 14, 2018 Is there a simpler way to center text so that it doesn't depend on the left margin? I have this counter and it looks right until it goes less than 100 and then less than 10. At that point it looks out of place. I thought I'd use "if self.timer...then self.textPos..." but then the text slides across the whole screen the whole time it's in the timer range. I want it to scoot over once then stop. How do I stop it? context:DrawText(""..Math:Round(self.timer),self.textPos, 465) --text positions if self.timer >= 100 and self.timer <= 999 then self.textPos = self.textPos end if self.timer >= 10 and self.timer <= 99 then self.textPos = self.textPos +4 end --slides across screen at a rate of "4" if self.timer >= 0 and self.timer <= 9 then self.textPos = self.textPos +8 end --slides across screen at a rate of "8" Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 I am not really sure what you are trying to do. You are asking about centering text, but than demonstrate code that animates the text. Can you elaborate a little bit more. Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 14, 2018 Author Share Posted June 14, 2018 Ok like if the countdown is 100 the text is centered where I want it to be but once it goes to 99 it looks slightly left since it loses that third digit place. So I want to keep it looking centered as it counts down and my solution was to shift it over slightly so it looks centered at 99 like it does at 100. But my problem is I'm animating it across the screen. I just want it to scoot over a bit then stop moving. Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 Ah I get it now. The best solution is not applying any 'move over' margin at all. Instead do the following: Lets say your health circle is 200 px wide. Get center position of the health UI: centerUiX = ScreenWidth - (healthCircleWidth/2) Get the healthAmountWidth of the text every frame. There is a leadwerks API command for that. Subtract half of the text width from the centerUiX: drawX = centerUiX - (healthAmountWidth/2) Draw the text with drawX; You can also use FlowGUI (free for download at https://bitbucket.org/Aggror/flowgui/src). I don't know if the official leadwerks UI has text centering. Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 14, 2018 Author Share Posted June 14, 2018 OK that'll take me a minute. Let me see if I can do that. The healthAmountWidth every frame? Is that just context:GetWidth? I got the FlowGUI. I've looked through it before. It seems really cool but it's out of my league. If only there were a tutorial or something on it (cough cough). Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 Technically you would only have to recalculate the position if your health changes, but it can't hurt to do it every frame. Context:GetWidth will get you the width of your game window. GetTextWidth, will get get you the length of a text string. https://www.leadwerks.com/learn?page=API-Reference_Object_Asset_Font_GetTextWidth Alternatively with FlowGui. Best to download the sample project and opening a sample scene with text element. From the top of my head create a pivot and attach flowgui manager lua script create a pivot and attach label style lua script (here you can fine tune font, text size, color, center positioning) create a healtbar script (your existing script) which references the label style and flowgui manager. Add something like this: --Load FlowGUI if a script makes use of it. import "Scripts/FlowGUI/FlowGUI.lua" Script.guiManager = nil --entity "GUI manager" Script.healthLabelStyle = nil --entity "HealthLabelStyle" Script.healthLabel = nil function Script:UpdateWorld() self.healthLabelStyle = self.healthLabelStyle.script:GetStyle() self:CreateLabel() end function Script:CreateLabel() self.healthLabel = FG_Label:Create() self.healthLabel:SetPosition(Vec2(200,120)) self.healthLabel:SetScale(Vec2(150,50)) self.healthLabel:SetText("Your health") self.healthLabel:SetGUIStyle(self.healthLabelStyle) self.healthLabel:SetTextPosition(FG_TextPosition.Center) self.healthLabel:SetDebug(false) self.guiManager:AddElement(self.healthLabel) end function Script:PostRender() self.healthLabel:SetText("Your updated health") end Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 14, 2018 Author Share Posted June 14, 2018 Ok this is what I have. If I put it under PostRender() it loads the font like every second. Doesn't do that if I put it under Start() but I think that would probably defeat the purpose. The other thing is it doesn't move position when it changes from 100 to 99. --text positions font = Font:Load("Fonts/arial.ttf",10) context:SetFont(font) centerUiX = self.cirPos.x - self.radius/2 timeX = font:GetTextWidth(text) drawX = centerUiX - timeX/2 (self.cirPos.x is context:GetWidth I'll clean that up) I'm going to try this with your FlowGUI. Also it's a countdown timer, though. Not health. I don't know if that changes anything. I think that may be why it's loading the font every second. Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 You can load the font in the start function, and set the font in the postrender function. self.font = Font:Load("Fonts/arial.ttf",10) You can clean it up (like you already said) with something like this: centerTimerX = context:GetWidth() - (timerAreaWidth / 2) drawX = centerTimerX - (font:GetTextWidth(text)/2) You can also System:Print(font:GetTextWidth(text)) to see if the width of the text is actually changing. Sorry I was thinking of a healthbar for some reason, but it doesn't matter for its purpose. Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 14, 2018 Author Share Posted June 14, 2018 Oh duh of course load the font in the Start()! It's not changing position. I'm not sure at what point we told it to. Tried System:Print it's telling me "argument #3 is 'string';'[no object]' expected. I'm not sure maybe I'm not putting the right thing in the brackets. I've tried "text" and "self.timer" I tried with FlowGUI it's telling me "attempt to index field 'healthLabel' (a nil value) --line 93 line 93: self.healthLabel:SetText("Your updated health") I'm not supposed to child something to something or anything else, right? I created the two pivots with the correct scripts. Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 "argument #3 is 'string';'[no object]' means that you put in an object rather than a string. Can you post the code were you print info? I tried with FlowGUI it's telling me "attempt to index field 'healthLabel' (a nil value) --line 93 Can you screenshot the scene tree were you have created the style, guimanager? Child/parent isn't really required but helps organising the scene. As long as the guimanager is loaded first and the styles are being loaded before you create the label, everything should work. If you look at any example scene from the FlowGUI project, you can see that I like to organise my scene as follow: pivot-GuiManager (gui manager script attached) pivot styles (no script attached) timerLabelStyle (labelstyle script attached) mycustomobject (in your case the timer) Referencing GUI manager and Timer lablestyle. here is loading the ui style with a wait time build in. I am not at home, so haven't tested it. --Load FlowGUI if a script makes use of it. import "Scripts/FlowGUI/FlowGUI.lua" Script.guiManager = nil --entity "GUI manager" Script.healthLabelStyle = nil --entity "HealthLabelStyle" Script.healthLabel = nil Script.uiLoadInterval = 1 Script.startTimeStamp = nil Script.uiLoaded = false function Script:Start() self.startTimeStamp = Time:GetCurrent() self.guiManager = self.guiManager.script end function Script:UpdateWorld() if self.uiLoaded == false and Time:GetCurrent()-self.startTimeStamp > self.uiLoadInterval then self.healthLabelStyle = self.healthLabelStyle.script:GetStyle() self:CreateLabel() sel.uiLoaded = true end end function Script:CreateLabel() self.healthLabel = FG_Label:Create() self.healthLabel:SetPosition(Vec2(200,120)) self.healthLabel:SetScale(Vec2(150,50)) self.healthLabel:SetText("Your health") self.healthLabel:SetGUIStyle(self.healthLabelStyle) self.healthLabel:SetTextPosition(FG_TextPosition.Center) self.healthLabel:SetDebug(false) self.guiManager:AddElement(self.healthLabel) end function Script:PostRender() if sel.uiLoaded then self.healthLabel:SetText("Your updated health") end end Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 14, 2018 Author Share Posted June 14, 2018 Yeah here's scene tree gui: Now I"m getting: attempt to call method 'AddElement' (a nil value) -- Line 70 Line 70: self.guiManager:AddElement(self.healthLabel) I don't know why it would be nil. Here's my current script. You can see it's a mess. System:Print is currently under PostRender near the bottom. "Timer" is this script on the tree. Countdown Circle.lua Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 We are getting closer. So for some reason the Flowgui manager is empty in your script. Is it referenced in your countdown script? Instead of linking in the flowGUI manager, you can also create it by script. Note that you only need 1 flowguiManager. So you would either place it in main.lua or you have to make sure it is made only once. self.flowGUIManager = FlowGUI_Manager:Create(Window:GetCurrent(), Context:GetCurrent() ) Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 14, 2018 Share Posted June 14, 2018 You could also do a simple test to see which script is loaded first. Place this in the start function of the scripts you use. System:Print("Script start from " .. self.entity:GetKeyValue("name")) Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 14, 2018 Author Share Posted June 14, 2018 OK sorry. What do you mean that the Flowgui manager is empty in the script? You mean the entity? Quote Link to comment Share on other sites More sharing options...
macklebee Posted June 14, 2018 Share Posted June 14, 2018 There is also a way to center text inherent to LE in available parameter settings not in the official documentation, but was posted at one point in the gui development blog, virtual void DrawText(std::string& text, const int x, const int y, const int width, const int height, const int style = 0);//lua So in your example, I would set the x and y positions as the upper left hand corner of the circle's image and the width/height as the width and height of the circle. Example showing drawing text within the center of a rectangle where the text width is changing and the style parameter settings are keeping it centered: window = Window:Create("example",0,0,400,400) context = Context:Create(window) world = World:Create() light = DirectionalLight:Create() light:SetRotation(45,45,0) camera = Camera:Create() camera:SetPosition(0,0,-3) counter = 1400 toggle = 0 myfont = Font:Load("Fonts/arial.ttf", 36) context:SetFont(myfont) while not window:KeyHit(Key.Escape) do if window:Closed() then return false end if toggle==1 then counter = counter + 10 end if toggle==0 then counter = counter - 10 end if counter>=1400 then toggle = 0 end if counter<=10 then toggle = 1 end Time:Update() world:Update() world:Render() context:SetBlendMode(Blend.Alpha) context:SetColor(1,0,0,.5) context:DrawRect(38,30,300,300,1,30) context:DrawText(string.format("%.0f",counter),38,30,300,300,Text.VCenter+Text.Center) context:SetColor(1,1,1,1) context:SetBlendMode(Blend.Solid) context:Sync(true) end 1 Quote Win7 64bit / Intel i7-2600 CPU @ 3.9 GHz / 16 GB DDR3 / NVIDIA GeForce GTX 590 LE / 3DWS / BMX / Hexagon macklebee's channel Link to comment Share on other sites More sharing options...
Yue Posted June 14, 2018 Share Posted June 14, 2018 A possible solution: 100 099 095 Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 15, 2018 Author Share Posted June 15, 2018 Ah ok sweet that worked: context:DrawText(string.format("%.0f",self.timer), self.cirPos.x-14, self.cirPos.y-14, 30, 30, Text.VCenter+Text.Center) Cool I'll leave it here for whoever wanders by: Circle Timer.lua (Currently set up to attach to pivot then child to player. Kills player at zero) Quote Link to comment Share on other sites More sharing options...
havenphillip Posted June 15, 2018 Author Share Posted June 15, 2018 I still want to learn that FlowGUI though. I studied some of the sample maps but the scripts call scripts that call scripts. Where's the starting point if I want to understand it? I want to read it all and understand the step by step logic. Where do I start? What's the first script? I also don't understand how you don't use the format "function Script:Start()" for instance but do things like "function GetGuiElements(guiType)". Reminds me of Rick's State Machine Coroutine thing he posted which I also can't make sense of. Quote Link to comment Share on other sites More sharing options...
AggrorJorn Posted June 15, 2018 Share Posted June 15, 2018 If you still want to use FlowGui, there is a small wiki: https://bitbucket.org/Aggror/flowgui/wiki/GUI Manager here is how a minimal example would work: import flowGui somewhere in your main.lua create a flowGui manager create a gui element and add it to the manager. (styles are not even needed to get a ui element to work. ) Remember that FlowGui is no longer being developed and that is there is an official Leadwerks ui that has been released. 1 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.