GUI introduction

From PioneerWiki
Revision as of 07:08, 28 May 2021 by Impaktor (talk | contribs) (First edit with some info on how to get started with UI programming in pioneer)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Background history

"OldUI" UI Started as a 1:1 clone of Frontier, in 2008, implemented in C++.

"NewUI" was meant to move UI from C++ to Lua, so we don't need to re-compile the game for every change, and allo players to easily modify the game.

"PiGUI" was the second attempt at moving UI from OldUI and NewUI, uses the third party Imgui library, so we get a lot for free, but downside is it's not custom made for us.

Pioneer has at times 3 different UI systems, in the transitioning phase to PiGUI. Now (2021-05) NewUI is completely replaced by PiGUI, but some parts of OldUI still linger (F6,F7,F8 screens).


Getting started with UI

Some pointers on how to get started with PiGUI

Imgui

Start with downloading and compiling the stand alone Imgui C++ program. Launch the demo app, to see the possibilities it offers. There you can find all features in imgui.

Search the C++ source code for some string/sentence you saw in the demo ap, e.g. if you found a specific table interesting, search the table text in the source, to find the spot in the C++ source. Then you see the name of the function that makes the table.

Then search for the same name in pioneer's lua code. E.g. "git grep -i <function name>"

PiGUI

code example

Below is a snippet that if saved to a lua file placed anywhere in data/modules/ will draw a window on the WorldView screen.

-- Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

--[[
	data/pigui/modules/add_crime.lua

	Written for @impaktor as a tutorial on how to get started with pigui by
	@sturnclaw, extended by @impaktor
--]]


local Game = require 'Game'

-- pigui is traditionally imported as 'ui' for simplicity.
local ui = require 'pigui'

-- gameView is needed to dispatch to our Hello World window
local gameView = require 'pigui.views.game'

-- we want all displayed text to be localized
local lui = require 'Lang'.GetResource('ui-core')

-- ui.WindowFlags is an acceleration structure to allow composing window flags
-- once and reusing them with each call.
local window_flags = ui.WindowFlags {
	-- We don't want to be able to collapse the window.
	-- "NoCollapse"
}

local amount = 1000

local Character = require "Character"

-- Register this window as a Game-view module. It will be displayed when the
-- player is in the World View.
-- registerModule takes two parameters, the unique key of the module, and the
-- module descriptor table.
gameView.registerModule("Small example", {

	-- Pretty self explanatory, if this is true, draw() is called when the
	-- ship is in hyperspace as well as in normal space.
	ShowInHyperspace = true,

	-- Called once per frame while the module is active. The function is passed
	-- the module object (this table) and the frame delta time
	draw = function(self, deltaTime)
		-- ui.window takes three parameters: the window title, the window flags,
		-- and a function containing the body of the window.

		-- the window title is an IMGUI string ID - two windows cannot share
		-- the same ID at the same stack position. To work around this,
		-- everything after ## is not part of the title, but instead used to
		-- make the window ID unique.
		ui.window("Debug!##id43", window_flags, function()
			ui.text("State: " .. Game.player:GetFlightState())

			if (ui.beginTabBar("mytabbar")) then
				if ui.beginTabItem("squares") then
					ui.text("test1")
					ui.endTabItem()
				end
				if ui.beginTabItem("BALLS!") then
					ui.text("test2")
					ui.endTabItem()
				end
				if ui.beginTabItem("Triangle") then
					ui.text("test3")
					ui.text("some more text")
					ui.endTabItem()
				end
				ui.endTabBar()
			end

			-- Give player mone if pressing the button
			if ui.button("Give money", Vector2(100, 0)) then
				Game.player:AddMoney(amount)
			end

			-- draws a horizontal line
			ui.separator()

			-- Reputation & kills
			if ui.collapsingHeader("Reputation & kills", {}) then
				Character.persistent.player.reputation = ui.sliderInt("Reputation", Character.persistent.player.reputation, 0, 512)
				ui.sameLine()
				ui.text(Character.persistent.player:GetReputationRating())

				Character.persistent.player.killcount = ui.sliderInt("Kills", Character.persistent.player.killcount, 0, 6000)
				ui.sameLine()
				ui.text(Character.persistent.player:GetCombatRating())
			end

		end)
	end
})