Jump to content

Einlander

Members
  • Posts

    778
  • Joined

  • Last visited

Posts posted by Einlander

  1. On 10/6/2018 at 12:26 AM, slimwaffle said:

    if event.source == self.but1 then

    replace that line with this 

    if event.source == Storage.but1 then

    Your Storage variable was created as a global variable. It is not local to the script that created it.

  2. It doesn't interface with leadwerks at all. It exploits how leadwerks likes to convert fbx files automatically. So my program sits there and waits until you save something. When that happens it automatically converts the file to a fbx file. Leadwerks sees a new updated fbx file and and converts it to a mdl. No actual integration at all.

  3. 2 minutes ago, Yue said:


    There's something strange going on here. When I put a polymesh the force of gravity does not attract it even though it has 2000 mass. If I put another body type, if it's attracted to gravity.  Something strange is that it only happens in the rear of the vehicle in the front if it goes downwards, without any problem, gives the impression that automatically the center of gravity is in the front, and I don't know how to change that point of gravity to my needs.  

    MC.png.8e4d4923bad52920d0f3c3c1c933094a.png

    Polymeshes do no move at all. Even with large mass. Use any option, but not polymesh when you want something to move.

    • Upvote 1
  4. This is a simple script that will let you get the desktops current resolution. It has not been tested in linux.

    It creates a hidden window, Maximizes it, and gets the window size. That's it.

    It returns a Vec2(). DO NOT USE IF THE PROGRAM IS ALREADY FULLSCREEN. It will cause you some annoyances.

    	function GetDesktopResolution() --Vec2()
    		-- get current desktop resolution ; Super quick and dirty method, works on windows dont know about linux
    		local launchertestwindow = Window:Create(System.AppName,0,0,1024,768,Window.Tool)
    		launchertestwindow:Maximize()
    		local desktopres = Vec2(launchertestwindow:GetWidth(),launchertestwindow:GetHeight())	
    		launchertestwindow:Release()
    		return desktopres
    	end

     

    • Upvote 1
  5. This is a launcher that starts before your game allowing players to set the game's graphical options. This was created to solve the issue of Leadwerks starting at the highest resolution of the monitor, instead of the current desktop settings. It uses a quick and dirty method to get the desktop resolution.  THIS HAS NOT BEEN TESTED ON LINUX!! If this works on linux let me know, or if you made any changes to make it work.

    The script is to be loaded with your game and launched before the main window is created. There are some modifications to main.lua but they are very simple.

    Here is the script. Save it as Launcher.lua in the same folder as Menu.lua

     
    
    -- Settings Launcher by Einlander
    
    function LauncherMenu() -- It provides it's own context
    	local LauncherMenu = {}	
    	local LauncherWindow = Window:Create(((title ~= nil) and title or System.AppName),0,0,400,650,Window.Titlebar + Window.Center)	
    	local LauncherContext = Context:Create(LauncherWindow)
    	local LauncherScale = 1
    	local LauncherBorder = 10
    	local LauncherMenu = GUI:Create(LauncherContext)	
    	local LauncherMenuClosed = false
    	
    
    	LauncherMenu:SetScale(LauncherScale)
    	LauncherMenu:GetBase():SetScript("Scripts/GUI/Panel.lua")
    	
    	LauncherMenu.tabber = Widget:Tabber(LauncherBorder,LauncherBorder,LauncherMenu:GetBase():GetClientSize().x-(LauncherBorder*2),LauncherMenu:GetBase():GetClientSize().y-(LauncherBorder*2)-28,LauncherMenu:GetBase())
    	LauncherMenu.tabber:AddItem("Options",true)
    	LauncherMenu.panel = Widget:Panel(0,0,LauncherMenu.tabber:GetClientSize().x,LauncherMenu.tabber:GetClientSize().y,LauncherMenu.tabber)
    	
    	local y=LauncherBorder
    	local sep=40
    	
    	LauncherMenu.screenreslabel =  Widget:Label("Screen Resolution",20,y,200,16,LauncherMenu.panel)
    	y=y+LauncherMenu.screenreslabel:GetSize().y
    	LauncherMenu.screenres = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	local count = System:CountGraphicsModes()	
    	for n=0,count-1 do
    		local gfx = System:GetGraphicsMode(n)
    		local selected=false		
    		LauncherMenu.screenres:AddItem( gfx.x.."x"..gfx.y,selected)
    	end
    	y=y+sep
    	
    	--Antialias
    	LauncherMenu.aalabel = Widget:Label("Antialias",20,y,200,16,LauncherMenu.panel)
    	y=y+LauncherMenu.aalabel:GetSize().y
    	LauncherMenu.antialias = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.antialias:AddItem("None")
    	LauncherMenu.antialias:AddItem("2x")
    	LauncherMenu.antialias:AddItem("4x")
    	y=y+sep
    	
    	--Texture quality
    	LauncherMenu.texturequalitylabel = Widget:Label("Texture Detail",20,y,200,16,LauncherMenu.panel)
    	y=y+16
    	LauncherMenu.texturequality = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.texturequality:AddItem("Low")
    	LauncherMenu.texturequality:AddItem("Medium")
    	LauncherMenu.texturequality:AddItem("High")
    	LauncherMenu.texturequality:AddItem("Very High")
    	y=y+sep
    	
    	--Lighting quality
    	LauncherMenu.lightqualitylabel = Widget:Label("Lighting Quality",20,y,200,16,LauncherMenu.panel)
    	y=y+16
    	LauncherMenu.lightquality = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.lightquality:AddItem("Low")
    	LauncherMenu.lightquality:AddItem("Medium")
    	LauncherMenu.lightquality:AddItem("High")
    	y=y+sep
    	
    	--Terrain quality
    	LauncherMenu.terrainqualitylabel = Widget:Label("Terrain Quality",20,y,200,16,LauncherMenu.panel)
    	y=y+16
    	LauncherMenu.terrainquality = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.terrainquality:AddItem("Low")
    	LauncherMenu.terrainquality:AddItem("Medium")
    	LauncherMenu.terrainquality:AddItem("High")
    	y=y+sep
    	
    	--Water quality	
    	LauncherMenu.waterqualitylabel = Widget:Label("Water Quality",20,y,200,16,LauncherMenu.panel)
    	y=y+16
    	LauncherMenu.waterquality = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.waterquality:AddItem("Low")
    	LauncherMenu.waterquality:AddItem("Medium")
    	LauncherMenu.waterquality:AddItem("High")
    	y=y+sep
    	
    	--Anisotropy
    	LauncherMenu.afilterlabel = Widget:Label("Anisotropic Filter",20,y,200,16,LauncherMenu.panel)
    	y=y+16
    	LauncherMenu.afilter = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.afilter:AddItem("None")
    	LauncherMenu.afilter:AddItem("2x")
    	LauncherMenu.afilter:AddItem("4x")
    	LauncherMenu.afilter:AddItem("8x")
    	LauncherMenu.afilter:AddItem("16x")
    	LauncherMenu.afilter:AddItem("32x")
    	y=y+sep
    	
    	--Screen Mode		
    	LauncherMenu.waterqualitylabel = Widget:Label("Window Mode",20,y,200,16,LauncherMenu.panel)
    	y=y+16
    	LauncherMenu.windowmode = Widget:ChoiceBox(20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.windowmode:AddItem("Windowed")
    	LauncherMenu.windowmode:AddItem("Borderless")
    	LauncherMenu.windowmode:AddItem("Full Screen")	
    	y=y+sep
    	
    	--Create a checkbox
    	LauncherMenu.tfilter = Widget:Button("Trilinear Filter",20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.tfilter:SetString("style","Checkbox")
    	y=y+sep
    	
    	--Create a checkbox
    	LauncherMenu.vsync = Widget:Button("Vertical Sync",20,y,200,30,LauncherMenu.panel)
    	LauncherMenu.vsync:SetString("style","Checkbox")
    	y=y+sep
    	
    	
    	LauncherMenu.closeoptions = Widget:Button("Close",LauncherMenu:GetBase():GetClientSize().x-72-LauncherBorder,LauncherMenu:GetBase():GetClientSize().y-28-5,72,28,LauncherMenu:GetBase())
    	LauncherMenu.applyoptions = Widget:Button("Apply",LauncherMenu:GetBase():GetClientSize().x-72*2-4-LauncherBorder,LauncherMenu:GetBase():GetClientSize().y-28-5,72,28,LauncherMenu:GetBase())
    
    
    	local function GetDesktopResolution() --Vec2()
    		-- get current desktop resolution ; Super quick and dirty method, works on windows dont know about linux
    		local launchertestwindow = Window:Create(System.AppName,0,0,1024,768,Window.Tool)
    		launchertestwindow:Maximize()
    		local desktopres = Vec2(launchertestwindow:GetWidth(),launchertestwindow:GetHeight())	
    		launchertestwindow:Release()
    		return desktopres
    	end
    
    	local function splitstring(str,sep)
    		local array = {}
    		local reg = string.format("([^%s]+)",sep)
    		for mem in string.gmatch(str,reg) do
    			table.insert(array, mem)
    		end
    		return array
    	end
    	
    	local function LoadSettings()
    		
    		--Graphics mode
    		-- Are there both screen settings?
    		if (tonumber((System:GetProperty("screenwidth"))) ~= nil) and (tonumber((System:GetProperty("screenheight"))) ~= nil) then
    			--Set the screen res to the saved settings
    			local count = System:CountGraphicsModes()	
    			for n=0,count-1 do
    				local gfx = System:GetGraphicsMode(n)
    				local selected=false
    				if tonumber((System:GetProperty("screenwidth"))) == gfx.x and tonumber((System:GetProperty("screenheight"))) ==gfx.y then					
    					LauncherMenu.screenres:SelectItem(n)
    					break
    				end								
    			end
    		else
    			-- Default
    			System:Print("setting not found")
    			--No setting found, use desktop resolution
    			local desktopres = GetDesktopResolution()
    			local count = System:CountGraphicsModes()
    			for n=0,count-1 do
    				local gfx = System:GetGraphicsMode(n)
    				local selected=false									
    				if desktopres.x ==gfx.x and desktopres.y ==gfx.y then
    					LauncherMenu.screenres:SelectItem(n)	
    					break
    				end															
    			end
    		end
    
    		
    		-- antialias
    		local num = 0
    		num = tonumber((System:GetProperty("antialias")))
    		if num ~= nil then
    			if num > 0 then				
    				if num < 5 then
    					LauncherMenu.antialias:SelectItem(num/2)
    				else					
    					LauncherMenu.antialias:SetText(num)
    				end
    			else
    				LauncherMenu.antialias:SelectItem(1)
    			end
    		else 
    		-- deafult
    			LauncherMenu.antialias:SelectItem(1)
    		end
    		
    		--Texture detail
    		num = tonumber((System:GetProperty("texturedetail")))		
    		if num~=nil then			
    			if num >= 0 then
    				if num <= 3 then
    					LauncherMenu.texturequality:SelectItem(3 - num)
    				else
    					LauncherMenu.texturequality:SelectItem(3)
    				end
    			else
    				LauncherMenu.texturequality:SelectItem(0)
    			end
    		else
    			-- default
    			LauncherMenu.texturequality:SelectItem(3)
    		end
    		
    		--Lighting Quality
    		num = tonumber((System:GetProperty("lightquality")))		
    		if num~=nil then			
    			if num >= 0 then
    				if num <= 2 then
    					LauncherMenu.lightquality:SelectItem(num)
    				else
    					LauncherMenu.lightquality:SelectItem(2)
    				end
    			else
    				LauncherMenu.lightquality:SelectItem(0)
    			end
    		else
    			-- Default
    			LauncherMenu.lightquality:SelectItem(1)
    		end
    		
    		--Terrain Quality
    		num = tonumber((System:GetProperty("terrainquality")))
    		if num ~= nil then
    			if num >= 0 then				
    				if num <= 3 then
    					LauncherMenu.terrainquality:SelectItem(num/2)
    				end
    			else
    				LauncherMenu.terrainquality:SelectItem(1)
    			end
    		else 
    		-- deafult
    			LauncherMenu.terrainquality:SelectItem(1)
    		end
    		
    		--Water Quality
    		num = tonumber((System:GetProperty("waterquality")))
    		if num ~= nil then
    			if num >= 0 then				
    				if num <= 3 then
    					LauncherMenu.waterquality:SelectItem(num)
    				end
    			else
    				LauncherMenu.waterquality:SelectItem(1)
    			end
    		else 
    		-- deafult
    			LauncherMenu.waterquality:SelectItem(1)
    		end
    		
    		--Anisotropic Filter
    		num = tonumber((System:GetProperty("anisotropicfilter")))
    		if num ~= nil then
    			num = num .. "x"
    			if anisotropy=="0x" then anisotropy="None" end
    			for n=0,LauncherMenu.afilter:CountItems()-1 do
    				LauncherMenu.afilter:SetText(num)
    				if num==LauncherMenu.afilter:GetItemText(n) then
    					LauncherMenu.afilter:SelectItem(n)
    					break
    				end
    			end
    		else 
    		-- deafult
    			LauncherMenu.afilter:SelectItem(1)
    		end
    		
    		num = tonumber((System:GetProperty("windowmode")))
    		if num ~= nil then
    			if num >= 0 then				
    				if num > 2 then
    					LauncherMenu.windowmode:SelectItem(2)
    				else
    					LauncherMenu.windowmode:SelectItem(num)
    				end
    			else
    				LauncherMenu.windowmode:SelectItem(2)
    			end
    		else
    		-- default
    			LauncherMenu.windowmode:SelectItem(2)
    		end
    		
    		num = tonumber((System:GetProperty("trilinearfilter")))
    		if num ~= nil then
    			if num > 0 then
    				LauncherMenu.tfilter:SetState(true)
    			end
    		else
    			--Default
    			LauncherMenu.tfilter:SetState(true)
    		end
    		
    		num = tonumber((System:GetProperty("verticalsync")))
    		if num ~= nil then
    			if num > 0 then
    				LauncherMenu.vsync:SetState(true)
    			end
    		else
    			--Default
    			LauncherMenu.vsync:SetState(true)
    		end
    
    
    		
    	end
    	
    	
    	local function ApplySettings()		
    		-- Screen Resolution 		
    		local gfxmode = splitstring(LauncherMenu.screenres:GetItemText(LauncherMenu.screenres:GetSelectedItem()),"x")		
    		System:SetProperty("screenwidth",tonumber(gfxmode[1]))
    		System:SetProperty("screenheight",tonumber(gfxmode[2]))
    		
    		-- Anti-aliasing		
    		if LauncherMenu.antialias:GetSelectedItem() > -1 then
    			
    			if string.lower(LauncherMenu.antialias:GetItemText(LauncherMenu.antialias:GetSelectedItem())) == "none" then
    				System:SetProperty("antialias",0)
    			else			
    				System:SetProperty("antialias",(string.gsub(LauncherMenu.antialias:GetItemText(LauncherMenu.antialias:GetSelectedItem()),"x","")))
    			end
    		else			
    			System:SetProperty("antialias",LauncherMenu.antialias:GetText())
    		end
    		
    		-- Texture Quality
    		System:SetProperty("texturedetail",LauncherMenu.texturequality:CountItems()-1-LauncherMenu.texturequality:GetSelectedItem())
    		
    		-- Lighting Quality
    		System:SetProperty("lightquality",LauncherMenu.lightquality:GetSelectedItem())		
    		
    		-- Terrain Quality		
    		System:SetProperty("terrainquality",LauncherMenu.terrainquality:GetSelectedItem())		
    		
    		-- Water Quality		
    		System:SetProperty("waterquality",LauncherMenu.waterquality:GetSelectedItem())		
    		
    		-- Anistropic Filtering
    		if LauncherMenu.afilter:GetSelectedItem() > -1 then
    			System:SetProperty("anisotropicfilter",(string.gsub(LauncherMenu.afilter:GetItemText(LauncherMenu.afilter:GetSelectedItem()),"x","")))
    			else			
    			System:SetProperty("anisotropicfilter",(string.gsub(LauncherMenu.afilter:GetText(),"x","")))
    		end
    		
    		--Anisotropic Filtering
    		System:SetProperty("trilinearfilter",((LauncherMenu.tfilter:GetState() == true) and 1 or 0))		
    		
    		-- Vsync
    		System:SetProperty("verticalsync",((LauncherMenu.vsync:GetState() == true) and 1 or 0))
    		
    		-- Window Mode
    		if LauncherMenu.windowmode:GetSelectedItem() > -1 then			
    			System:SetProperty("windowmode",LauncherMenu.windowmode:GetSelectedItem())
    			if LauncherMenu.windowmode:GetSelectedItem() == 0 then			
    				LauncherWindowMode = Window.Center + Window.Titlebar				
    			elseif LauncherMenu.windowmode:GetSelectedItem() == 1 then
    				LauncherWindowMode = Window.Center + Window.Tool
    			elseif LauncherMenu.windowmode:GetSelectedItem() == 2 then
    				LauncherWindowMode = Window.FullScreen
    			else
    				LauncherWindowMode = Window.FullScreen
    				System:SetProperty("windowmode",2)
    			end
    			
    		else
    			LauncherWindowMode = Window.FullScreen
    			System:SetProperty("windowmode",2)
    		end		
    	end
    	
    	
    	local function ApplyScreenMode()
    		-- Window Mode
    		
    		num = tonumber((System:GetProperty("windowmode")))
    		if num ~= nil then
    			if num >= 0 then				
    				if num > 2 then
    					LauncherMenu.windowmode:SelectItem(2)
    				else
    					LauncherMenu.windowmode:SelectItem(num)
    				end
    			else
    				LauncherMenu.windowmode:SelectItem(2)
    			end
    		else
    		-- default
    			LauncherMenu.windowmode:SelectItem(2)
    		end
    		
    		if LauncherMenu.windowmode:GetSelectedItem() > -1 then						
    			if LauncherMenu.windowmode:GetSelectedItem() == 0 then			
    				LauncherWindowMode = Window.Center + Window.Titlebar				
    			elseif LauncherMenu.windowmode:GetSelectedItem() == 1 then
    				LauncherWindowMode = Window.Center + Window.Tool
    			elseif LauncherMenu.windowmode:GetSelectedItem() == 2 then
    				LauncherWindowMode = Window.FullScreen
    			else
    				LauncherWindowMode = Window.FullScreen				
    			end			
    		else
    			LauncherWindowMode = Window.FullScreen			
    		end		
    	end
    	
    	local function ProcessEvents(event)					
    		if event.source == LauncherMenu.applyoptions then
    			ApplySettings()
    			ProcessEvents(Event(Event.WidgetAction,LauncherMenu.closeoptions))
    		end
    		if event.source == LauncherMenu.closeoptions then
    			LauncherMenuClosed = true			
    		end		
    	end
    	
    	
    	LoadSettings()
    	ApplyScreenMode()
    	while LauncherWindow:Closed()==false do
    		while EventQueue:Peek() do
    			ProcessEvents(EventQueue:Wait())
    		end
    		if VSyncMode==nil then VSyncMode=true end				
    		LauncherContext:Sync(VSyncMode)
    		if LauncherMenuClosed == true then break end
    	end
    	
    	LauncherWindow:Release()
    end

     

     

    To use it, first add:

    import("Scripts/Launcher.lua")

    to the top of Main.lua.

     

    Next add 

    LauncherMenu()

    After the title line.

     

    Lastly, change:

    window=Window:Create(title,0,0,gfxmode.x,gfxmode.y,windowstyle)

    to 

    window=Window:Create(title,0,0,gfxmode.x,gfxmode.y, LauncherWindowMode)

     

    This is all that needs to be done.

    hCfTXNj.png

     

    In action:

    hsA3Lgd.gif

    • Like 1
    • Thanks 1
    • Upvote 3
  6. I would make sure that the rest of the engine works with utf8 and let lua itself fail with the encoding. 5.3 has utf8 support https://www.lua.org/manual/5.3/manual.html#6.5 but it's not very robust.

    Since it is still early, you do have the option to choose Lua derived language or a completely different language not based on Lua. As distasteful as it may be the API is changing, the scripts will need to be updated and it might be simpler to start over early with something else.

    Who knows.

  7. Yes that is the part that is giving you issues.

    	--if gamemenu:Hidden() then
    		
    		--Update the app timing
    		Time:Update()
    		
    		--Update the world
    		world:Update()
    		
    	--end

    This would keep the game running in the background when you are in a menu. But there is a HUGE catch/problem. Any script that reads input needs to be edited to be made aware that a menu is open or to ignore input. Any script that reads or sets the mouses position or the keyboard or mouses key state will need to be edited. For example,the  fpsplayer script will will move your mouse to the middle of the screen and you will not be able to select anything. So you will need to think of a way to let all scripts know that they are in a menu.

  8. I've spent the last few days creating a simple self contained server browser. It will list all the servers of a specific game, allow the user to select a server and send a callback with the selected info.

    kqr55SK.gif

    Requirements: 

    The script from this topic placed in a file here: Scripts/Functions/eventqueuemanager.lua

    The Script:

     
    
    --[[
    		  Name:	serverBrowser
    		Author:	Einlander
    Date Completed: 2017-8-22
       Description:	A Server Browser for Leadwerks
    	     Notes:	This is a rather simple Server Browser script that allows for listing of servers and selection.
    				-2017-8-24: -Added the ability to directly connect to a ip and port.
    							-Moved the code to put the window into a function and check on server browser creation.
    				-2017-8-25: -Added the abilitiy to automatically resize to fit inside the bounds of the current context
    --]]
    
    
    --TODO: Add manual server connect
    
    import("Scripts/Functions/eventqueuemanager.lua")
    function serverBrowser(gameName,context,x,y,width,height)
    	local self = {}	
    	self.gameName=""
    	local _context
    	local serverBrowser = {}
    	local ServerBrowserClient = Client:Create()
    	local callback = {}
    	local movemode = false
    	local currentWindow
    	
    	
    	--[[
    	Description: Initializes and Draws the GUI
    	Parameters: x as integer
    				y as integer
    				width as integer
    				height as integer
    	Notes: 	None
    	]]
    	
    	local function createUI(x,y,width,height)		
    		x = ((tonumber(x)~= nil) and x or 100)
    		y = ((tonumber(y)~= nil) and y or 100)
    		width = ((tonumber(width)~= nil) and width or 500)
    		height = ((tonumber(height)~= nil) and height or 300)				
    		serverBrowser.gui = GUI:Create(_context)
    		serverBrowser.gui:Hide()
    		serverBrowser.root = serverBrowser.gui:GetBase()				
    		serverBrowser.root:SetLayout(x,y,width,height)
    		serverBrowser.panel = Widget:Panel(0,0,width,height,serverBrowser.root)
    		serverBrowser.closeButton = Widget:Button("X",1,1,19,19,serverBrowser.panel )
    		serverBrowser.closeButton:SetLayout(serverBrowser.panel:GetSize().x-serverBrowser.closeButton:GetSize().x - 10,1,19,19)	-- hides browser when clicked, regardless of results	
    		serverBrowser.moveButton = Widget:Button("+",10,1,19,19,serverBrowser.panel )
    		serverBrowser.titlelabel = Widget:Label("Server Browser",40,5,100,25,serverBrowser.panel)
    		
    		serverBrowser.serveriplabel = Widget:Label("IP/Address:",15,serverBrowser.panel:GetSize().y - 23,100,25,serverBrowser.panel)
    		serverBrowser.serverportlabel = Widget:Label("Port:",290,serverBrowser.panel:GetSize().y - 23,100,25,serverBrowser.panel)
    		serverBrowser.serveripfield = Widget:TextField("",85,serverBrowser.panel:GetSize().y - 30, 200, 25, serverBrowser.panel)		
    		serverBrowser.serverportfield = Widget:TextField("",320,serverBrowser.panel:GetSize().y - 30,80,25,serverBrowser.panel)		
    		serverBrowser.connectButton = Widget:Button("Connect",405,serverBrowser.panel:GetSize().y - 30,55,25,serverBrowser.panel )		
    		serverBrowser.serverList = Widget:ListBox(10,20,serverBrowser.panel:GetSize().x - 20,serverBrowser.panel:GetSize().y - 100,serverBrowser.panel)
    		serverBrowser.refreshButton = Widget:Button("Refresh",10,serverBrowser.panel:GetSize().y - 70,55,25,serverBrowser.panel )
    		serverBrowser.joinButton = Widget:Button("Join",0,0,55,25,serverBrowser.panel )		
    		serverBrowser.joinButton:SetLayout(serverBrowser.panel:GetSize().x-serverBrowser.refreshButton:GetSize().x - 10,serverBrowser.panel:GetSize().y - 70,55,25)				
    		serverBrowser.gui:Show()
    	end
    	
    	
    	--[[
    	Description: Resizes the GUI
    	Parameters: Width as integer
    				Height as integer
    	Notes: none
    	]]
    	
    	function self:SetSize(width,height)				
    		serverBrowser.root:SetLayout(serverBrowser.root:GetPosition().x,serverBrowser.root:GetPosition().y,width,height)
    		serverBrowser.panel:SetLayout(0,0,width,height)				
    		serverBrowser.closeButton:SetLayout(serverBrowser.panel:GetSize().x-serverBrowser.closeButton:GetSize().x - 10,1,19,19)	-- hides browser when clicked, regardless of results
    		serverBrowser.moveButton:SetLayout(10,1,19,19)
    		serverBrowser.titlelabel:SetLayout(40,5,100,25)	
    		serverBrowser.serveriplabel:SetLayout(15,serverBrowser.panel:GetSize().y - 23,100,25)
    		serverBrowser.serverportlabel:SetLayout(290,serverBrowser.panel:GetSize().y - 23,100,25)
    		serverBrowser.serveripfield:SetLayout(85,serverBrowser.panel:GetSize().y - 30, 200, 25)
    		serverBrowser.serverportfield:SetLayout(320,serverBrowser.panel:GetSize().y - 30,80,25)
    		serverBrowser.connectButton:SetLayout(405,serverBrowser.panel:GetSize().y - 30,55,25)
    		serverBrowser.serverList:SetLayout(10,20,serverBrowser.panel:GetSize().x - 20,serverBrowser.panel:GetSize().y - 100)
    		serverBrowser.refreshButton:SetLayout(10,serverBrowser.panel:GetSize().y - 70,55,25)		
    		serverBrowser.joinButton:SetLayout(serverBrowser.panel:GetSize().x-serverBrowser.refreshButton:GetSize().x - 10,serverBrowser.panel:GetSize().y - 70,55,25)						
    	end
    	
    	
    	
    	--[[
    	Description: Returns the server browsers size
    	Parameters: ScaledCoords as boolean
    	Notes: scaledCoords: if set to false logical coordinates will be returned, otherwise scaled coordinates will be returned.
    	]]
    	
    	function self:GetSize(ScaledCoords)
    		return serverBrowser.root:GetSize(ScaledCoords == true and true or false )
    	end
    	
    	--[[
    	Description: Shows UI
    	Parameters: none
    	Notes: none
    	]]
    	
    	function self:Show()
    		serverBrowser.gui:Show()
    		serverBrowser.root:Enable()
    		self.context:GetWindow():ShowMouse()
    	end
    	
    	
    	--[[
    	Description: Hides UI
    	Parameters: none
    	Notes: none
    	]]
    	function self:Hide()
    		serverBrowser.gui:Hide()
    		serverBrowser.root:Disable()		
    	end
    	
    	
    	--[[
    	Description: Returns if UI is hidden or not
    	Parameters: none
    	Notes: none
    	]]
    	function self:Hidden()		
    		return serverBrowser.gui:Hidden()		
    	end
    	
    	
    	--[[
    	Description: Sets a external function to call when server is selected or window is closed.
    	Parameters: callback as function
    	Notes: 
    				--self:SetCallback is an overloaded function
    				--self:SetCallback(callback) simple callback, used on functions not attached to an entity
    				--self:SetCallback(self, callback) Used when adding from a script attached to an entity (calling from and to any function that starts with Script: )
    				
    				self:SetCallback requires the callback function to have these 3 parameters: (ip,port,close)
    				Ip is the server address as a string
    				port is unused as of now since the leadwerks master server does not return it and also the remoteserver class has no property for it
    				close is a boolean that retuns true if the serverbrowser is closed
    				if it is closed it will return (nil,nil,true)
    				if a server is chosen and connect is clicked, it will return ("address",nil,true) it will also close the window. Take care of how the callback handles the data
    					(recursion is possible if not thought out properly)
    				
    	]]	
    	
    	function self:SetCallback(_callback)		
    		--if (#args==1) then		
    			if type(_callback) ~= "function" then return false end
    			callback.functionValue = _callback
    		--elseif (#args==2) then
    			--if type(args[2]) ~= "function" then return false end
    			--callback.selfValue = args[1]
    			--callback.functionValue = args[2]			
    		--else
    			--return false
    		--end	
    		
    	end
    	
    
    	--[[
    	Description: Removes the callback
    	Parameters: none
    	Notes: none
    	]]
    	function self:ClearCallback()
    		--callback.selfValue = nil
    		callback.functionValue = nil
    	end
    	
    	--[[
    	Description: Moves the serverbrowser back into the window
    	Parameters: non
    	Notes: none
    	]]
    	local function FitInScreen()
    		-- resize to fit inside current context
    		if serverBrowser.root:GetSize().x > _context:GetWidth() then
    			self:SetSize(_context:GetWidth(), serverBrowser.root:GetSize().y)
    		end
    		if serverBrowser.root:GetSize().y > _context:GetHeight() then
    			self:SetSize(serverBrowser.root:GetSize().x, _context:GetHeight() )
    		end
    		-- move it into view
    		if serverBrowser.root:GetPosition().x + serverBrowser.root:GetSize().x > _context:GetWidth() then
    			serverBrowser.root:SetLayout(serverBrowser.root:GetPosition().x - (  (serverBrowser.root:GetPosition().x + serverBrowser.root:GetSize().x)  - _context:GetWidth()) ,serverBrowser.root:GetPosition().y ,serverBrowser.root:GetSize().x,serverBrowser.root:GetSize().y)
    		end
    		if serverBrowser.root:GetPosition().x < 0 then
    			serverBrowser.root:SetLayout(0,serverBrowser.root:GetPosition().y ,serverBrowser.root:GetSize().x,serverBrowser.root:GetSize().y)
    		end
    		
    		if serverBrowser.root:GetPosition().y + serverBrowser.root:GetSize().y > _context:GetHeight() then
    			serverBrowser.root:SetLayout(serverBrowser.root:GetPosition().x  ,serverBrowser.root:GetPosition().y - (  (serverBrowser.root:GetPosition().y + serverBrowser.root:GetSize().y)  - _context:GetHeight()),serverBrowser.root:GetSize().x,serverBrowser.root:GetSize().y)
    		end
    		if serverBrowser.root:GetPosition().y < 0 then
    			serverBrowser.root:SetLayout(serverBrowser.root:GetPosition().x, 0 ,serverBrowser.root:GetSize().x,serverBrowser.root:GetSize().y)
    		end											
    	end
    	
    	--[[
    	Description: Processes all the events recived
    	Parameters: event as Event
    	Notes: none
    	]]
    	local function ProcessEvent(event)
    		if event.id == Event.WidgetSelect then											
    		elseif event.id == Event.WidgetAction then		
    			if movemode == true and (event.source == serverBrowser.gui) then 			
    				_context:SetColor(0,0,0,0) -- need to clear alpha!!! otherwise you wont see the 3d
    				serverBrowser.gui:Clear()
    				serverBrowser.root:SetLayout(currentWindow:GetMousePosition().x - serverBrowser.moveButton:GetSize().x , currentWindow:GetMousePosition().y - (serverBrowser.moveButton:GetSize().y/2) ,serverBrowser.root:GetSize().x,serverBrowser.root:GetSize().y)				
    				EventQueue:Emit(Event.WidgetAction,serverBrowser.gui)				
    				if currentWindow:MouseHit(Key.LButton) then
    					-- make sure it doesnt escape the screen					
    					movemode = false
    					FitInScreen()
    					_context:SetColor(0,0,0,0)
    					serverBrowser.gui:Clear()					
    					serverBrowser.root:Enable()
    				end										
    				serverBrowser.panel:Redraw()
    			return true
    			end	
    			
    			if event.source == serverBrowser.moveButton then				
    				movemode = true				
    				currentWindow = Window:GetCurrent()				
    				EventQueue:Emit(Event.WidgetAction,serverBrowser.gui)
    				_context:SetColor(0,0,0,0)
    				serverBrowser.gui:Clear()
    				serverBrowser.root:Disable()
    				currentWindow:FlushMouse()
    				return true
    			end
    			if event.source == serverBrowser.closeButton then				
    				serverBrowser.root:Disable()
    				serverBrowser.gui:Hide()				
    				--System:Print(self.gameName .. ":: Close button")
    				if callback.functionValue ~= nil then
    					callback.functionValue(nil,nil,true)
    				end
    				self:Release()
    				return true
    			end		
    			
    			if event.source == serverBrowser.connectButton then
    				local serverip = ((string.len(serverBrowser.serveripfield:GetText())>0)	and serverBrowser.serveripfield:GetText() or nil)
    				local serverport = ((tonumber(serverBrowser.serverportfield:GetText()) ~= nil) and tonumber(serverBrowser.serverportfield:GetText())	or nil)
    				if callback.functionValue ~= nil then						
    					local cb = callback.functionValue
    					-- release everything to minimize mem use in case of consecutive server hopping.abs
    					self:Release()
    					cb(serverip,serverport,true)-- should it close when they chose a server?						
    					return true
    				end
    				return false
    			end
    			
    			if event.source == serverBrowser.joinButton then	
    				--System:Print(self.gameName .. ":: Connect button")
    				if serverBrowser.serverList:GetSelectedItem() > -1 then					
    					local servercount = ServerBrowserClient:CountServers(self.gameName) -- has a super high chance of screwing up when clicked, i mean REALLY HIGH
    					local remoteServerData = ServerBrowserClient:GetServer(serverBrowser.serverList:GetSelectedItem())
    					--System:Print("Server Name::" .. remoteServerData.address .."#### Description" .. remoteServerData.description)
    					serverBrowser.root:Disable()
    					serverBrowser.gui:Hide()
    					if callback.functionValue ~= nil then
    						local cb = callback.functionValue
    						local addy = remoteServerData.address
    						-- there is no port :/
    						remoteServerData:Release() -- release everything to minimize mem use in case of consecutive server hopping.
    						self:Release()
    						cb(addy,nil,true)-- should it close when they chose a server?						
    						return true
    					end					
    				end
    				return false
    			end	
    			if event.source == serverBrowser.refreshButton then				
    				--System:Print(self.gameName .. ":: Refresh button")								
    				self:PopulateServers(self.gameName)
    				return true
    			end
    		end
    		return true
    	end
    	
    	
    	--[[
    	Description: Hides UI
    	Parameters: none
    	Notes: none
    	]]
    	function self:Update(event)
    		if serverBrowser == nil then return false end
    		if serverBrowser.gui:Hidden() then return false end				
    		if event:GetClassName() == "Event" then					
    			ProcessEvent(event)
    		end
    		return true		
    	end
    	
    	--[[
    	Description: Adds Servers to the server list
    	Parameters: gameName as string
    	Notes: Gamename is the exact name of the game the server registered
    	]]
    	
    	function self:PopulateServers(gameName)
    		if gameName == nil then return end		
    		local servercount = ServerBrowserClient:CountServers(gameName)
    		--System:Print("Server Count::" .. tostring(servercount))
    		serverBrowser.serverList:ClearItems()
    		serverBrowser.serverList:SelectItem(-1)
    		for i=0, servercount-1 do
    			remoteServerData = ServerBrowserClient:GetServer(i)
    		--	System:Print("Server Name::" .. remoteServerData.address .."#### Description" .. remoteServerData.description)
    			serverBrowser.serverList:AddItem("["..remoteServerData.address.."]  ["..remoteServerData.description.."]")
    		end		
    	end
    	
    	
    	--[[
    	Description: Initializes Class
    	Parameters: gameName as string
    				context as Context
    				x as integer
    				y as y as integer
    				width as integer
    				height as integer
    	Notes: Gamename is the exact name of the game the server registered
    	]]
    	local function init(gameName,context,x,y,width,height)
    		-- check for the context
    		_context = context		
    		createUI(x,y,width,height)
    		FitInScreen()
    		self.gameName = gameName		
    		self:PopulateServers(self.gameName)		
    		EventQueueManager:AddListener(self.Update)		
    	end	
    	
    	
    	--[[
    	Description: Unloads the class and all it's componentes
    	Parameters: none
    	Notes: none
    	]]
    	function self:Release()
    		for item in pairs(self) do
    			if (type(self[item]) == "function") or (type(self[item]) == "userdata") then
    				self[item] = nil
    			end
    		end					
    		self.gameName = nil	
    		
    		-- The order is important!
    		serverBrowser.root:Disable()
    		serverBrowser.gui:Hide()
    		serverBrowser.closeButton:Release()
    		serverBrowser.titlelabel:Release()		
    		serverBrowser.serverList:Release()
    		serverBrowser.joinButton:Release()		
    		serverBrowser.refreshButton:Release()
    		serverBrowser.connectButton:Release()
    		serverBrowser.moveButton:Release()
    		serverBrowser.serveriplabel:Release()
    		serverBrowser.serverportlabel:Release()
    		serverBrowser.serveripfield:Release()
    		serverBrowser.serverportfield:Release()		
    		serverBrowser.panel:Release()
    		serverBrowser.root:Release()
    		serverBrowser.gui = nil
    		serverBrowser=nil
    		ServerBrowserClient:Release()
    		_context = nil
    		callback = nil		
    		movemode = nil
    		self.Show = nil
    		self = nil		
    	end
    	
    	
    	init(gameName,context,x,y,width,height)
    	
    	return self
    end

     

    A simple example:

    It will create a server and open a server browser window. + Starts the move mode, click to exit it. X closes the window.

    import("Scripts/Functions/eventqueuemanager.lua")
    import("Scripts/serverbrowser.lua")
    local window = Window:Create()
    local context = Context:Create(window)
    local server = Server:Create()
    System:Print("Server1 publish::" .. tostring(server:Publish("Example Temp Test Server", "Testing population of server list from masterserver ")))
    server:Release()
    
    function test(ip,port,close) -- callback function
    	System:Print("Callback")
    	System:Print(ip)	
    	System:Print(tostring((close == true) and "close" or ""))
    end
    
    local serverbrowser = serverBrowser("Example Temp Test Server",context,0,0) -- create the serverbrowser
    serverbrowser:SetCallback(test) -- set callback
    
    -- do stuff
    while true do
    	if window:Closed() then return end
    	if window:KeyHit(Key.Escape) then return end	
    	Time:Update()
    	context:SetColor(0,0,0,0) -- need to clear alpha!! or the gui will stay on screen!!
    	context:Clear()	
    	EventQueueManager:Update()					
    	context:Sync()
    end
    serverbrowser:ClearCallback() -- remove callback
    serverbrowser:Release() -- release everything

    The server browser will obey the limits of your window. If any part of it is not on screen, it will be pushed back onto it.

    Edits:

    -2017-8-24: -Added the ability to directly connect to a ip and port.
                        -Moved the code to put the window into a function and check on server browser creation.

    -2017-8-25: -Added the abilitiy to automatically resize to fit inside the bounds of the current context

  9. [I had text here but in the edit it dissapeared :(]

    I found that there can only be one instance of the EventQueue. This meant that all the widget events need to be handled in a single location leading to possible complications in code and lowering the possibility to dynamic things. This script allows the developer to subscribe to an eventqueue manager and get their event safely, without usurping all gui controls.

    The script will automatically create an EventQueueManager variable that all other scripts can expect.

    To use it from a script not attached to an entity use:

    EventQueueManager:AddListener(Update)  -- a simple function

     

    On a script attached to an entity or a lua based class use:

    EventQueueManager:AddListener(serverbrowser.Update)  --  convert : into .

     

    Place the script into a file at: Scripts/Functions/eventqueuemanager.lua

    --[[
    		  Name:	EventQueueManager
    		Author:	Einlander
    Date Completed: 2017-8-20
       Description:	An EventQueue manager
    	     Notes:	This script puts all the eventqueue proccessing in one location, allowing other scripts to manage themselves
    				and not take control of the eventqueue.
    				THIS SCRIPT WILL AUTO LOAD AS A GLOBAL
    				THIS SCRIPT WILL AUTO LOAD AS A GLOBAL
    				THIS SCRIPT WILL AUTO LOAD AS A GLOBAL
    				THIS SCRIPT WILL AUTO LOAD AS A GLOBAL
    	   Updates: 2017-8-22
    					-Will no longer overwrite EventQueueManager variable. This will lead to unintended behavior
    					-No longer loops through the evenqueue. It is possible to have infinite Loops With previous behavior
    --]]
    
    EventQueueManager = {}
    function EventQueueManager:Create()
    	local self = {}
    	local callbackList = {}
    	
    	--self:AddListener is an overloaded function
    	--self:AddListener(callback) simple callback, used on functions not attached to an entity
    	--self:AddListener(self, callback) Used when adding from a script attached to an entity (calling from and to any function that starts with Script: )
    	function self:AddListener(...)
    		local args = {...}
    		local _callbackself 
    		local _callback 
    		if (#args==1) then		
    			_callback = args[1]		
    		elseif (#args==2) then				
    			_callbackself = args[1]
    			_callback = args[2]
    		else
    			return false
    		end		
    		for index,callback in ipairs(callbackList) do
    			if callback == _callback then 
    			--System:Print("Match Found")
    			return false 
    			end
    		end
    		table.insert(callbackList,{callback = _callback,self = _callbackself})
    		return true
    	end
    	function self:RemoveListener(_callback) -- removes the callback
    		for index,callbackitem in ipairs(callbackList) do
    			if callbackitem.callback == _callback then				
    				table.remove(callbackList,index)				
    				return true
    			end
    		end
    		return false
    	end
    	function self:Update() -- processes eventqueue and sends the event info to all callbacks
    		if EventQueue:Peek() then -- will no longer loop through the entire event queue. It can lead to infinite loops.
    			local event = EventQueue:Wait()	
    			for index,callbackitem in pairs(callbackList) do
    				if callbackitem.self == nil then 					
    					callbackitem:callback(event)
    				else
    					callbackitem.callback(callbackitem.self,event)
    				end
    			end
    		end
    	end
    	return self
    end
    
    
    if EventQueueManager ~= nil then -- Will no longer Overwrite variable but will allow for unexpected behavior
    	EventQueueManager = EventQueueManager:Create()
    end

    8-22-2017 -- updated script

    • Upvote 1
  10. I am trying to have a generic gui class and I realized that there can be only 1 EventQueue. This means that all widgets must be managed from a single area. This means that I can't create a gui class that handles its own events without using some creative methods that have some serious edge cases. I would like to specify my own function/callback/eventqueue to call for each widget item. It would allow people to create safe, shareable scripts.

    I would like to create a widget and pass it a local eventqueue such as this one 

    and handle all the events locally.

  11. I discovered that there can only be one eventqueue in leadwerks. I wanted local eventqueue instances, so I created a lua based version of EventQueue called EventQueueEx

     

    It is initialized as such:

    MyQueue = EventQueueEx:Create()

    It is used EXACTLY the same as the Leadwerks version.

     
    
    --[[
    		  Name:	EventQueEX
    		Author:	Einlander
    Date Completed: 
       Description:	A lua Implementation of the EventQueue class
    	     Notes:	This script was mainly created a developer can have self contained EventQueue
    				and not have to restructure your program to have exactly 1 EventQueue processing routine.
    				To be used exactly as the built-in EventQueue.
    --]]
    EventQueueEx = {}
    
    function EventQueueEx:Create() -- Create an instance of EventQueueEx
    	local self = {}
    	local queue = {}
    	
    	function self:Peek() -- Return true if table is not empty
    		if #queue > 0 then return true end
    		return false
    	end
    	function self:Wait() -- get top entry and remove from table		
    		if #queue < 1 then return nil end		
    		local eventItem = Event(queue[1].id, queue[1].source, queue[1].data, iVec2(queue[1].x, queue[1].y) , iVec2(queue[1].width, queue[1].height), queue[1].extra)
    		-- we remove and not nil it to keep a contigous array with no holes in it.
    		-- This allows for the #table shorcut to work without manually looping through the whole table
    		table.remove(queue,1) 		
    		return eventItem
    	end
    	function self:Flush() -- Clear Queue
    		queue = {}
    	end
    	function self:Emit(id, source, data, x,y,width,height,extra) -- Add Event to Queue
    		-- simple input checks and sanitation				
    		Debug:Assert(id ~= nil, "id is ["..type(id).."], Number or Event expected." )	
    		if id:GetClassName() == "Event"	then 
    			-- passed a event object
    			table.insert(queue,{id = id.id, source = id.source, data = id.data, x = id.position.x, y = id.position.y, width = id.size.x, height = id.size.y, extra = extra})			
    		else
    			-- simple input checks and sanitation
    			-- will set defaults if value is missing
    			Debug:Assert(type(id) == "number", "id is ["..type(id).."], Number Expected." )				
    			local source = source
    			local data = (type(data) == "number") and data or 0		
    			local x = (type(x) == "number") and x or 0
    			local y = (type(y) == "number") and y or 0
    			local width = (type(width) == "number") and width or 0
    			local height = (type(height) == "number") and height or 0
    			local extra = extra		
    			table.insert(queue,{id = id, source = source, data = data, x = x, y = y, width = width, height = height, extra = extra})
    		end
    		
    	end
    	function self:Release() -- allow class to go out of scope
    		queue = nil
    		self = nil
    	end
    	return self
    end

     

  12. The server list seems to fail when attempting to register multiple servers from the same server but different port.

     

    Also, it will fail to register if the name is just one word.

     

    Example:

    server = Server:Create()
    System:Print("Server1 publish::" .. tostring(server:Publish("Einlanders server stub", "Testing population of server list from masterserver ")))
    
    server2 = Server:Create(27015)
    System:Print("Server2 publish::" .. tostring(server2:Publish("Einlanders server stub", "Testing population of server list from masterserver 2")))
    
    client = Client:Create()
    local servercount = client:CountServers("Einlanders server stub")
    System:Print("Server Count::" .. tostring(servercount))
    for i=0, servercount-1 do
    	remoteServerData = client:GetServer(i)
    	System:Print("Server Name::" .. remoteServerData.address .."#### Description" .. remoteServerData.description)	
    end

     

    The Output:

    Server1 publish::true
    ERROR
    
    Server2 publish::false
    Server Count::1
    Server Name::xxx.xxx.xxx.xxx#### DescriptionTesting pupulation of server list from masterserver 

     

×
×
  • Create New...