Compare commits
16 Commits
2e44d9302e
...
6092733940
Author | SHA1 | Date |
---|---|---|
|
6092733940 | |
|
08386499a9 | |
|
8e54a3be06 | |
|
9d719273fe | |
|
8e31d169ee | |
|
2310827da0 | |
|
f6ebcbe966 | |
|
ac7e98248e | |
|
af5d52cfd9 | |
|
b754aeed2a | |
|
2ea32811f7 | |
|
ca3fde811f | |
|
053ff32ef1 | |
|
7b3a69a385 | |
|
e584780ce9 | |
|
a1745867ff |
|
@ -1,3 +1,10 @@
|
|||
April 2020
|
||||
* New Features
|
||||
* Move the System Map to PiGUI (#4821)
|
||||
|
||||
* Internal Changes
|
||||
* Refactor the ModelViewer to use PiGui (#4849)
|
||||
|
||||
March 2020
|
||||
* New Features
|
||||
* Stars that are brighter are now bigger and have a brighter colour on the Starfield (#4833)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
viewBox="0 0 3628.3465 3628.3464"
|
||||
id="svg4446"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="icons.svg">
|
||||
<defs
|
||||
id="defs4448">
|
||||
|
@ -881,16 +881,16 @@
|
|||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.1767767"
|
||||
inkscape:cx="1429.7092"
|
||||
inkscape:cy="1859.5164"
|
||||
inkscape:zoom="0.25000001"
|
||||
inkscape:cx="2379.8651"
|
||||
inkscape:cy="2002.5917"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1850"
|
||||
inkscape:window-height="1057"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-width="1853"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="67"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
|
@ -943,7 +943,7 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
@ -9014,5 +9014,29 @@
|
|||
id="rect7847"
|
||||
style="fill:none;stroke:none;stroke-width:10.69061661;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:10.69061666, 21.38123329;stroke-dashoffset:0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="rotate_view"
|
||||
transform="translate(-4762.2048,1133.8583)"
|
||||
id="g2225">
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:21.25984192;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.5151515"
|
||||
id="rect2223"
|
||||
width="226.77151"
|
||||
height="226.77162"
|
||||
x="8163.7798"
|
||||
y="-2575.9844" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:14.17322826;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 8203.6641,-2505.9607 -28.4385,-0.4182 49.7674,65.2412 56.877,-63.5684 -35.9663,-0.8364 c 0,0 8.0177,-38.3618 43.3419,-41.9946 28.4386,4.1822 18.5537,47.4314 18.5537,47.4314 0,0 7.1096,-5.4369 17.9831,-5.0187 10.8736,0.4183 15.8922,11.9192 15.8922,11.9192 0,0 4.182,-23.2109 -4.1822,-37.8484 -8.3642,-14.6374 -28.4385,-31.7841 -53.5313,-30.5295 -25.0928,1.2547 -44.3307,4.1821 -62.3138,23.8382 -14.6375,18.8196 -17.9832,31.7842 -17.9832,31.7842 z"
|
||||
id="path2227"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:14.17322826;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 8234.8718,-2421.3714 50.2389,63.6822 0.3823,-35.7724 c 40.2329,6.163 71.2869,1.8276 85.669,-13.457 14.3821,-15.2847 15.0115,-40.8195 5.6423,-57.6389 -9.3693,-16.8194 -32.0947,-21.798 -32.0947,-21.798 0,0 6.1707,10.9709 6.3568,20.8718 0.1827,9.7237 -10.2431,16.3492 -10.2431,16.3492 0,0 17.5122,1.9115 20.8358,3.4682 3.3236,1.5567 5.762,1.9039 -0.5228,7.4519 -6.2848,5.548 -41.2332,12.4421 -74.9406,2.6361 l 0.8277,-38.7801 z"
|
||||
id="path2231"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccczzcsczzccc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 717 KiB After Width: | Height: | Size: 719 KiB |
|
@ -167,6 +167,10 @@
|
|||
"description": "",
|
||||
"message": "Cargo scoop attempted. Not enough room in cargo hold."
|
||||
},
|
||||
"CENTER": {
|
||||
"description": "",
|
||||
"message": "Center"
|
||||
},
|
||||
"CH4_ATMOSPHERE": {
|
||||
"description": "",
|
||||
"message": "\" Methane atmosphere\""
|
||||
|
@ -1091,6 +1095,10 @@
|
|||
"description": "",
|
||||
"message": "Orbital starport"
|
||||
},
|
||||
"ORBIT_PLANNER": {
|
||||
"description": "",
|
||||
"message": "Orbit planner"
|
||||
},
|
||||
"OUTDOOR_AGRICULTURAL_WORLD": {
|
||||
"description": "",
|
||||
"message": "Outdoor agricultural world."
|
||||
|
@ -1323,6 +1331,14 @@
|
|||
"description": "",
|
||||
"message": "Semi-major axis"
|
||||
},
|
||||
"SET_AS_COMBAT_TARGET": {
|
||||
"description": "",
|
||||
"message": "Set as combat target"
|
||||
},
|
||||
"SET_AS_TARGET": {
|
||||
"description": "",
|
||||
"message": "Set as navigation target"
|
||||
},
|
||||
"SET_HYPERSPACE_DESTINATION_TO": {
|
||||
"description": "",
|
||||
"message": "Set hyperspace destination to %system"
|
||||
|
|
|
@ -263,6 +263,10 @@
|
|||
"description": "Player combat rating",
|
||||
"message": "Deadly"
|
||||
},
|
||||
"DECREASE": {
|
||||
"description": "Decrease something.",
|
||||
"message": "Decrease"
|
||||
},
|
||||
"DELTA_V": {
|
||||
"description": "",
|
||||
"message": "Delta-v"
|
||||
|
@ -963,6 +967,10 @@
|
|||
"description": "For player reputation",
|
||||
"message": "Incompetent"
|
||||
},
|
||||
"INCREASE": {
|
||||
"description": "Increase something.",
|
||||
"message": "Increase"
|
||||
},
|
||||
"INEXPERIENCED": {
|
||||
"description": "For player reputation",
|
||||
"message": "Inexperienced"
|
||||
|
@ -1531,6 +1539,10 @@
|
|||
"description": "",
|
||||
"message": "Reward"
|
||||
},
|
||||
"ROTATE_VIEW": {
|
||||
"description": "",
|
||||
"message": "Rotate view"
|
||||
},
|
||||
"ROUTE_INFO": {
|
||||
"description": "For hyperjump planner",
|
||||
"message": "Route Info"
|
||||
|
@ -1627,6 +1639,10 @@
|
|||
"description": "",
|
||||
"message": "Ship Repairs"
|
||||
},
|
||||
"SHIP_TYPE": {
|
||||
"description": "",
|
||||
"message": "Ship Type"
|
||||
},
|
||||
"SHIP_VIEWING_WAS_SOLD": {
|
||||
"description": "",
|
||||
"message": "The ship you were viewing has been sold"
|
||||
|
|
|
@ -0,0 +1,516 @@
|
|||
local Game = require 'Game'
|
||||
local Engine = require 'Engine'
|
||||
local Event = require 'Event'
|
||||
local Lang = require 'Lang'
|
||||
local ui = require 'pigui'
|
||||
local Format = require 'Format'
|
||||
local Input = require 'Input'
|
||||
|
||||
local Vector2 = _G.Vector2
|
||||
local lc = Lang.GetResource("core")
|
||||
local luc = Lang.GetResource("ui-core")
|
||||
|
||||
local player = nil
|
||||
local colors = ui.theme.colors
|
||||
local icons = ui.theme.icons
|
||||
|
||||
local systemView
|
||||
|
||||
local mainButtonSize = ui.rescaleUI(Vector2(32,32), Vector2(1600, 900))
|
||||
local mainButtonFramePadding = 3
|
||||
local itemSpacing = Vector2(8, 4) -- couldn't get default from ui
|
||||
local indicatorSize = Vector2(30 , 30)
|
||||
|
||||
local selectedObject -- object, centered in SystemView
|
||||
|
||||
local pionillium = ui.fonts.pionillium
|
||||
local ASTEROID_RADIUS = 1500000 -- rocky planets smaller than this (in meters) are considered an asteroid, not a planet
|
||||
|
||||
--load enums Projectable::types and Projectable::bases in one table "Projectable"
|
||||
local Projectable = {}
|
||||
for _, key in pairs(Constants.ProjectableTypes) do Projectable[key] = Engine.GetEnumValue("ProjectableTypes", key) end
|
||||
for _, key in pairs(Constants.ProjectableBases) do Projectable[key] = Engine.GetEnumValue("ProjectableBases", key) end
|
||||
|
||||
local svColor = {
|
||||
BUTTON_BACK = colors.buttonBlue,
|
||||
BUTTON_INK = colors.white,
|
||||
COMBAT_TARGET = colors.combatTarget,
|
||||
GRID = Color(25,25,25),
|
||||
LAGRANGE = Color(0,214,226),
|
||||
NAV_TARGET = colors.navTarget,
|
||||
OBJECT = colors.frame,
|
||||
PLANNER = Color(0,0,255),
|
||||
PLANNER_ORBIT = Color(0,0,255),
|
||||
PLAYER = Color(255,0,0),
|
||||
PLAYER_ORBIT = Color(255,0,0),
|
||||
SELECTED_SHIP_ORBIT = Color(0,186,255),
|
||||
SHIP = colors.frame,
|
||||
SHIP_ORBIT = Color(0,0,155),
|
||||
SYSTEMBODY = Color(109,109,134),
|
||||
SYSTEMBODY_ICON = colors.frame,
|
||||
SYSTEMBODY_ORBIT = Color(0,155,0),
|
||||
SYSTEMNAME_BACK = colors.transparent,
|
||||
WINDOW_BACK = colors.lightBlackBackground,
|
||||
UNKNOWN = Color(255,0,255)
|
||||
}
|
||||
|
||||
local onGameStart = function ()
|
||||
--connect to class SystemView
|
||||
systemView = Game.systemView
|
||||
--export several colors to class SystemView (only those which mentioned in the enum SystemViewColorIndex)
|
||||
for _, key in pairs(Constants.SystemViewColorIndex) do
|
||||
systemView:SetColor(key, svColor[key])
|
||||
end
|
||||
end
|
||||
|
||||
local function showDvLine(leftIcon, resetIcon, rightIcon, key, Formatter, leftTooltip, resetTooltip, rightTooltip)
|
||||
local wheel = function()
|
||||
if ui.isItemHovered() then
|
||||
local w = ui.getMouseWheel()
|
||||
if w ~= 0 then
|
||||
systemView:TransferPlannerAdd(key, w * 10)
|
||||
end
|
||||
end
|
||||
end
|
||||
local press = ui.coloredSelectedIconButton(leftIcon, mainButtonSize, false, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, leftTooltip)
|
||||
if press or (key ~= "factor" and ui.isItemActive()) then
|
||||
systemView:TransferPlannerAdd(key, -10)
|
||||
end
|
||||
wheel()
|
||||
ui.sameLine()
|
||||
if ui.coloredSelectedIconButton(resetIcon, mainButtonSize, false, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, resetTooltip) then
|
||||
systemView:TransferPlannerReset(key)
|
||||
end
|
||||
wheel()
|
||||
ui.sameLine()
|
||||
press = ui.coloredSelectedIconButton(rightIcon, mainButtonSize, false, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, rightTooltip)
|
||||
if press or (key ~= "factor" and ui.isItemActive()) then
|
||||
systemView:TransferPlannerAdd(key, 10)
|
||||
end
|
||||
wheel()
|
||||
ui.sameLine()
|
||||
local speed, speed_unit = Formatter(systemView:TransferPlannerGet(key))
|
||||
ui.text(speed .. " " .. speed_unit)
|
||||
return 0
|
||||
end
|
||||
|
||||
local time_selected_button_icon = icons.time_center
|
||||
|
||||
local function timeButton(icon, tooltip, factor)
|
||||
if ui.coloredSelectedIconButton(icon, mainButtonSize, false, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, tooltip) then
|
||||
time_selected_button_icon = icon
|
||||
end
|
||||
local active = ui.isItemActive()
|
||||
if active then
|
||||
systemView:AccelerateTime(factor)
|
||||
end
|
||||
ui.sameLine()
|
||||
return active
|
||||
end
|
||||
|
||||
local function loop3items(a, b, c) return { [a] = b, [b] = c, [c] = a } end
|
||||
|
||||
local ship_drawing = "SHIPS_OFF"
|
||||
local show_lagrange = "LAG_OFF"
|
||||
local show_grid = "GRID_OFF"
|
||||
local nextShipDrawings = loop3items("SHIPS_OFF", "SHIPS_ON", "SHIPS_ORBITS")
|
||||
local nextShowLagrange = loop3items("LAG_OFF", "LAG_ICON", "LAG_ICONTEXT")
|
||||
local nextShowGrid = loop3items("GRID_OFF", "GRID_ON", "GRID_AND_LEGS")
|
||||
|
||||
local function calcWindowWidth(buttons)
|
||||
return (mainButtonSize.y + mainButtonFramePadding * 2) * buttons
|
||||
+ itemSpacing.x * (buttons + 1)
|
||||
end
|
||||
|
||||
local function calcWindowHeight(buttons, separators, texts)
|
||||
return
|
||||
(mainButtonSize.y + mainButtonFramePadding * 2) * buttons
|
||||
+ separators * itemSpacing.y
|
||||
+ texts * ui.fonts.pionillium.medium.size
|
||||
+ (buttons + texts - 1) * itemSpacing.y
|
||||
+ itemSpacing.x * 2
|
||||
end
|
||||
|
||||
local orbitPlannerWindowPos = Vector2(ui.screenWidth - calcWindowWidth(7), ui.screenHeight - calcWindowHeight(7, 3, 2))
|
||||
|
||||
local function showOrbitPlannerWindow()
|
||||
ui.setNextWindowPos(orbitPlannerWindowPos, "Always")
|
||||
ui.withStyleColors({["WindowBg"] = svColor.WINDOW_BACK}, function()
|
||||
ui.window("OrbitPlannerWindow", {"NoTitleBar", "NoResize", "NoFocusOnAppearing", "NoBringToFrontOnFocus", "NoSavedSettings", "AlwaysAutoResize"},
|
||||
function()
|
||||
ui.text(lc.ORBIT_PLANNER)
|
||||
|
||||
ui.separator()
|
||||
|
||||
if ui.coloredSelectedIconButton(icons.reset_view, mainButtonSize, showShips, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, lc.RESET_ORIENTATION_AND_ZOOM) then
|
||||
systemView:SetVisibility("RESET_VIEW")
|
||||
end
|
||||
ui.sameLine()
|
||||
if ui.coloredSelectedIconButton(icons.toggle_grid, mainButtonSize, showShips, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, lc.GRID_DISPLAY_MODE_TOGGLE) then
|
||||
show_grid = nextShowGrid[show_grid]
|
||||
systemView:SetVisibility(show_grid);
|
||||
end
|
||||
ui.sameLine()
|
||||
if ui.coloredSelectedIconButton(icons.toggle_ships, mainButtonSize, showShips, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, lc.SHIPS_DISPLAY_MODE_TOGGLE) then
|
||||
ship_drawing = nextShipDrawings[ship_drawing]
|
||||
systemView:SetVisibility(ship_drawing);
|
||||
end
|
||||
ui.sameLine()
|
||||
if ui.coloredSelectedIconButton(icons.toggle_lagrange, mainButtonSize, showLagrangePoints, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, lc.L4L5_DISPLAY_MODE_TOGGLE) then
|
||||
show_lagrange = nextShowLagrange[show_lagrange]
|
||||
systemView:SetVisibility(show_lagrange);
|
||||
end
|
||||
ui.sameLine()
|
||||
ui.coloredSelectedIconButton(icons.search_lens,mainButtonSize, false, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, luc.ZOOM)
|
||||
systemView:SetZoomMode(ui.isItemActive())
|
||||
|
||||
ui.sameLine()
|
||||
ui.coloredSelectedIconButton(icons.rotate_view, mainButtonSize, false, mainButtonFramePadding, svColor.BUTTON_BACK, svColor.BUTTON_INK, luc.ROTATE_VIEW)
|
||||
systemView:SetRotateMode(ui.isItemActive())
|
||||
|
||||
ui.separator()
|
||||
|
||||
showDvLine(icons.decrease, icons.delta, icons.increase, "factor", function(i) return i, "x" end, luc.DECREASE, lc.PLANNER_RESET_FACTOR, luc.INCREASE)
|
||||
showDvLine(icons.decrease, icons.clock, icons.increase, "starttime",
|
||||
function(i)
|
||||
local now = Game.time
|
||||
local start = systemView:GetOrbitPlannerStartTime()
|
||||
if start then
|
||||
return ui.Format.Duration(math.floor(start - now)), ""
|
||||
else
|
||||
return lc.NOW, ""
|
||||
end
|
||||
end,
|
||||
luc.DECREASE, lc.PLANNER_RESET_START, luc.INCREASE)
|
||||
showDvLine(icons.decrease, icons.orbit_prograde, icons.increase, "prograde", ui.Format.Speed, luc.DECREASE, lc.PLANNER_RESET_PROGRADE, luc.INCREASE)
|
||||
showDvLine(icons.decrease, icons.orbit_normal, icons.increase, "normal", ui.Format.Speed, luc.DECREASE, lc.PLANNER_RESET_NORMAL, luc.INCREASE)
|
||||
showDvLine(icons.decrease, icons.orbit_radial, icons.increase, "radial", ui.Format.Speed, luc.DECREASE, lc.PLANNER_RESET_RADIAL, luc.INCREASE)
|
||||
|
||||
ui.separator()
|
||||
|
||||
local t = systemView:GetOrbitPlannerTime()
|
||||
ui.text(t and ui.Format.Datetime(t) or lc.NOW)
|
||||
local r = false
|
||||
r = timeButton(icons.time_backward_100x, "-10,000,000x",-10000000) or r
|
||||
r = timeButton(icons.time_backward_10x, "-100,000x", -100000) or r
|
||||
r = timeButton(icons.time_backward_1x, "-1,000x", -1000) or r
|
||||
r = timeButton(icons.time_center, lc.NOW, nil) or r
|
||||
r = timeButton(icons.time_forward_1x, "1,000x", 1000) or r
|
||||
r = timeButton(icons.time_forward_10x, "100,000x", 100000) or r
|
||||
r = timeButton(icons.time_forward_100x, "10,000,000x", 10000000) or r
|
||||
if not r then
|
||||
if time_selected_button_icon == icons.time_center then
|
||||
systemView:AccelerateTime(nil)
|
||||
else
|
||||
systemView:AccelerateTime(0.0)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
local function getBodyIcon(obj)
|
||||
if obj.type == Projectable.APOAPSIS then return icons.apoapsis
|
||||
elseif obj.type == Projectable.PERIAPSIS then return icons.periapsis
|
||||
elseif obj.type == Projectable.L4 then return icons.lagrange_marker
|
||||
elseif obj.type == Projectable.L5 then return icons.lagrange_marker
|
||||
elseif obj.base == Projectable.PLAYER or obj.base == Projectable.PLANNER then
|
||||
local shipClass = obj.ref:GetShipClass()
|
||||
if icons[shipClass] then
|
||||
return icons[shipClass]
|
||||
else
|
||||
return icons.ship
|
||||
end
|
||||
elseif obj.base == Projectable.SYSTEMBODY then
|
||||
local body = obj.ref
|
||||
local st = body.superType
|
||||
local t = body.type
|
||||
if st == "STARPORT" then
|
||||
if t == "STARPORT_ORBITAL" then
|
||||
return icons.spacestation
|
||||
elseif body.type == "STARPORT_SURFACE" then
|
||||
return icons.starport
|
||||
end
|
||||
elseif st == "GAS_GIANT" then
|
||||
return icons.gas_giant
|
||||
elseif st == "STAR" then
|
||||
return icons.sun
|
||||
elseif st == "ROCKY_PLANET" then
|
||||
if body.IsMoon then
|
||||
return icons.moon
|
||||
else
|
||||
if body.radius < ASTEROID_RADIUS then
|
||||
return icons.asteroid_hollow
|
||||
else
|
||||
return icons.rocky_planet
|
||||
end
|
||||
end
|
||||
end -- st
|
||||
else
|
||||
-- physical body
|
||||
local body = obj.ref
|
||||
if body:IsShip() then
|
||||
local shipClass = body:GetShipClass()
|
||||
if icons[shipClass] then
|
||||
return icons[shipClass]
|
||||
else
|
||||
print("system-view-ui.lua: getBodyIcon unknown ship class " .. (shipClass and shipClass or "nil"))
|
||||
return icons.ship -- TODO: better icon
|
||||
end
|
||||
elseif body:IsHyperspaceCloud() then
|
||||
return icons.hyperspace -- TODO: better icon
|
||||
elseif body:IsMissile() then
|
||||
return icons.bullseye -- TODO: better icon
|
||||
elseif body:IsCargoContainer() then
|
||||
return icons.rocky_planet -- TODO: better icon
|
||||
else
|
||||
print("system-view-ui.lua: getBodyIcon not sure how to process body, supertype: " .. (st and st or "nil") .. ", type: " .. (t and t or "nil"))
|
||||
--utils.print_r(body)
|
||||
return icons.ship
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function getLabel(obj)
|
||||
if obj.type == Projectable.OBJECT then
|
||||
if obj.base == Projectable.SYSTEMBODY then return obj.ref.name
|
||||
elseif obj.base == Projectable.PLANNER then return ""
|
||||
else return obj.ref:GetLabel() end
|
||||
elseif obj.type == Projectable.L4 and show_lagrange == "LAG_ICONTEXT" then return "L4"
|
||||
elseif obj.type == Projectable.L5 and show_lagrange == "LAG_ICONTEXT" then return "L5"
|
||||
else return ""
|
||||
end
|
||||
end
|
||||
|
||||
local function getColor(obj)
|
||||
if obj.type == Projectable.OBJECT then
|
||||
if obj.base == Projectable.SYSTEMBODY then return svColor.SYSTEMBODY_ICON
|
||||
elseif obj.base == Projectable.SHIP then return svColor.SHIP
|
||||
elseif obj.base == Projectable.PLAYER then return svColor.PLAYER
|
||||
elseif obj.base == Projectable.PLANNER then return svColor.PLANNER
|
||||
else return svColor.OBJECT
|
||||
end
|
||||
elseif obj.type == Projectable.APOAPSIS or obj.type == Projectable.PERIAPSIS then
|
||||
if obj.base == Projectable.SYSTEMBODY then return svColor.SYSTEMBODY_ORBIT
|
||||
elseif obj.base == Projectable.SHIP then
|
||||
if obj.ref == selectedObject then return svColor.SELECTED_SHIP_ORBIT
|
||||
else return svColor.SHIP_ORBIT
|
||||
end
|
||||
elseif obj.base == Projectable.PLAYER then return svColor.PLAYER_ORBIT
|
||||
elseif obj.base == Projectable.PLANNER then return svColor.PLANNER_ORBIT
|
||||
else return svColor.UNKNOWN -- unknown base
|
||||
end
|
||||
elseif obj.type == Projectable.L4 or obj.type == Projectable.L5 then return svColor.LAGRANGE
|
||||
else return svColor.UNKNOWN
|
||||
end
|
||||
end
|
||||
|
||||
local function showSystemName()
|
||||
ui.setNextWindowPos(Vector2(20, 20), "Always")
|
||||
ui.withStyleColors({["WindowBg"] = svColor.SYSTEMNAME_BACK}, function()
|
||||
ui.window("SystemName", {"NoTitleBar", "AlwaysAutoResize", "NoResize", "NoFocusOnAppearing", "NoBringToFrontOnFocus", "NoSavedSettings"},
|
||||
function()
|
||||
local path = Engine.GetSectorMapSelectedSystemPath()
|
||||
local starsystem = path:GetStarSystem()
|
||||
ui.text(starsystem.name .. " (" .. path.sectorX .. ", " .. path.sectorY .. ", " .. path.sectorZ .. ")")
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
-- forked from data/pigui/views/game.lua
|
||||
local function displayOnScreenObjects()
|
||||
|
||||
local navTarget = player:GetNavTarget()
|
||||
local combatTarget = player:GetCombatTarget()
|
||||
|
||||
local should_show_label = ui.shouldShowLabels()
|
||||
local iconsize = Vector2(18 , 18)
|
||||
local label_offset = 14 -- enough so that the target rectangle fits
|
||||
local collapse = iconsize -- size of clusters to be collapsed into single bodies
|
||||
local click_radius = collapse:length() * 0.5
|
||||
-- make click_radius sufficiently smaller than the cluster size
|
||||
-- to prevent overlap of selection regions
|
||||
local objectCounter = 0
|
||||
local objects_grouped = systemView:GetProjectedGrouped(collapse, 1e64)
|
||||
if #objects_grouped == 0 then
|
||||
ui.setNextWindowPos(Vector2(ui.screenWidth, ui.screenHeight) / 2 - ui.calcTextSize(lc.UNEXPLORED_SYSTEM_NO_SYSTEM_VIEW) / 2, "Always")
|
||||
ui.withStyleColors({["WindowBg"] = svColor.SYSTEMNAME_BACK}, function()
|
||||
ui.window("NoSystemView", {"NoTitleBar", "AlwaysAutoResize", "NoResize", "NoFocusOnAppearing", "NoBringToFrontOnFocus", "NoSavedSettings"},
|
||||
function()
|
||||
ui.text(lc.UNEXPLORED_SYSTEM_NO_SYSTEM_VIEW);
|
||||
end)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
for _,group in ipairs(objects_grouped) do
|
||||
local mainObject = group.mainObject
|
||||
local mainCoords = Vector2(group.screenCoordinates.x, group.screenCoordinates.y)
|
||||
|
||||
-- indicators
|
||||
local stackedSize = indicatorSize
|
||||
local stackStep = Vector2(10, 10)
|
||||
if group.hasPlayer then
|
||||
ui.addIcon(mainCoords, icons.square, svColor.PLAYER, stackedSize, ui.anchor.center, ui.anchor.center)
|
||||
stackedSize = stackedSize + stackStep
|
||||
end
|
||||
if group.hasNavTarget then
|
||||
ui.addIcon(mainCoords, icons.square, svColor.NAV_TARGET, stackedSize, ui.anchor.center, ui.anchor.center)
|
||||
stackedSize = stackedSize + stackStep
|
||||
end
|
||||
if group.hasCombatTarget then
|
||||
ui.addIcon(mainCoords, icons.square, svColor.COMBAT_TARGET, stackedSize, ui.anchor.center, ui.anchor.center)
|
||||
stackedSize = stackedSize + stackStep
|
||||
end
|
||||
if mainObject.type == Projectable.OBJECT and mainObject.base == Projectable.PLANNER then ui.addIcon(mainCoords, icons.square, svColor.PLANNER, indicatorSize, ui.anchor.center, ui.anchor.center) end
|
||||
|
||||
ui.addIcon(mainCoords, getBodyIcon(mainObject), getColor(mainObject), iconsize, ui.anchor.center, ui.anchor.center)
|
||||
|
||||
if should_show_label then
|
||||
local label = getLabel(mainObject)
|
||||
if group.objects then
|
||||
label = label .. " (" .. #group.objects .. ")"
|
||||
end
|
||||
ui.addStyledText(mainCoords + Vector2(label_offset,0), ui.anchor.left, ui.anchor.center, label , getColor(mainObject), pionillium.small)
|
||||
end
|
||||
local mp = ui.getMousePos()
|
||||
|
||||
if mainObject.type == Projectable.OBJECT and (mainObject.base == Projectable.SYSTEMBODY or mainObject.base == Projectable.SHIP or mainObject.base == Projectable.PLAYER) then
|
||||
-- mouse release handler for right button
|
||||
if (mp - mainCoords):length() < click_radius then
|
||||
if not ui.isAnyWindowHovered() and ui.isMouseReleased(1) then
|
||||
ui.openPopup("target" .. objectCounter)
|
||||
end
|
||||
end
|
||||
-- make popup
|
||||
ui.popup("target" .. objectCounter, function()
|
||||
local isObject = mainObject.type == Projectable.OBJECT
|
||||
local isSystemBody = isObject and mainObject.base == Projectable.SYSTEMBODY
|
||||
local isShip = isObject and not isSystemBody and mainObject.ref:IsShip()
|
||||
ui.text(getLabel(mainObject))
|
||||
ui.separator()
|
||||
if ui.selectable(lc.CENTER, false, {}) then
|
||||
systemView:SetSelectedObject(mainObject.type, mainObject.base, mainObject.ref)
|
||||
end
|
||||
if (isShip or isSystemBody and mainObject.ref.physicsBody) and ui.selectable(lc.SET_AS_TARGET, false, {}) then
|
||||
if isSystemBody then
|
||||
player:SetNavTarget(mainObject.ref.physicsBody)
|
||||
else
|
||||
if combatTarget == mainObject.ref then player:SetCombatTarget(nil) end
|
||||
player:SetNavTarget(mainObject.ref)
|
||||
end
|
||||
end
|
||||
if isShip and ui.selectable(lc.SET_AS_COMBAT_TARGET, false, {}) then
|
||||
if navTarget == mainObject.ref then player:SetNavTarget(nil) end
|
||||
player:SetCombatTarget(mainObject.ref)
|
||||
end
|
||||
end)
|
||||
end
|
||||
-- mouse release handler for left button
|
||||
if (mp - mainCoords):length() < click_radius then
|
||||
if not ui.isAnyWindowHovered() and ui.isMouseReleased(0) and mainObject.type == Projectable.OBJECT then
|
||||
systemView:SetSelectedObject(mainObject.type, mainObject.base, mainObject.ref)
|
||||
end
|
||||
end
|
||||
|
||||
objectCounter = objectCounter + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function tabular(data)
|
||||
if data and #data > 0 then
|
||||
ui.columns(2, "Attributes", true)
|
||||
for _,item in pairs(data) do
|
||||
if item.value then
|
||||
ui.text(item.name)
|
||||
ui.nextColumn()
|
||||
ui.text(item.value)
|
||||
ui.nextColumn()
|
||||
end
|
||||
end
|
||||
ui.columns(1, "NoAttributes", false)
|
||||
end
|
||||
end
|
||||
|
||||
local function showTargetInfoWindow(obj)
|
||||
if obj.type ~= Projectable.OBJECT or obj.base ~= Projectable.SHIP and obj.base ~= Projectable.SYSTEMBODY then return end
|
||||
ui.setNextWindowSize(Vector2(ui.screenWidth / 5, 0), "Always")
|
||||
ui.setNextWindowPos(Vector2(20, (ui.screenHeight / 5) * 2 + 20), "Always")
|
||||
ui.withStyleColors({["WindowBg"] = svColor.WINDOW_BACK}, function()
|
||||
ui.window("TargetInfoWindow", {"NoTitleBar", "AlwaysAutoResize", "NoResize", "NoFocusOnAppearing", "NoBringToFrontOnFocus", "NoSavedSettings"},
|
||||
function()
|
||||
local data
|
||||
-- system body
|
||||
if obj.type == Projectable.OBJECT and obj.base == Projectable.SYSTEMBODY then
|
||||
local systemBody = obj.ref
|
||||
local name = systemBody.name
|
||||
local rp = systemBody.rotationPeriod * 24 * 60 * 60
|
||||
local r = systemBody.radius
|
||||
local radius = nil
|
||||
if r and r > 0 then
|
||||
local v,u = ui.Format.Distance(r)
|
||||
radius = v .. u
|
||||
end
|
||||
local sma = systemBody.semiMajorAxis
|
||||
local semimajoraxis = nil
|
||||
if sma and sma > 0 then
|
||||
local v,u = ui.Format.Distance(sma)
|
||||
semimajoraxis = v .. u
|
||||
end
|
||||
local op = systemBody.orbitPeriod * 24 * 60 * 60
|
||||
data = {
|
||||
{ name = lc.NAME_OBJECT,
|
||||
value = name },
|
||||
{ name = lc.DAY_LENGTH .. lc.ROTATIONAL_PERIOD,
|
||||
value = rp > 0 and ui.Format.Duration(rp, 2) or nil },
|
||||
{ name = lc.RADIUS,
|
||||
value = radius },
|
||||
{ name = lc.SEMI_MAJOR_AXIS,
|
||||
value = semimajoraxis },
|
||||
{ name = lc.ORBITAL_PERIOD,
|
||||
value = op and op > 0 and ui.Format.Duration(op, 2) or nil }
|
||||
}
|
||||
-- physical body
|
||||
elseif obj.type == Projectable.OBJECT and obj.ref:IsShip() then
|
||||
local body = obj.ref
|
||||
local name = body.label
|
||||
data = {{ name = lc.NAME_OBJECT, value = name }, }
|
||||
-- TODO: the advanced target scanner should add additional data here,
|
||||
-- but we really do not want to hardcode that here. there should be
|
||||
-- some kind of hook that the target scanner can hook into to display
|
||||
-- more info here.
|
||||
-- This is what should be inserted:
|
||||
table.insert(data, { name = luc.SHIP_TYPE, value = body:GetShipType() })
|
||||
if player:GetEquipCountOccupied('target_scanner') > 0 or player:GetEquipCountOccupied('advanced_target_scanner') > 0 then
|
||||
local hd = body:GetEquip("engine", 1)
|
||||
table.insert(data, { name = lc.HYPERDRIVE, value = hd and hd:GetName() or lc.NO_HYPERDRIVE })
|
||||
table.insert(data, { name = lc.MASS, value = Format.MassTonnes(body:GetStats().staticMass) })
|
||||
table.insert(data, { name = lc.CARGO, value = Format.MassTonnes(body:GetStats().usedCargo) })
|
||||
end
|
||||
else
|
||||
data = {}
|
||||
end
|
||||
tabular(data)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
local function displaySystemViewUI()
|
||||
player = Game.player
|
||||
local current_view = Game.CurrentView()
|
||||
|
||||
if current_view == "system" and not Game.InHyperspace() then
|
||||
selectedObject = systemView:GetSelectedObject()
|
||||
displayOnScreenObjects()
|
||||
ui.withFont(ui.fonts.pionillium.medium.name, ui.fonts.pionillium.medium.size, function()
|
||||
showOrbitPlannerWindow()
|
||||
showTargetInfoWindow(selectedObject)
|
||||
end)
|
||||
showSystemName()
|
||||
end
|
||||
end
|
||||
|
||||
Event.Register("onGameStart", onGameStart)
|
||||
ui.registerModule("game", displaySystemViewUI)
|
||||
|
||||
return {}
|
|
@ -160,6 +160,7 @@ theme.icons = {
|
|||
shield = 92,
|
||||
hull = 93,
|
||||
temperature = 94,
|
||||
rotate_view = 95,
|
||||
-- seventh row
|
||||
heavy_cargo_shuttle = 96,
|
||||
medium_cargo_shuttle = 97,
|
||||
|
|
|
@ -373,8 +373,8 @@ def write_header(enums, fl):
|
|||
fl.write('#ifndef HX_GEN_ENUM_TABLES\n')
|
||||
fl.write('#define HX_GEN_ENUM_TABLES\n\n')
|
||||
write_generation_header(fl)
|
||||
fl.write('struct EnumItem { const char *name; int value; };\n')
|
||||
fl.write('struct EnumTable { const char *name; const EnumItem *first; };\n\n')
|
||||
fl.write('struct EnumItem {\n\tconst char *name;\n\tint value;\n};\n')
|
||||
fl.write('struct EnumTable {\n\tconst char *name;\n\tconst EnumItem *first;\n};\n\n')
|
||||
for e in enums:
|
||||
e.write_c_header(fl)
|
||||
fl.write('\n')
|
||||
|
|
|
@ -9,10 +9,17 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
void Input::Init(GameConfig *config)
|
||||
Input::Input(IniConfig *config) :
|
||||
m_config(config),
|
||||
m_capturingMouse(false),
|
||||
mouseYInvert(false),
|
||||
joystickEnabled(true),
|
||||
keyModState(0),
|
||||
mouseButton(),
|
||||
mouseMotion()
|
||||
{
|
||||
joystickEnabled = (config->Int("EnableJoystick")) ? true : false;
|
||||
mouseYInvert = (config->Int("InvertMouseY")) ? true : false;
|
||||
joystickEnabled = (m_config->Int("EnableJoystick")) ? true : false;
|
||||
mouseYInvert = (m_config->Int("InvertMouseY")) ? true : false;
|
||||
|
||||
InitJoysticks();
|
||||
}
|
||||
|
@ -22,8 +29,8 @@ void Input::InitGame()
|
|||
//reset input states
|
||||
keyState.clear();
|
||||
keyModState = 0;
|
||||
std::fill(mouseButton, mouseButton + COUNTOF(mouseButton), 0);
|
||||
std::fill(mouseMotion, mouseMotion + COUNTOF(mouseMotion), 0);
|
||||
mouseButton.fill(0);
|
||||
mouseMotion.fill(0);
|
||||
for (std::map<SDL_JoystickID, JoystickState>::iterator stick = joysticks.begin(); stick != joysticks.end(); ++stick) {
|
||||
JoystickState &state = stick->second;
|
||||
std::fill(state.buttons.begin(), state.buttons.end(), false);
|
||||
|
@ -32,6 +39,25 @@ void Input::InitGame()
|
|||
}
|
||||
}
|
||||
|
||||
void Input::NewFrame()
|
||||
{
|
||||
mouseMotion.fill(0);
|
||||
mouseWheel = 0;
|
||||
for (auto &k : keyState) {
|
||||
auto &val = keyState[k.first];
|
||||
switch (k.second) {
|
||||
case 1: // if we were just pressed last frame, migrate to held state
|
||||
val = 2;
|
||||
break;
|
||||
case 4: // if we were just released last frame, migrate to empty state
|
||||
val = 0;
|
||||
break;
|
||||
default: // otherwise, no need to do anything
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InputResponse Input::InputFrame::ProcessSDLEvent(SDL_Event &event)
|
||||
{
|
||||
bool matched = false;
|
||||
|
@ -95,7 +121,7 @@ KeyBindings::ActionBinding *Input::AddActionBinding(std::string id, BindingGroup
|
|||
group->bindings[id] = BindingGroup::ENTRY_ACTION;
|
||||
|
||||
// Load from the config
|
||||
std::string config_str = Pi::config->String(id.c_str());
|
||||
std::string config_str = m_config->String(id.c_str());
|
||||
if (config_str.length() > 0) binding.SetFromString(config_str);
|
||||
|
||||
return &(actionBindings[id] = binding);
|
||||
|
@ -110,7 +136,7 @@ KeyBindings::AxisBinding *Input::AddAxisBinding(std::string id, BindingGroup *gr
|
|||
group->bindings[id] = BindingGroup::ENTRY_AXIS;
|
||||
|
||||
// Load from the config
|
||||
std::string config_str = Pi::config->String(id.c_str());
|
||||
std::string config_str = m_config->String(id.c_str());
|
||||
if (config_str.length() > 0) binding.SetFromString(config_str);
|
||||
|
||||
return &(axisBindings[id] = binding);
|
||||
|
@ -120,30 +146,33 @@ void Input::HandleSDLEvent(SDL_Event &event)
|
|||
{
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
keyState[event.key.keysym.sym] = true;
|
||||
// Set key state to "just pressed"
|
||||
keyState[event.key.keysym.sym] = 1;
|
||||
keyModState = event.key.keysym.mod;
|
||||
onKeyPress.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
keyState[event.key.keysym.sym] = false;
|
||||
// Set key state to "just released"
|
||||
keyState[event.key.keysym.sym] = 4;
|
||||
keyModState = event.key.keysym.mod;
|
||||
onKeyRelease.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button < COUNTOF(mouseButton)) {
|
||||
if (event.button.button < mouseButton.size()) {
|
||||
mouseButton[event.button.button] = 1;
|
||||
onMouseButtonDown.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button < COUNTOF(mouseButton)) {
|
||||
if (event.button.button < mouseButton.size()) {
|
||||
mouseButton[event.button.button] = 0;
|
||||
onMouseButtonUp.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
mouseWheel = event.wheel.y;
|
||||
onMouseWheel.emit(event.wheel.y > 0); // true = up
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
|
|
35
src/Input.h
35
src/Input.h
|
@ -8,18 +8,16 @@
|
|||
#include "utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
class GameConfig;
|
||||
class IniConfig;
|
||||
|
||||
class Input {
|
||||
// TODO: better decouple these two classes.
|
||||
friend class Pi;
|
||||
|
||||
public:
|
||||
Input() = default;
|
||||
void Init(GameConfig *config);
|
||||
Input(IniConfig *config);
|
||||
void InitGame();
|
||||
void HandleSDLEvent(SDL_Event &ev);
|
||||
void NewFrame();
|
||||
|
||||
// The Page->Group->Binding system serves as a thin veneer for the UI to make
|
||||
// sane reasonings about how to structure the Options dialog.
|
||||
|
@ -94,7 +92,17 @@ public:
|
|||
return axisBindings.count(id) ? &axisBindings[id] : nullptr;
|
||||
}
|
||||
|
||||
bool KeyState(SDL_Keycode k) { return keyState[k]; }
|
||||
bool KeyState(SDL_Keycode k) { return IsKeyDown(k); }
|
||||
|
||||
// returns true if key K is currently pressed
|
||||
bool IsKeyDown(SDL_Keycode k) { return keyState[k] & 0x3; }
|
||||
|
||||
// returns true if key K was pressed this frame
|
||||
bool IsKeyPressed(SDL_Keycode k) { return keyState[k] == 1; }
|
||||
|
||||
// returns true if key K was released this frame
|
||||
bool IsKeyReleased(SDL_Keycode k) { return keyState[k] == 4; }
|
||||
|
||||
int KeyModState() { return keyModState; }
|
||||
|
||||
int JoystickButtonState(int joystick, int button);
|
||||
|
@ -132,9 +140,11 @@ public:
|
|||
|
||||
void GetMouseMotion(int motion[2])
|
||||
{
|
||||
memcpy(motion, mouseMotion, sizeof(int) * 2);
|
||||
std::copy_n(mouseMotion.data(), mouseMotion.size(), motion);
|
||||
}
|
||||
|
||||
int GetMouseWheel() { return mouseWheel; }
|
||||
|
||||
// Capturing the mouse hides the cursor, puts the mouse into relative mode,
|
||||
// and passes all mouse inputs to the input system, regardless of whether
|
||||
// ImGui is using them or not.
|
||||
|
@ -154,10 +164,13 @@ public:
|
|||
private:
|
||||
void InitJoysticks();
|
||||
|
||||
std::map<SDL_Keycode, bool> keyState;
|
||||
IniConfig *m_config;
|
||||
|
||||
std::map<SDL_Keycode, uint8_t> keyState;
|
||||
int keyModState;
|
||||
char mouseButton[6];
|
||||
int mouseMotion[2];
|
||||
std::array<char, 6> mouseButton;
|
||||
std::array<int, 2> mouseMotion;
|
||||
int mouseWheel;
|
||||
bool m_capturingMouse;
|
||||
|
||||
bool joystickEnabled;
|
||||
|
|
1397
src/ModelViewer.cpp
1397
src/ModelViewer.cpp
File diff suppressed because it is too large
Load Diff
|
@ -3,66 +3,114 @@
|
|||
|
||||
#ifndef MODELVIEWER_H
|
||||
#define MODELVIEWER_H
|
||||
|
||||
#include "Input.h"
|
||||
#include "NavLights.h"
|
||||
#include "Shields.h"
|
||||
#include "core/GuiApplication.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "libs.h"
|
||||
#include "lua/LuaManager.h"
|
||||
#include "pigui/PiGui.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
#include "ui/Context.h"
|
||||
|
||||
class ModelViewer {
|
||||
public:
|
||||
ModelViewer(Graphics::Renderer *r, LuaManager *l);
|
||||
~ModelViewer();
|
||||
#include <memory>
|
||||
|
||||
static void Run(const std::string &modelName);
|
||||
class Input;
|
||||
class ModelViewer;
|
||||
|
||||
class ModelViewerApp : public GuiApplication {
|
||||
public:
|
||||
ModelViewerApp() :
|
||||
GuiApplication("Model Viewer")
|
||||
{}
|
||||
|
||||
void SetInitialModel(std::string &modelName) { m_modelName = modelName; }
|
||||
std::string &GetModelName() { return m_modelName; }
|
||||
|
||||
protected:
|
||||
void Startup() override;
|
||||
void Shutdown() override;
|
||||
|
||||
void PreUpdate() override;
|
||||
void PostUpdate() override;
|
||||
|
||||
friend class ModelViewer;
|
||||
|
||||
private:
|
||||
std::string m_modelName;
|
||||
std::unique_ptr<Input> m_input;
|
||||
std::shared_ptr<ModelViewer> m_modelViewer;
|
||||
};
|
||||
|
||||
class ModelViewer : public Application::Lifecycle {
|
||||
public:
|
||||
enum class CameraPreset : uint8_t {
|
||||
Front,
|
||||
Back,
|
||||
Left,
|
||||
Right,
|
||||
Top,
|
||||
Bottom
|
||||
};
|
||||
|
||||
ModelViewer(ModelViewerApp *app, LuaManager *l);
|
||||
|
||||
void SetModel(const std::string &modelName);
|
||||
bool SetRandomColor();
|
||||
void ResetCamera();
|
||||
void ChangeCameraPreset(CameraPreset preset);
|
||||
|
||||
protected:
|
||||
void Start() override;
|
||||
void Update(float deltaTime) override;
|
||||
void End() override;
|
||||
void SetupAxes();
|
||||
void HandleInput();
|
||||
|
||||
private:
|
||||
bool OnPickModel(UI::List *);
|
||||
bool OnQuit();
|
||||
bool OnReloadModel(UI::Widget *);
|
||||
bool OnToggleCollMesh(UI::CheckBox *);
|
||||
bool OnToggleShowShields(UI::CheckBox *);
|
||||
bool OnToggleGrid(UI::Widget *);
|
||||
bool OnToggleGuns(UI::CheckBox *);
|
||||
bool OnRandomColor(UI::Widget *);
|
||||
void UpdateShield();
|
||||
bool OnHitIt(UI::Widget *);
|
||||
void HitImpl();
|
||||
void AddLog(const std::string &line);
|
||||
void ChangeCameraPreset(SDL_Keycode, SDL_Keymod);
|
||||
|
||||
void UpdateModelList();
|
||||
void UpdateDecalList();
|
||||
void UpdateShield();
|
||||
|
||||
void UpdateCamera(float deltaTime);
|
||||
void UpdateLights();
|
||||
|
||||
void ReloadModel();
|
||||
void SetAnimation(SceneGraph::Animation *anim);
|
||||
void SetDecals(const std::string &file);
|
||||
|
||||
void OnModelChanged();
|
||||
|
||||
void ToggleCollMesh();
|
||||
void ToggleShowShields();
|
||||
void ToggleGrid();
|
||||
void ToggleGuns();
|
||||
void HitIt();
|
||||
|
||||
void ToggleViewControlMode();
|
||||
void ClearLog();
|
||||
void ClearModel();
|
||||
void CreateTestResources();
|
||||
void DrawBackground();
|
||||
void DrawGrid(const matrix4x4f &trans, float radius);
|
||||
void DrawModel(const matrix4x4f &mv);
|
||||
void MainLoop();
|
||||
void OnAnimChanged(unsigned int, const std::string &);
|
||||
void OnAnimSliderChanged(float);
|
||||
void OnDecalChanged(unsigned int, const std::string &);
|
||||
void OnLightPresetChanged(unsigned int index, const std::string &);
|
||||
void OnModelColorsChanged(float);
|
||||
void OnPatternChanged(unsigned int, const std::string &);
|
||||
void OnThrustChanged(float);
|
||||
void PollEvents();
|
||||
void PopulateFilePicker();
|
||||
void ResetCamera();
|
||||
|
||||
void ResetThrusters();
|
||||
void Screenshot();
|
||||
void SaveModelToBinary();
|
||||
void SetModel(const std::string &name);
|
||||
void SetupFilePicker();
|
||||
void SetupUI();
|
||||
void UpdateAnimList();
|
||||
void UpdateCamera();
|
||||
void UpdateLights();
|
||||
void UpdatePatternList();
|
||||
|
||||
void DrawModelSelector();
|
||||
void DrawModelOptions();
|
||||
void DrawShipControls();
|
||||
void DrawLog();
|
||||
void DrawPiGui();
|
||||
|
||||
private:
|
||||
//toggleable options
|
||||
struct Options {
|
||||
bool attachGuns;
|
||||
|
@ -77,17 +125,69 @@ private:
|
|||
bool wireframe;
|
||||
bool mouselookEnabled;
|
||||
float gridInterval;
|
||||
int lightPreset;
|
||||
uint32_t lightPreset;
|
||||
bool orthoView;
|
||||
|
||||
Options();
|
||||
};
|
||||
bool m_done;
|
||||
|
||||
private:
|
||||
ModelViewerApp *m_app;
|
||||
Input *m_input;
|
||||
PiGui::Instance *m_pigui;
|
||||
|
||||
KeyBindings::AxisBinding *m_moveForward;
|
||||
KeyBindings::AxisBinding *m_moveLeft;
|
||||
KeyBindings::AxisBinding *m_moveUp;
|
||||
KeyBindings::AxisBinding *m_zoomAxis;
|
||||
|
||||
KeyBindings::AxisBinding *m_rotateViewLeft;
|
||||
KeyBindings::AxisBinding *m_rotateViewUp;
|
||||
|
||||
KeyBindings::ActionBinding *m_viewTop;
|
||||
KeyBindings::ActionBinding *m_viewLeft;
|
||||
KeyBindings::ActionBinding *m_viewFront;
|
||||
|
||||
vector2f m_windowSize;
|
||||
vector2f m_logWindowSize;
|
||||
vector2f m_animWindowSize;
|
||||
std::vector<std::string> m_log;
|
||||
bool m_resetLogScroll = false;
|
||||
|
||||
vector3f m_linearThrust = {};
|
||||
vector3f m_angularThrust = {};
|
||||
|
||||
// Model pattern colors
|
||||
std::vector<Color> m_colors;
|
||||
|
||||
std::vector<std::string> m_fileNames;
|
||||
std::string m_modelName;
|
||||
std::string m_requestedModelName;
|
||||
|
||||
std::unique_ptr<SceneGraph::Model> m_model;
|
||||
bool m_modelIsShip = false;
|
||||
|
||||
std::vector<SceneGraph::Animation *> m_animations;
|
||||
SceneGraph::Animation *m_currentAnimation = nullptr;
|
||||
|
||||
bool m_modelSupportsPatterns = false;
|
||||
std::vector<std::string> m_patterns;
|
||||
uint32_t m_currentPattern = 0;
|
||||
|
||||
bool m_modelSupportsDecals = false;
|
||||
std::vector<std::string> m_decals;
|
||||
uint32_t m_currentDecal = 0;
|
||||
|
||||
bool m_modelHasShields = false;
|
||||
std::unique_ptr<Shields> m_shields;
|
||||
std::unique_ptr<NavLights> m_navLights;
|
||||
std::unique_ptr<SceneGraph::Model> m_gunModel;
|
||||
std::unique_ptr<SceneGraph::Model> m_scaleModel;
|
||||
|
||||
bool m_screenshotQueued;
|
||||
bool m_shieldIsHit;
|
||||
bool m_settingColourSliders;
|
||||
float m_shieldHitPan;
|
||||
double m_frameTime;
|
||||
Graphics::Renderer *m_renderer;
|
||||
Graphics::Texture *m_decalTexture;
|
||||
vector3f m_viewPos;
|
||||
|
@ -95,41 +195,13 @@ private:
|
|||
float m_rotX, m_rotY, m_zoom;
|
||||
float m_baseDistance;
|
||||
Random m_rng;
|
||||
SceneGraph::Animation *m_currentAnimation;
|
||||
SceneGraph::Model *m_model;
|
||||
|
||||
Options m_options;
|
||||
float m_landingMinOffset;
|
||||
std::unique_ptr<NavLights> m_navLights;
|
||||
std::unique_ptr<Shields> m_shields;
|
||||
std::unique_ptr<SceneGraph::Model> m_gunModel;
|
||||
std::unique_ptr<SceneGraph::Model> m_scaleModel;
|
||||
std::string m_modelName;
|
||||
std::string m_requestedModelName;
|
||||
RefCountedPtr<UI::Context> m_ui;
|
||||
|
||||
Graphics::RenderState *m_bgState;
|
||||
RefCountedPtr<Graphics::VertexBuffer> m_bgBuffer;
|
||||
|
||||
//undecided on this input stuff
|
||||
//updating the states of all inputs during PollEvents
|
||||
std::map<SDL_Keycode, bool> m_keyStates;
|
||||
bool m_mouseButton[SDL_BUTTON_RIGHT + 1]; //buttons start at 1
|
||||
int m_mouseMotion[2];
|
||||
bool m_mouseWheelUp, m_mouseWheelDown;
|
||||
|
||||
//interface stuff that needs to be accessed later (unorganized)
|
||||
UI::MultiLineText *m_log;
|
||||
RefCountedPtr<UI::Scroller> m_logScroller;
|
||||
|
||||
UI::List *m_fileList;
|
||||
UI::DropDown *animSelector;
|
||||
UI::DropDown *patternSelector;
|
||||
UI::DropDown *decalSelector;
|
||||
UI::Label *nameLabel;
|
||||
UI::Slider *animSlider;
|
||||
UI::Label *animValue;
|
||||
UI::Slider *colorSliders[9];
|
||||
UI::Slider *thrustSliders[2 * 3]; //thruster sliders 2*xyz (linear & angular)
|
||||
|
||||
sigc::signal<void> onModelChanged;
|
||||
|
||||
Graphics::Drawables::Lines m_gridLines;
|
||||
|
|
171
src/Pi.cpp
171
src/Pi.cpp
|
@ -25,9 +25,11 @@
|
|||
#include "NavLights.h"
|
||||
#include "OS.h"
|
||||
#include "core/GuiApplication.h"
|
||||
#include "graphics/opengl/RendererGL.h"
|
||||
#include "lua/Lua.h"
|
||||
#include "lua/LuaConsole.h"
|
||||
#include "lua/LuaEvent.h"
|
||||
#include "lua/LuaPiGui.h"
|
||||
#include "lua/LuaTimer.h"
|
||||
#include "profiler/Profiler.h"
|
||||
#include "sound/AmbientSounds.h"
|
||||
|
@ -133,7 +135,7 @@ float Pi::amountOfBackgroundStarsDisplayed = 1.0f;
|
|||
bool Pi::DrawGUI = true;
|
||||
Graphics::Renderer *Pi::renderer;
|
||||
RefCountedPtr<UI::Context> Pi::ui;
|
||||
RefCountedPtr<PiGui> Pi::pigui;
|
||||
PiGui::Instance *Pi::pigui = nullptr;
|
||||
ModelCache *Pi::modelCache;
|
||||
Intro *Pi::intro;
|
||||
SDLGraphics *Pi::sdl;
|
||||
|
@ -361,8 +363,7 @@ void Pi::App::Startup()
|
|||
Pi::rng.IncRefCount(); // so nothing tries to free it
|
||||
Pi::rng.seed(time(0));
|
||||
|
||||
Pi::input = new Input();
|
||||
Pi::input->Init(Pi::config);
|
||||
Pi::input = StartupInput(config);
|
||||
Pi::input->onKeyPress.connect(sigc::ptr_fun(&Pi::HandleKeyDown));
|
||||
|
||||
// we can only do bindings once joysticks are initialised.
|
||||
|
@ -371,6 +372,8 @@ void Pi::App::Startup()
|
|||
|
||||
RegisterInputBindings();
|
||||
|
||||
Pi::pigui = StartupPiGui();
|
||||
|
||||
// FIXME: move these into the appropriate class!
|
||||
navTunnelDisplayed = (config->Int("DisplayNavTunnel")) ? true : false;
|
||||
speedLinesDisplayed = (config->Int("SpeedLines")) ? true : false;
|
||||
|
@ -438,9 +441,11 @@ void Pi::App::Shutdown()
|
|||
BaseSphere::Uninit();
|
||||
FaceParts::Uninit();
|
||||
Graphics::Uninit();
|
||||
Pi::pigui->Uninit();
|
||||
|
||||
PiGUI::Lua::Uninit();
|
||||
ShutdownPiGui();
|
||||
Pi::pigui = nullptr;
|
||||
Pi::ui.Reset(0);
|
||||
Pi::pigui.Reset(0);
|
||||
Lua::UninitModules();
|
||||
Lua::Uninit();
|
||||
Gui::Uninit();
|
||||
|
@ -452,6 +457,9 @@ void Pi::App::Shutdown()
|
|||
ShutdownRenderer();
|
||||
Pi::renderer = nullptr;
|
||||
|
||||
ShutdownInput();
|
||||
Pi::input = nullptr;
|
||||
|
||||
delete Pi::config;
|
||||
delete Pi::planner;
|
||||
asyncJobQueue.reset();
|
||||
|
@ -489,14 +497,12 @@ void LoadStep::Start()
|
|||
// TODO: Get the lua state responsible for drawing the init progress up as fast as possible
|
||||
// Investigate using a pigui-only Lua state that we can initialize without depending on
|
||||
// normal init flow, or drawing the init screen in C++ instead?
|
||||
// Ideally we can initialize the ImGui related parts of pigui as soon as the renderer is online,
|
||||
// and then load all the lua-related state once Lua's registered and online...
|
||||
Pi::pigui.Reset(new PiGui);
|
||||
Pi::pigui->Init(Pi::renderer->GetSDLWindow());
|
||||
// Loads just the PiGui class and PiGui-related modules
|
||||
PiGUI::Lua::Init();
|
||||
|
||||
// Don't render the first frame, just make sure all of our fonts are loaded
|
||||
Pi::pigui->NewFrame(Pi::renderer->GetSDLWindow());
|
||||
Pi::pigui->RunHandler(0.01, "INIT");
|
||||
Pi::pigui->NewFrame();
|
||||
PiGUI::RunHandler(0.01, "INIT");
|
||||
Pi::pigui->EndFrame();
|
||||
|
||||
AddStep("UI::AddContext", []() {
|
||||
|
@ -608,8 +614,8 @@ void LoadStep::Update(float deltaTime)
|
|||
Output("Loading [%02.f%%]: %s took %.2fms\n", progress * 100.,
|
||||
loader.name.c_str(), timer.milliseconds());
|
||||
|
||||
Pi::pigui->NewFrame(Pi::renderer->GetSDLWindow());
|
||||
Pi::pigui->RunHandler(progress, "INIT");
|
||||
Pi::pigui->NewFrame();
|
||||
PiGUI::RunHandler(progress, "INIT");
|
||||
Pi::pigui->Render();
|
||||
|
||||
} else {
|
||||
|
@ -643,43 +649,12 @@ void MainMenu::Start()
|
|||
|
||||
void MainMenu::Update(float deltaTime)
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT)
|
||||
Pi::RequestQuit();
|
||||
else {
|
||||
Pi::pigui->ProcessEvent(&event);
|
||||
|
||||
if (Pi::pigui->WantCaptureMouse()) {
|
||||
// don't process mouse event any further, imgui already handled it
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_MOUSEMOTION:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (Pi::pigui->WantCaptureKeyboard()) {
|
||||
// don't process keyboard event any further, imgui already handled it
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
case SDL_TEXTINPUT:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
Pi::input->HandleSDLEvent(event);
|
||||
}
|
||||
}
|
||||
Pi::GetApp()->HandleEvents();
|
||||
|
||||
Pi::intro->Draw(deltaTime);
|
||||
|
||||
Pi::pigui->NewFrame(Pi::renderer->GetSDLWindow());
|
||||
Pi::pigui->RunHandler(deltaTime, "MAINMENU");
|
||||
Pi::pigui->NewFrame();
|
||||
PiGUI::RunHandler(deltaTime, "MAINMENU");
|
||||
|
||||
Pi::pigui->Render();
|
||||
|
||||
|
@ -847,12 +822,13 @@ void Pi::HandleEscKey()
|
|||
}
|
||||
}
|
||||
|
||||
void Pi::App::HandleEvents()
|
||||
// Return true if the event has been handled and shouldn't be passed through
|
||||
// to the normal input system.
|
||||
bool Pi::App::HandleEvent(SDL_Event &event)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
SDL_Event event;
|
||||
|
||||
// XXX for most keypresses SDL will generate KEYUP/KEYDOWN and TEXTINPUT
|
||||
// HACK for most keypresses SDL will generate KEYUP/KEYDOWN and TEXTINPUT
|
||||
// events. keybindings run off KEYUP/KEYDOWN. the console is opened/closed
|
||||
// via keybinding. the console TextInput widget uses TEXTINPUT events. thus
|
||||
// after switching the console, the stray TEXTINPUT event causes the
|
||||
|
@ -860,64 +836,37 @@ void Pi::App::HandleEvents()
|
|||
// this by setting this flag if the console was switched. if its set, we
|
||||
// swallow the TEXTINPUT event this hack must remain until we have a
|
||||
// unified input system
|
||||
bool skipTextInput = false;
|
||||
// This is safely able to be removed once GUI and newUI are gone
|
||||
static bool skipTextInput = false;
|
||||
|
||||
Pi::input->mouseMotion[0] = Pi::input->mouseMotion[1] = 0;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
Pi::RequestQuit();
|
||||
}
|
||||
|
||||
Pi::pigui->ProcessEvent(&event);
|
||||
|
||||
// Input system takes priority over mouse events when capturing the mouse
|
||||
if (Pi::pigui->WantCaptureMouse() && !Pi::input->IsCapturingMouse()) {
|
||||
// don't process mouse event any further, imgui already handled it
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_MOUSEMOTION:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (Pi::pigui->WantCaptureKeyboard()) {
|
||||
// don't process keyboard event any further, imgui already handled it
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
case SDL_TEXTINPUT:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipTextInput && event.type == SDL_TEXTINPUT) {
|
||||
skipTextInput = false;
|
||||
continue;
|
||||
}
|
||||
if (ui->DispatchSDLEvent(event))
|
||||
continue;
|
||||
|
||||
bool consoleActive = Pi::IsConsoleActive();
|
||||
if (!consoleActive) {
|
||||
KeyBindings::DispatchSDLEvent(&event);
|
||||
if (currentView)
|
||||
currentView->HandleSDLEvent(event);
|
||||
} else
|
||||
KeyBindings::toggleLuaConsole.CheckSDLEventAndDispatch(&event);
|
||||
if (consoleActive != Pi::IsConsoleActive()) {
|
||||
skipTextInput = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Pi::IsConsoleActive())
|
||||
continue;
|
||||
|
||||
Gui::HandleSDLEvent(&event);
|
||||
input->HandleSDLEvent(event);
|
||||
if (skipTextInput && event.type == SDL_TEXTINPUT) {
|
||||
skipTextInput = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ui->DispatchSDLEvent(event))
|
||||
return true;
|
||||
|
||||
bool consoleActive = Pi::IsConsoleActive();
|
||||
if (!consoleActive) {
|
||||
KeyBindings::DispatchSDLEvent(&event);
|
||||
if (currentView)
|
||||
currentView->HandleSDLEvent(event);
|
||||
} else {
|
||||
KeyBindings::toggleLuaConsole.CheckSDLEventAndDispatch(&event);
|
||||
}
|
||||
|
||||
if (consoleActive != Pi::IsConsoleActive()) {
|
||||
skipTextInput = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Pi::IsConsoleActive())
|
||||
return true;
|
||||
|
||||
Gui::HandleSDLEvent(&event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Pi::App::HandleRequests()
|
||||
|
@ -1126,10 +1075,16 @@ void GameLoop::Update(float deltaTime)
|
|||
Pi::ui->Draw();
|
||||
}
|
||||
|
||||
// Ask ImGui to hide OS cursor if we're capturing it for input:
|
||||
// it will do this if GetMouseCursor == ImGuiMouseCursor_None.
|
||||
if (Pi::input->IsCapturingMouse()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
|
||||
}
|
||||
|
||||
// TODO: the escape menu depends on HandleEvents() being called before NewFrame()
|
||||
// Move HandleEvents to either the end of the loop or the very start of the loop
|
||||
// The goal is to be able to call imgui functions for debugging inside C++ code
|
||||
Pi::pigui->NewFrame(Pi::renderer->GetSDLWindow());
|
||||
Pi::pigui->NewFrame();
|
||||
|
||||
if (Pi::game && !Pi::player->IsDead()) {
|
||||
// FIXME: Always begin a camera frame because WorldSpaceToScreenSpace
|
||||
|
@ -1137,7 +1092,7 @@ void GameLoop::Update(float deltaTime)
|
|||
Pi::game->GetWorldView()->BeginCameraFrame();
|
||||
// FIXME: major hack to work around the fact that the console is in newUI and not pigui
|
||||
if (!Pi::IsConsoleActive())
|
||||
Pi::pigui->RunHandler(deltaTime, "GAME");
|
||||
PiGUI::RunHandler(deltaTime, "GAME");
|
||||
Pi::game->GetWorldView()->EndCameraFrame();
|
||||
}
|
||||
|
||||
|
|
9
src/Pi.h
9
src/Pi.h
|
@ -16,6 +16,10 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace PiGui {
|
||||
class Instance;
|
||||
} //namespace PiGui
|
||||
|
||||
class Game;
|
||||
|
||||
class GameConfig;
|
||||
|
@ -26,7 +30,6 @@ class LuaNameGen;
|
|||
class LuaTimer;
|
||||
class ModelCache;
|
||||
class ObjectViewerView;
|
||||
class PiGui;
|
||||
class Player;
|
||||
class SystemPath;
|
||||
class TransferPlanner;
|
||||
|
@ -101,7 +104,7 @@ public:
|
|||
void RunJobs();
|
||||
|
||||
void HandleRequests();
|
||||
void HandleEvents();
|
||||
bool HandleEvent(SDL_Event &ev) override;
|
||||
|
||||
private:
|
||||
// msgs/requests that can be posted which the game processes at the end of a game loop in HandleRequests
|
||||
|
@ -170,7 +173,7 @@ public:
|
|||
#endif
|
||||
|
||||
static RefCountedPtr<UI::Context> ui;
|
||||
static RefCountedPtr<PiGui> pigui;
|
||||
static PiGui::Instance *pigui;
|
||||
|
||||
static Random rng;
|
||||
static int statSceneTris;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "Player.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Star.h"
|
||||
#include "SystemView.h"
|
||||
#include "collider/CollisionContact.h"
|
||||
#include "collider/CollisionSpace.h"
|
||||
#include "galaxy/Galaxy.h"
|
||||
|
@ -427,7 +428,7 @@ static void RelocateStarportIfNecessary(SystemBody *sbody, Planet *planet, vecto
|
|||
double bestVariation = 1e10; // any high value
|
||||
matrix3x3d rotNotUnderwaterWithLeastVariation = rot;
|
||||
vector3d posNotUnderwaterWithLeastVariation = pos;
|
||||
const double heightVariationCheckThreshold = 0.008; // max variation to radius radius ratio to check for local slope, ganymede is around 0.01
|
||||
const double heightVariationCheckThreshold = 0.008; // max variation to radius radius ratio to check for local slope, ganymede is around 0.01
|
||||
const double terrainHeightVariation = planet->GetMaxFeatureRadius(); //in radii
|
||||
|
||||
//Output("%s: terrain height variation %f\n", sbody->name.c_str(), terrainHeightVariation);
|
||||
|
@ -436,8 +437,8 @@ static void RelocateStarportIfNecessary(SystemBody *sbody, Planet *planet, vecto
|
|||
// points must stay within max height variation to be accepted
|
||||
// 1. delta should be chosen such that it a distance from the starport center that encloses landing pads for the largest starport
|
||||
// 2. maxSlope should be set so maxHeightVariation is less than the height of the landing pads
|
||||
const double delta = 20.0 / radius; // in radii
|
||||
const double maxSlope = 0.2; // 0.0 to 1.0
|
||||
const double delta = 20.0 / radius; // in radii
|
||||
const double maxSlope = 0.2; // 0.0 to 1.0
|
||||
const double maxHeightVariation = maxSlope * delta * radius; // in m
|
||||
|
||||
matrix3x3d rot_ = rot;
|
||||
|
@ -1006,6 +1007,7 @@ void Space::UpdateBodies()
|
|||
rmb->SetFrame(FrameId::Invalid);
|
||||
for (Body *b : m_bodies)
|
||||
b->NotifyRemoved(rmb);
|
||||
if (Pi::GetView()) Pi::game->GetSystemView()->BodyInaccessible(rmb);
|
||||
m_bodies.remove(rmb);
|
||||
}
|
||||
m_removeBodies.clear();
|
||||
|
@ -1013,6 +1015,7 @@ void Space::UpdateBodies()
|
|||
for (Body *killb : m_killBodies) {
|
||||
for (Body *b : m_bodies)
|
||||
b->NotifyRemoved(killb);
|
||||
if (Pi::GetView()) Pi::game->GetSystemView()->BodyInaccessible(killb);
|
||||
m_bodies.remove(killb);
|
||||
delete killb;
|
||||
}
|
||||
|
@ -1030,7 +1033,7 @@ static void DebugDumpFrame(FrameId fId, bool details, unsigned int indent)
|
|||
Frame *f = Frame::GetFrame(fId);
|
||||
Frame *parent = Frame::GetFrame(f->GetParent());
|
||||
|
||||
Output("%.*s%2i) %p (%s)%s\n", indent, space, fId, static_cast<void *>(f), f->GetLabel().c_str(), f->IsRotFrame() ? " [rotating]" : " [non rotating]");
|
||||
Output("%.*s%2i) %p (%s)%s\n", indent, space, static_cast<int>(fId), static_cast<void *>(f), f->GetLabel().c_str(), f->IsRotFrame() ? " [rotating]" : " [non rotating]");
|
||||
if (f->GetParent().valid())
|
||||
Output("%.*s parent %p (%s)\n", indent + 3, space, static_cast<void *>(parent), parent->GetLabel().c_str());
|
||||
if (f->GetBody())
|
||||
|
|
File diff suppressed because it is too large
Load Diff
140
src/SystemView.h
140
src/SystemView.h
|
@ -9,12 +9,15 @@
|
|||
#include "graphics/Drawables.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "vector3.h"
|
||||
#include "enum_table.h"
|
||||
#include "Frame.h"
|
||||
|
||||
class StarSystem;
|
||||
class SystemBody;
|
||||
class Orbit;
|
||||
class Ship;
|
||||
class Game;
|
||||
class Body;
|
||||
|
||||
enum BurnDirection {
|
||||
PROGRADE,
|
||||
|
@ -40,6 +43,7 @@ enum ShowLagrange {
|
|||
LAG_OFF
|
||||
};
|
||||
|
||||
|
||||
class TransferPlanner {
|
||||
public:
|
||||
TransferPlanner();
|
||||
|
@ -51,7 +55,9 @@ public:
|
|||
void IncreaseFactor(), ResetFactor(), DecreaseFactor();
|
||||
void AddStartTime(double timeStep);
|
||||
void ResetStartTime();
|
||||
double GetFactor() const { return m_factor; }
|
||||
void AddDv(BurnDirection d, double dv);
|
||||
double GetDv(BurnDirection d);
|
||||
void ResetDv(BurnDirection d);
|
||||
void ResetDv();
|
||||
std::string printDeltaTime();
|
||||
|
@ -69,85 +75,130 @@ private:
|
|||
double m_startTime;
|
||||
};
|
||||
|
||||
class SystemView : public UIView {
|
||||
struct Projectable
|
||||
{
|
||||
enum types { // <enum name=ProjectableTypes scope='Projectable' public>
|
||||
NONE = 0, // empty projectable, don't try to get members
|
||||
OBJECT = 1, // clickable space object, may be without phys.body (other starsystem)
|
||||
L4 = 2,
|
||||
L5 = 3,
|
||||
APOAPSIS = 4,
|
||||
PERIAPSIS = 5
|
||||
} type;
|
||||
enum bases { // <enum name=ProjectableBases scope='Projectable' public>
|
||||
SYSTEMBODY = 0, // ref class SystemBody, may not have a physical body
|
||||
BODY = 1, // generic body
|
||||
SHIP = 2,
|
||||
PLAYER = 3, // player's ship
|
||||
PLANNER = 4 // player's ship planned by transfer planner, refers to player's object
|
||||
} base;
|
||||
union{
|
||||
const Body* body;
|
||||
const SystemBody* sbody;
|
||||
} ref;
|
||||
vector3d screenpos; // x,y - screen coordinate, z - in NDC
|
||||
|
||||
Projectable(const types t, const bases b, const Body* obj) : type(t), base(b)
|
||||
{
|
||||
ref.body = obj;
|
||||
}
|
||||
Projectable(const types t, const bases b, const SystemBody* obj) : type(t), base(b)
|
||||
{
|
||||
ref.sbody = obj;
|
||||
}
|
||||
Projectable() : type(NONE) {}
|
||||
};
|
||||
|
||||
class SystemView : public UIView, public DeleteEmitter {
|
||||
public:
|
||||
SystemView(Game *game);
|
||||
virtual ~SystemView();
|
||||
virtual void Update();
|
||||
virtual void Draw3D();
|
||||
virtual void OnSwitchTo() { Update(); Draw3D(); }
|
||||
|
||||
Projectable* GetSelectedObject();
|
||||
void SetSelectedObject(Projectable::types type, Projectable::bases base, SystemBody *sb);
|
||||
void SetSelectedObject(Projectable::types type, Projectable::bases base, Body *b);
|
||||
TransferPlanner* GetTransferPlanner() const { return m_planner; }
|
||||
double GetOrbitPlannerStartTime() const { return m_planner->GetStartTime(); }
|
||||
double GetOrbitPlannerTime() const { return m_time; }
|
||||
void AccelerateTime(float step);
|
||||
void SetRealTime();
|
||||
std::vector<Projectable> GetProjected() const { return m_projected; }
|
||||
void BodyInaccessible(Body *b);
|
||||
void SetVisibility(std::string param);
|
||||
void SetZoomMode(bool enable);
|
||||
void SetRotateMode(bool enable);
|
||||
double ProjectedSize(double size, vector3d pos);
|
||||
|
||||
// all used colors. defined in system-view-ui.lua
|
||||
enum ColorIndex { // <enum name=SystemViewColorIndex scope='SystemView' public>
|
||||
GRID = 0,
|
||||
SYSTEMBODY = 1,
|
||||
SYSTEMBODY_ORBIT = 2,
|
||||
PLAYER_ORBIT = 3,
|
||||
PLANNER_ORBIT = 4,
|
||||
SELECTED_SHIP_ORBIT = 5,
|
||||
SHIP_ORBIT = 6
|
||||
};
|
||||
|
||||
Color svColor[7];
|
||||
void SetColor(ColorIndex color_index, Color* color_value) { svColor[color_index] = *color_value; }
|
||||
|
||||
private:
|
||||
bool m_rotateWithMouseButton = false;
|
||||
bool m_rotateView = false;
|
||||
bool m_zoomView = false;
|
||||
std::vector<Projectable> m_projected;
|
||||
static const double PICK_OBJECT_RECT_SIZE;
|
||||
static const Uint16 N_VERTICES_MAX;
|
||||
void PutOrbit(const Orbit *orb, const vector3d &offset, const Color &color, const double planetRadius = 0.0, const bool showLagrange = false);
|
||||
const float CAMERA_FOV = 50.f;
|
||||
const float CAMERA_FOV_RADIANS = CAMERA_FOV / 57.295779f;
|
||||
matrix4x4f m_cameraSpace;
|
||||
template <typename RefType>
|
||||
void PutOrbit(Projectable::bases base, RefType *ref, const Orbit *orb, const vector3d &offset, const Color &color, const double planetRadius = 0.0, const bool showLagrange = false);
|
||||
void PutBody(const SystemBody *b, const vector3d &offset, const matrix4x4f &trans);
|
||||
void PutLabel(const SystemBody *b, const vector3d &offset);
|
||||
void PutSelectionBox(const SystemBody *b, const vector3d &rootPos, const Color &col);
|
||||
void PutSelectionBox(const vector3d &worldPos, const Color &col);
|
||||
void GetTransformTo(const SystemBody *b, vector3d &pos);
|
||||
void OnClickObject(const SystemBody *b);
|
||||
void OnClickLagrange();
|
||||
void OnClickAccel(float step);
|
||||
void OnClickRealt();
|
||||
void OnIncreaseFactorButtonClick(void), OnResetFactorButtonClick(void), OnDecreaseFactorButtonClick(void);
|
||||
void OnIncreaseStartTimeButtonClick(void), OnResetStartTimeButtonClick(void), OnDecreaseStartTimeButtonClick(void);
|
||||
void OnToggleShipsButtonClick(void);
|
||||
void OnToggleGridButtonClick(void);
|
||||
void OnToggleL4L5ButtonClick(Gui::MultiStateImageButton *);
|
||||
void GetTransformTo(Projectable &p, vector3d &pos);
|
||||
void ResetViewpoint();
|
||||
void MouseWheel(bool up);
|
||||
void RefreshShips(void);
|
||||
void DrawShips(const double t, const vector3d &offset);
|
||||
void PrepareGrid();
|
||||
void DrawGrid();
|
||||
void LabelShip(Ship *s, const vector3d &offset);
|
||||
void OnClickShip(Ship *s);
|
||||
template <typename T>
|
||||
void AddProjected(Projectable::types type, Projectable::bases base, T *ref, vector3d &pos);
|
||||
template <typename T>
|
||||
void AddNotProjected(Projectable::types type, Projectable::bases base, T *ref, const vector3d &worldscaledpos);
|
||||
void CalculateShipPositionAtTime(const Ship *s, Orbit o, double t, vector3d &pos);
|
||||
void CalculateFramePositionAtTime(FrameId frameId, double t, vector3d &pos);
|
||||
double GetOrbitTime(double t, const SystemBody* b);
|
||||
double GetOrbitTime(double t, const Body* b);
|
||||
|
||||
Game *m_game;
|
||||
RefCountedPtr<StarSystem> m_system;
|
||||
const SystemBody *m_selectedObject;
|
||||
Projectable m_selectedObject;
|
||||
std::vector<SystemBody *> m_displayed_sbody;
|
||||
bool m_unexplored;
|
||||
ShowLagrange m_showL4L5;
|
||||
TransferPlanner *m_planner;
|
||||
std::list<std::pair<Ship *, Orbit>> m_contacts;
|
||||
Gui::LabelSet *m_shipLabels;
|
||||
ShipDrawing m_shipDrawing;
|
||||
GridDrawing m_gridDrawing;
|
||||
int m_grid_lines;
|
||||
float m_rot_x, m_rot_z;
|
||||
float m_rot_x_to, m_rot_z_to;
|
||||
float m_rot_x, m_rot_y;
|
||||
float m_rot_x_to, m_rot_y_to;
|
||||
float m_zoom, m_zoomTo;
|
||||
int m_animateTransition;
|
||||
vector3d m_trans;
|
||||
vector3d m_transTo;
|
||||
double m_time;
|
||||
bool m_realtime;
|
||||
double m_timeStep;
|
||||
Gui::ImageButton *m_zoomInButton;
|
||||
Gui::ImageButton *m_zoomOutButton;
|
||||
Gui::ImageButton *m_toggleShipsButton;
|
||||
Gui::ImageButton *m_toggleGridButton;
|
||||
Gui::ImageButton *m_ResetOrientButton;
|
||||
Gui::MultiStateImageButton *m_toggleL4L5Button;
|
||||
Gui::ImageButton *m_plannerIncreaseStartTimeButton, *m_plannerResetStartTimeButton, *m_plannerDecreaseStartTimeButton;
|
||||
Gui::ImageButton *m_plannerIncreaseFactorButton, *m_plannerResetFactorButton, *m_plannerDecreaseFactorButton;
|
||||
Gui::ImageButton *m_plannerAddProgradeVelButton;
|
||||
Gui::ImageButton *m_plannerAddRetrogradeVelButton;
|
||||
Gui::ImageButton *m_plannerAddNormalVelButton;
|
||||
Gui::ImageButton *m_plannerAddAntiNormalVelButton;
|
||||
Gui::ImageButton *m_plannerAddRadiallyInVelButton;
|
||||
Gui::ImageButton *m_plannerAddRadiallyOutVelButton;
|
||||
Gui::ImageButton *m_plannerZeroProgradeVelButton, *m_plannerZeroNormalVelButton, *m_plannerZeroRadialVelButton;
|
||||
Gui::Label *m_timePoint;
|
||||
Gui::Label *m_infoLabel;
|
||||
Gui::Label *m_infoText;
|
||||
Gui::Label *m_plannerFactorText, *m_plannerStartTimeText, *m_plannerProgradeDvText, *m_plannerNormalDvText, *m_plannerRadialDvText;
|
||||
Gui::LabelSet *m_objectLabels;
|
||||
sigc::connection m_onMouseWheelCon;
|
||||
|
||||
std::unique_ptr<Graphics::Drawables::Disk> m_bodyIcon;
|
||||
std::unique_ptr<Gui::TexturedQuad> m_l4Icon;
|
||||
std::unique_ptr<Gui::TexturedQuad> m_l5Icon;
|
||||
std::unique_ptr<Gui::TexturedQuad> m_periapsisIcon;
|
||||
std::unique_ptr<Gui::TexturedQuad> m_apoapsisIcon;
|
||||
Graphics::RenderState *m_lineState;
|
||||
Graphics::Drawables::Lines m_orbits;
|
||||
Graphics::Drawables::Lines m_selectBox;
|
||||
|
@ -157,7 +208,6 @@ private:
|
|||
|
||||
std::unique_ptr<Graphics::VertexArray> m_lineVerts;
|
||||
Graphics::Drawables::Lines m_lines;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SYSTEMVIEW_H */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Application.h"
|
||||
#include "FileSystem.h"
|
||||
#include "OS.h"
|
||||
#include "SDL.h"
|
||||
#include "profiler/Profiler.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
@ -33,11 +34,14 @@ void Application::Startup()
|
|||
#ifdef PIONEER_PROFILER
|
||||
FileSystem::userFiles.MakeDirectory("profiler");
|
||||
#endif
|
||||
|
||||
SDL_Init(SDL_INIT_EVENTS);
|
||||
}
|
||||
|
||||
void Application::Shutdown()
|
||||
{
|
||||
FileSystem::Uninit();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
bool Application::StartLifecycle()
|
||||
|
@ -96,6 +100,7 @@ void Application::Run()
|
|||
{
|
||||
Profiler::Clock m_runtime{};
|
||||
m_runtime.Start();
|
||||
m_applicationRunning = true;
|
||||
|
||||
Startup();
|
||||
|
||||
|
@ -137,7 +142,7 @@ void Application::Run()
|
|||
|
||||
EndFrame();
|
||||
|
||||
if (m_activeLifecycle->m_endLifecycle) {
|
||||
if (m_activeLifecycle->m_endLifecycle || !m_applicationRunning) {
|
||||
EndLifecycle();
|
||||
}
|
||||
|
||||
|
|
|
@ -40,8 +40,6 @@ public:
|
|||
m_nextLifecycle = l;
|
||||
}
|
||||
|
||||
Application *GetApp();
|
||||
|
||||
private:
|
||||
// set to true when you want to accumulate all updates in a lifecycle into a single profile frame
|
||||
bool m_profilerAccumulate = false;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "graphics/RenderTarget.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "pigui/PiGui.h"
|
||||
#include "utils.h"
|
||||
#include "versioningInfo.h"
|
||||
|
||||
|
@ -31,7 +32,8 @@ void GuiApplication::BeginFrame()
|
|||
void GuiApplication::DrawRenderTarget()
|
||||
{
|
||||
#if RTT
|
||||
m_renderer->BeginFrame();
|
||||
m_renderer->SetRenderTarget(nullptr);
|
||||
m_renderer->ClearScreen();
|
||||
m_renderer->SetViewport(0, 0, Graphics::GetScreenWidth(), Graphics::GetScreenHeight());
|
||||
m_renderer->SetTransform(matrix4x4f::Identity());
|
||||
|
||||
|
@ -60,9 +62,9 @@ void GuiApplication::DrawRenderTarget()
|
|||
void GuiApplication::EndFrame()
|
||||
{
|
||||
#if RTT
|
||||
m_renderer->SetRenderTarget(nullptr);
|
||||
DrawRenderTarget();
|
||||
#endif
|
||||
|
||||
m_renderer->EndFrame();
|
||||
m_renderer->SwapBuffers();
|
||||
}
|
||||
|
@ -100,7 +102,55 @@ Graphics::RenderTarget *GuiApplication::CreateRenderTarget(const Graphics::Setti
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Graphics::Renderer *GuiApplication::StartupRenderer(const GameConfig *config, bool hidden)
|
||||
void GuiApplication::HandleEvents()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
SDL_Event event;
|
||||
|
||||
// FIXME: input state is right before handling updates because
|
||||
// legacy UI code needs to run before input does.
|
||||
// When HandleEvents() is moved to BeginFrame / PreUpdate, this call should go with it
|
||||
m_input->NewFrame();
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
RequestQuit();
|
||||
}
|
||||
|
||||
m_pigui->ProcessEvent(&event);
|
||||
|
||||
// Input system takes priority over mouse events when capturing the mouse
|
||||
if (PiGui::WantCaptureMouse() && !m_input->IsCapturingMouse()) {
|
||||
// don't process mouse event any further, imgui already handled it
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_MOUSEMOTION:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (PiGui::WantCaptureKeyboard()) {
|
||||
// don't process keyboard event any further, imgui already handled it
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
case SDL_TEXTINPUT:
|
||||
continue;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: virtual method dispatch for each event isn't great. Let's find a better solution
|
||||
if (HandleEvent(event))
|
||||
continue;
|
||||
|
||||
m_input->HandleSDLEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Renderer *GuiApplication::StartupRenderer(IniConfig *config, bool hidden)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// Initialize SDL
|
||||
|
@ -145,3 +195,28 @@ void GuiApplication::ShutdownRenderer()
|
|||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
}
|
||||
|
||||
Input *GuiApplication::StartupInput(IniConfig *config)
|
||||
{
|
||||
m_input.reset(new Input(config));
|
||||
|
||||
return m_input.get();
|
||||
}
|
||||
|
||||
void GuiApplication::ShutdownInput()
|
||||
{
|
||||
m_input.reset();
|
||||
}
|
||||
|
||||
PiGui::Instance *GuiApplication::StartupPiGui()
|
||||
{
|
||||
m_pigui.Reset(new PiGui::Instance());
|
||||
m_pigui->Init(GetRenderer());
|
||||
return m_pigui.Get();
|
||||
}
|
||||
|
||||
void GuiApplication::ShutdownPiGui()
|
||||
{
|
||||
m_pigui->Uninit();
|
||||
m_pigui.Reset();
|
||||
}
|
||||
|
|
|
@ -4,32 +4,51 @@
|
|||
#pragma once
|
||||
|
||||
#include "Application.h"
|
||||
#include "GameConfig.h"
|
||||
#include "Input.h"
|
||||
#include "RefCounted.h"
|
||||
#include "SDL_events.h"
|
||||
#include "pigui/PiGui.h"
|
||||
|
||||
#include "graphics/RenderState.h"
|
||||
#include "graphics/RenderTarget.h"
|
||||
#include "graphics/Renderer.h"
|
||||
|
||||
class IniConfig;
|
||||
|
||||
class GuiApplication : public Application {
|
||||
public:
|
||||
GuiApplication(std::string title) :
|
||||
Application(), m_applicationTitle(title)
|
||||
{}
|
||||
|
||||
protected:
|
||||
Graphics::Renderer *GetRenderer() { return m_renderer.get(); }
|
||||
Input *GetInput() { return m_input.get(); }
|
||||
PiGui::Instance *GetPiGui() { return m_pigui.Get(); }
|
||||
|
||||
protected:
|
||||
// Called at the end of the frame automatically, blits the RT onto the application
|
||||
// framebuffer
|
||||
void DrawRenderTarget();
|
||||
|
||||
// TODO: unify config handling, possibly make the config an Application member
|
||||
// Call this from your Startup() method
|
||||
Graphics::Renderer *StartupRenderer(const GameConfig *config, bool hidden = false);
|
||||
Graphics::Renderer *StartupRenderer(IniConfig *config, bool hidden = false);
|
||||
|
||||
// Call this from your Startup() method
|
||||
Input *StartupInput(IniConfig *config);
|
||||
|
||||
// Call this from your Startup() method
|
||||
PiGui::Instance *StartupPiGui();
|
||||
|
||||
// Call this from your Shutdown() method
|
||||
void ShutdownRenderer();
|
||||
|
||||
// Call this from your Shutdown() method
|
||||
void ShutdownInput();
|
||||
|
||||
// Call this from your shutdown() method
|
||||
void ShutdownPiGui();
|
||||
|
||||
// Hook to bind the RT and clear the screen.
|
||||
// If you override BeginFrame, make sure you call this.
|
||||
void BeginFrame() override;
|
||||
|
@ -38,9 +57,21 @@ protected:
|
|||
// If you override EndFrame, make sure you call this.
|
||||
void EndFrame() override;
|
||||
|
||||
// Consume events from SDL and dispatch to pigui / input
|
||||
void HandleEvents();
|
||||
|
||||
// Override point for classes to add custom event handling
|
||||
virtual bool HandleEvent(SDL_Event &ev) { return false; }
|
||||
|
||||
// Override point to handle an application quit notification
|
||||
virtual void HandleQuit(SDL_QuitEvent &ev) { RequestQuit(); }
|
||||
|
||||
private:
|
||||
Graphics::RenderTarget *CreateRenderTarget(const Graphics::Settings &settings);
|
||||
|
||||
RefCountedPtr<PiGui::Instance> m_pigui;
|
||||
std::unique_ptr<Input> m_input;
|
||||
|
||||
std::string m_applicationTitle;
|
||||
|
||||
std::unique_ptr<Graphics::Renderer> m_renderer;
|
||||
|
|
|
@ -10,15 +10,17 @@
|
|||
#include "Ship.h"
|
||||
#include "ShipAICmd.h"
|
||||
#include "ShipType.h"
|
||||
#include "SystemView.h"
|
||||
#include "galaxy/Economy.h"
|
||||
#include "galaxy/Polit.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "galaxy/SystemBody.h"
|
||||
#include "gameui/Face.h"
|
||||
#include "lua/LuaEngine.h"
|
||||
#include "lua/LuaFileSystem.h"
|
||||
#include "pigui/Face.h"
|
||||
#include "scenegraph/Model.h"
|
||||
#include "ship/PlayerShipController.h"
|
||||
#include "ship/Propulsion.h"
|
||||
#include "ship/ShipController.h"
|
||||
#include "ui/Align.h"
|
||||
#include "ui/Animation.h"
|
||||
#include "ui/Event.h"
|
||||
|
@ -37,21 +39,6 @@ const struct EnumItem ENUM_ShipAIError[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_DetailLevel[] = {
|
||||
{ "VERY_LOW", int(LuaEngine::DETAIL_VERY_LOW) },
|
||||
{ "LOW", int(LuaEngine::DETAIL_LOW) },
|
||||
{ "MEDIUM", int(LuaEngine::DETAIL_MEDIUM) },
|
||||
{ "HIGH", int(LuaEngine::DETAIL_HIGH) },
|
||||
{ "VERY_HIGH", int(LuaEngine::DETAIL_VERY_HIGH) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_FileSystemRoot[] = {
|
||||
{ "USER", int(LuaFileSystem::ROOT_USER) },
|
||||
{ "DATA", int(LuaFileSystem::ROOT_DATA) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PhysicsObjectType[] = {
|
||||
{ "BODY", int(Object::BODY) },
|
||||
{ "MODELBODY", int(Object::MODELBODY) },
|
||||
|
@ -65,52 +52,6 @@ const struct EnumItem ENUM_PhysicsObjectType[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PolitEcon[] = {
|
||||
{ "NONE", int(Polit::ECON_NONE) },
|
||||
{ "VERY_CAPITALIST", int(Polit::ECON_VERY_CAPITALIST) },
|
||||
{ "CAPITALIST", int(Polit::ECON_CAPITALIST) },
|
||||
{ "MIXED", int(Polit::ECON_MIXED) },
|
||||
{ "PLANNED", int(Polit::ECON_PLANNED) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PolitGovType[] = {
|
||||
{ "NONE", int(Polit::GOV_NONE) },
|
||||
{ "EARTHCOLONIAL", int(Polit::GOV_EARTHCOLONIAL) },
|
||||
{ "EARTHDEMOC", int(Polit::GOV_EARTHDEMOC) },
|
||||
{ "EMPIRERULE", int(Polit::GOV_EMPIRERULE) },
|
||||
{ "CISLIBDEM", int(Polit::GOV_CISLIBDEM) },
|
||||
{ "CISSOCDEM", int(Polit::GOV_CISSOCDEM) },
|
||||
{ "LIBDEM", int(Polit::GOV_LIBDEM) },
|
||||
{ "CORPORATE", int(Polit::GOV_CORPORATE) },
|
||||
{ "SOCDEM", int(Polit::GOV_SOCDEM) },
|
||||
{ "EARTHMILDICT", int(Polit::GOV_EARTHMILDICT) },
|
||||
{ "MILDICT1", int(Polit::GOV_MILDICT1) },
|
||||
{ "MILDICT2", int(Polit::GOV_MILDICT2) },
|
||||
{ "EMPIREMILDICT", int(Polit::GOV_EMPIREMILDICT) },
|
||||
{ "COMMUNIST", int(Polit::GOV_COMMUNIST) },
|
||||
{ "PLUTOCRATIC", int(Polit::GOV_PLUTOCRATIC) },
|
||||
{ "DISORDER", int(Polit::GOV_DISORDER) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ShipTypeThruster[] = {
|
||||
{ "REVERSE", int(Thruster::THRUSTER_REVERSE) },
|
||||
{ "FORWARD", int(Thruster::THRUSTER_FORWARD) },
|
||||
{ "UP", int(Thruster::THRUSTER_UP) },
|
||||
{ "DOWN", int(Thruster::THRUSTER_DOWN) },
|
||||
{ "LEFT", int(Thruster::THRUSTER_LEFT) },
|
||||
{ "RIGHT", int(Thruster::THRUSTER_RIGHT) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PropulsionFuelStatus[] = {
|
||||
{ "OK", int(Propulsion::FUEL_OK) },
|
||||
{ "WARNING", int(Propulsion::FUEL_WARNING) },
|
||||
{ "EMPTY", int(Propulsion::FUEL_EMPTY) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ShipFlightState[] = {
|
||||
{ "FLYING", int(Ship::FLYING) },
|
||||
{ "DOCKING", int(Ship::DOCKING) },
|
||||
|
@ -138,6 +79,7 @@ const struct EnumItem ENUM_ShipAlertStatus[] = {
|
|||
{ "NONE", int(Ship::ALERT_NONE) },
|
||||
{ "SHIP_NEARBY", int(Ship::ALERT_SHIP_NEARBY) },
|
||||
{ "SHIP_FIRING", int(Ship::ALERT_SHIP_FIRING) },
|
||||
{ "MISSILE_DETECTED", int(Ship::ALERT_MISSILE_DETECTED) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -153,20 +95,6 @@ const struct EnumItem ENUM_ShipAICmdName[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ShipControllerFlightControlState[] = {
|
||||
{ "CONTROL_MANUAL", int(FlightControlState::CONTROL_MANUAL) },
|
||||
{ "CONTROL_FIXSPEED", int(FlightControlState::CONTROL_FIXSPEED) },
|
||||
{ "CONTROL_FIXHEADING_FORWARD", int(FlightControlState::CONTROL_FIXHEADING_FORWARD) },
|
||||
{ "CONTROL_FIXHEADING_BACKWARD", int(FlightControlState::CONTROL_FIXHEADING_BACKWARD) },
|
||||
{ "CONTROL_FIXHEADING_NORMAL", int(FlightControlState::CONTROL_FIXHEADING_NORMAL) },
|
||||
{ "CONTROL_FIXHEADING_ANTINORMAL", int(FlightControlState::CONTROL_FIXHEADING_ANTINORMAL) },
|
||||
{ "CONTROL_FIXHEADING_RADIALLY_INWARD", int(FlightControlState::CONTROL_FIXHEADING_RADIALLY_INWARD) },
|
||||
{ "CONTROL_FIXHEADING_RADIALLY_OUTWARD", int(FlightControlState::CONTROL_FIXHEADING_RADIALLY_OUTWARD) },
|
||||
{ "CONTROL_FIXHEADING_KILLROT", int(FlightControlState::CONTROL_FIXHEADING_KILLROT) },
|
||||
{ "CONTROL_AUTOPILOT", int(FlightControlState::CONTROL_AUTOPILOT) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_DualLaserOrientation[] = {
|
||||
{ "HORIZONTAL", int(ShipType::DUAL_LASERS_HORIZONTAL) },
|
||||
{ "VERTICAL", int(ShipType::DUAL_LASERS_VERTICAL) },
|
||||
|
@ -181,6 +109,36 @@ const struct EnumItem ENUM_ShipTypeTag[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ProjectableTypes[] = {
|
||||
{ "NONE", int(Projectable::NONE) },
|
||||
{ "OBJECT", int(Projectable::OBJECT) },
|
||||
{ "L4", int(Projectable::L4) },
|
||||
{ "L5", int(Projectable::L5) },
|
||||
{ "APOAPSIS", int(Projectable::APOAPSIS) },
|
||||
{ "PERIAPSIS", int(Projectable::PERIAPSIS) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ProjectableBases[] = {
|
||||
{ "SYSTEMBODY", int(Projectable::SYSTEMBODY) },
|
||||
{ "BODY", int(Projectable::BODY) },
|
||||
{ "SHIP", int(Projectable::SHIP) },
|
||||
{ "PLAYER", int(Projectable::PLAYER) },
|
||||
{ "PLANNER", int(Projectable::PLANNER) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_SystemViewColorIndex[] = {
|
||||
{ "GRID", int(SystemView::GRID) },
|
||||
{ "SYSTEMBODY", int(SystemView::SYSTEMBODY) },
|
||||
{ "SYSTEMBODY_ORBIT", int(SystemView::SYSTEMBODY_ORBIT) },
|
||||
{ "PLAYER_ORBIT", int(SystemView::PLAYER_ORBIT) },
|
||||
{ "PLANNER_ORBIT", int(SystemView::PLANNER_ORBIT) },
|
||||
{ "SELECTED_SHIP_ORBIT", int(SystemView::SELECTED_SHIP_ORBIT) },
|
||||
{ "SHIP_ORBIT", int(SystemView::SHIP_ORBIT) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_EconType[] = {
|
||||
{ "MINING", int(GalacticEconomy::ECON_MINING) },
|
||||
{ "AGRICULTURE", int(GalacticEconomy::ECON_AGRICULTURE) },
|
||||
|
@ -223,6 +181,35 @@ const struct EnumItem ENUM_CommodityType[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PolitEcon[] = {
|
||||
{ "NONE", int(Polit::ECON_NONE) },
|
||||
{ "VERY_CAPITALIST", int(Polit::ECON_VERY_CAPITALIST) },
|
||||
{ "CAPITALIST", int(Polit::ECON_CAPITALIST) },
|
||||
{ "MIXED", int(Polit::ECON_MIXED) },
|
||||
{ "PLANNED", int(Polit::ECON_PLANNED) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PolitGovType[] = {
|
||||
{ "NONE", int(Polit::GOV_NONE) },
|
||||
{ "EARTHCOLONIAL", int(Polit::GOV_EARTHCOLONIAL) },
|
||||
{ "EARTHDEMOC", int(Polit::GOV_EARTHDEMOC) },
|
||||
{ "EMPIRERULE", int(Polit::GOV_EMPIRERULE) },
|
||||
{ "CISLIBDEM", int(Polit::GOV_CISLIBDEM) },
|
||||
{ "CISSOCDEM", int(Polit::GOV_CISSOCDEM) },
|
||||
{ "LIBDEM", int(Polit::GOV_LIBDEM) },
|
||||
{ "CORPORATE", int(Polit::GOV_CORPORATE) },
|
||||
{ "SOCDEM", int(Polit::GOV_SOCDEM) },
|
||||
{ "EARTHMILDICT", int(Polit::GOV_EARTHMILDICT) },
|
||||
{ "MILDICT1", int(Polit::GOV_MILDICT1) },
|
||||
{ "MILDICT2", int(Polit::GOV_MILDICT2) },
|
||||
{ "EMPIREMILDICT", int(Polit::GOV_EMPIREMILDICT) },
|
||||
{ "COMMUNIST", int(Polit::GOV_COMMUNIST) },
|
||||
{ "PLUTOCRATIC", int(Polit::GOV_PLUTOCRATIC) },
|
||||
{ "DISORDER", int(Polit::GOV_DISORDER) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_BodyType[] = {
|
||||
{ "GRAVPOINT", int(SystemBody::TYPE_GRAVPOINT) },
|
||||
{ "BROWN_DWARF", int(SystemBody::TYPE_BROWN_DWARF) },
|
||||
|
@ -286,6 +273,29 @@ const struct EnumItem ENUM_GameUIFaceFlags[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_DetailLevel[] = {
|
||||
{ "VERY_LOW", int(LuaEngine::DETAIL_VERY_LOW) },
|
||||
{ "LOW", int(LuaEngine::DETAIL_LOW) },
|
||||
{ "MEDIUM", int(LuaEngine::DETAIL_MEDIUM) },
|
||||
{ "HIGH", int(LuaEngine::DETAIL_HIGH) },
|
||||
{ "VERY_HIGH", int(LuaEngine::DETAIL_VERY_HIGH) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_FileSystemRoot[] = {
|
||||
{ "USER", int(LuaFileSystem::ROOT_USER) },
|
||||
{ "DATA", int(LuaFileSystem::ROOT_DATA) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PiGUIFaceFlags[] = {
|
||||
{ "RAND", int(PiGUI::Face::RAND) },
|
||||
{ "MALE", int(PiGUI::Face::MALE) },
|
||||
{ "FEMALE", int(PiGUI::Face::FEMALE) },
|
||||
{ "ARMOUR", int(PiGUI::Face::ARMOUR) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ModelDebugFlags[] = {
|
||||
{ "NONE", int(SceneGraph::Model::DEBUG_NONE) },
|
||||
{ "BBOX", int(SceneGraph::Model::DEBUG_BBOX) },
|
||||
|
@ -296,6 +306,37 @@ const struct EnumItem ENUM_ModelDebugFlags[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ShipTypeThruster[] = {
|
||||
{ "REVERSE", int(Thruster::THRUSTER_REVERSE) },
|
||||
{ "FORWARD", int(Thruster::THRUSTER_FORWARD) },
|
||||
{ "UP", int(Thruster::THRUSTER_UP) },
|
||||
{ "DOWN", int(Thruster::THRUSTER_DOWN) },
|
||||
{ "LEFT", int(Thruster::THRUSTER_LEFT) },
|
||||
{ "RIGHT", int(Thruster::THRUSTER_RIGHT) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_PropulsionFuelStatus[] = {
|
||||
{ "OK", int(Propulsion::FUEL_OK) },
|
||||
{ "WARNING", int(Propulsion::FUEL_WARNING) },
|
||||
{ "EMPTY", int(Propulsion::FUEL_EMPTY) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_ShipControllerFlightControlState[] = {
|
||||
{ "CONTROL_MANUAL", int(FlightControlState::CONTROL_MANUAL) },
|
||||
{ "CONTROL_FIXSPEED", int(FlightControlState::CONTROL_FIXSPEED) },
|
||||
{ "CONTROL_FIXHEADING_FORWARD", int(FlightControlState::CONTROL_FIXHEADING_FORWARD) },
|
||||
{ "CONTROL_FIXHEADING_BACKWARD", int(FlightControlState::CONTROL_FIXHEADING_BACKWARD) },
|
||||
{ "CONTROL_FIXHEADING_NORMAL", int(FlightControlState::CONTROL_FIXHEADING_NORMAL) },
|
||||
{ "CONTROL_FIXHEADING_ANTINORMAL", int(FlightControlState::CONTROL_FIXHEADING_ANTINORMAL) },
|
||||
{ "CONTROL_FIXHEADING_RADIALLY_INWARD", int(FlightControlState::CONTROL_FIXHEADING_RADIALLY_INWARD) },
|
||||
{ "CONTROL_FIXHEADING_RADIALLY_OUTWARD", int(FlightControlState::CONTROL_FIXHEADING_RADIALLY_OUTWARD) },
|
||||
{ "CONTROL_FIXHEADING_KILLROT", int(FlightControlState::CONTROL_FIXHEADING_KILLROT) },
|
||||
{ "CONTROL_AUTOPILOT", int(FlightControlState::CONTROL_AUTOPILOT) },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
const struct EnumItem ENUM_UIAlignDirection[] = {
|
||||
{ "TOP_LEFT", int(UI::Align::TOP_LEFT) },
|
||||
{ "TOP", int(UI::Align::TOP) },
|
||||
|
@ -479,26 +520,30 @@ const struct EnumItem ENUM_UIFont[] = {
|
|||
|
||||
const struct EnumTable ENUM_TABLES[] = {
|
||||
{ "ShipAIError", ENUM_ShipAIError },
|
||||
{ "DetailLevel", ENUM_DetailLevel },
|
||||
{ "FileSystemRoot", ENUM_FileSystemRoot },
|
||||
{ "PhysicsObjectType", ENUM_PhysicsObjectType },
|
||||
{ "PolitEcon", ENUM_PolitEcon },
|
||||
{ "PolitGovType", ENUM_PolitGovType },
|
||||
{ "ShipTypeThruster", ENUM_ShipTypeThruster },
|
||||
{ "PropulsionFuelStatus", ENUM_PropulsionFuelStatus },
|
||||
{ "ShipFlightState", ENUM_ShipFlightState },
|
||||
{ "ShipJumpStatus", ENUM_ShipJumpStatus },
|
||||
{ "ShipAlertStatus", ENUM_ShipAlertStatus },
|
||||
{ "ShipAICmdName", ENUM_ShipAICmdName },
|
||||
{ "ShipControllerFlightControlState", ENUM_ShipControllerFlightControlState },
|
||||
{ "DualLaserOrientation", ENUM_DualLaserOrientation },
|
||||
{ "ShipTypeTag", ENUM_ShipTypeTag },
|
||||
{ "ProjectableTypes", ENUM_ProjectableTypes },
|
||||
{ "ProjectableBases", ENUM_ProjectableBases },
|
||||
{ "SystemViewColorIndex", ENUM_SystemViewColorIndex },
|
||||
{ "EconType", ENUM_EconType },
|
||||
{ "CommodityType", ENUM_CommodityType },
|
||||
{ "PolitEcon", ENUM_PolitEcon },
|
||||
{ "PolitGovType", ENUM_PolitGovType },
|
||||
{ "BodyType", ENUM_BodyType },
|
||||
{ "BodySuperType", ENUM_BodySuperType },
|
||||
{ "GameUIFaceFlags", ENUM_GameUIFaceFlags },
|
||||
{ "DetailLevel", ENUM_DetailLevel },
|
||||
{ "FileSystemRoot", ENUM_FileSystemRoot },
|
||||
{ "PiGUIFaceFlags", ENUM_PiGUIFaceFlags },
|
||||
{ "ModelDebugFlags", ENUM_ModelDebugFlags },
|
||||
{ "ShipTypeThruster", ENUM_ShipTypeThruster },
|
||||
{ "PropulsionFuelStatus", ENUM_PropulsionFuelStatus },
|
||||
{ "ShipControllerFlightControlState", ENUM_ShipControllerFlightControlState },
|
||||
{ "UIAlignDirection", ENUM_UIAlignDirection },
|
||||
{ "UIAnimationType", ENUM_UIAnimationType },
|
||||
{ "UIAnimationEasing", ENUM_UIAnimationEasing },
|
||||
|
@ -523,26 +568,30 @@ const struct EnumTable ENUM_TABLES[] = {
|
|||
|
||||
const struct EnumTable ENUM_TABLES_PUBLIC[] = {
|
||||
{ "ShipAIError", ENUM_ShipAIError },
|
||||
{ "DetailLevel", ENUM_DetailLevel },
|
||||
{ "FileSystemRoot", ENUM_FileSystemRoot },
|
||||
{ "PhysicsObjectType", ENUM_PhysicsObjectType },
|
||||
{ "PolitEcon", ENUM_PolitEcon },
|
||||
{ "PolitGovType", ENUM_PolitGovType },
|
||||
{ "ShipTypeThruster", ENUM_ShipTypeThruster },
|
||||
{ "PropulsionFuelStatus", ENUM_PropulsionFuelStatus },
|
||||
{ "ShipFlightState", ENUM_ShipFlightState },
|
||||
{ "ShipJumpStatus", ENUM_ShipJumpStatus },
|
||||
{ "ShipAlertStatus", ENUM_ShipAlertStatus },
|
||||
{ "ShipAICmdName", ENUM_ShipAICmdName },
|
||||
{ "ShipControllerFlightControlState", ENUM_ShipControllerFlightControlState },
|
||||
{ "DualLaserOrientation", ENUM_DualLaserOrientation },
|
||||
{ "ShipTypeTag", ENUM_ShipTypeTag },
|
||||
{ "ProjectableTypes", ENUM_ProjectableTypes },
|
||||
{ "ProjectableBases", ENUM_ProjectableBases },
|
||||
{ "SystemViewColorIndex", ENUM_SystemViewColorIndex },
|
||||
{ "EconType", ENUM_EconType },
|
||||
{ "CommodityType", ENUM_CommodityType },
|
||||
{ "PolitEcon", ENUM_PolitEcon },
|
||||
{ "PolitGovType", ENUM_PolitGovType },
|
||||
{ "BodyType", ENUM_BodyType },
|
||||
{ "BodySuperType", ENUM_BodySuperType },
|
||||
{ "GameUIFaceFlags", ENUM_GameUIFaceFlags },
|
||||
{ "DetailLevel", ENUM_DetailLevel },
|
||||
{ "FileSystemRoot", ENUM_FileSystemRoot },
|
||||
{ "PiGUIFaceFlags", ENUM_PiGUIFaceFlags },
|
||||
{ "ModelDebugFlags", ENUM_ModelDebugFlags },
|
||||
{ "ShipTypeThruster", ENUM_ShipTypeThruster },
|
||||
{ "PropulsionFuelStatus", ENUM_PropulsionFuelStatus },
|
||||
{ "ShipControllerFlightControlState", ENUM_ShipControllerFlightControlState },
|
||||
{ "UIAlignDirection", ENUM_UIAlignDirection },
|
||||
{ "UIAnimationType", ENUM_UIAnimationType },
|
||||
{ "UIAnimationEasing", ENUM_UIAnimationEasing },
|
||||
|
|
|
@ -17,26 +17,30 @@ struct EnumTable {
|
|||
};
|
||||
|
||||
extern const struct EnumItem ENUM_ShipAIError[];
|
||||
extern const struct EnumItem ENUM_DetailLevel[];
|
||||
extern const struct EnumItem ENUM_FileSystemRoot[];
|
||||
extern const struct EnumItem ENUM_PhysicsObjectType[];
|
||||
extern const struct EnumItem ENUM_PolitEcon[];
|
||||
extern const struct EnumItem ENUM_PolitGovType[];
|
||||
extern const struct EnumItem ENUM_ShipTypeThruster[];
|
||||
extern const struct EnumItem ENUM_PropulsionFuelStatus[];
|
||||
extern const struct EnumItem ENUM_ShipFlightState[];
|
||||
extern const struct EnumItem ENUM_ShipJumpStatus[];
|
||||
extern const struct EnumItem ENUM_ShipAlertStatus[];
|
||||
extern const struct EnumItem ENUM_ShipAICmdName[];
|
||||
extern const struct EnumItem ENUM_ShipControllerFlightControlState[];
|
||||
extern const struct EnumItem ENUM_DualLaserOrientation[];
|
||||
extern const struct EnumItem ENUM_ShipTypeTag[];
|
||||
extern const struct EnumItem ENUM_ProjectableTypes[];
|
||||
extern const struct EnumItem ENUM_ProjectableBases[];
|
||||
extern const struct EnumItem ENUM_SystemViewColorIndex[];
|
||||
extern const struct EnumItem ENUM_EconType[];
|
||||
extern const struct EnumItem ENUM_CommodityType[];
|
||||
extern const struct EnumItem ENUM_PolitEcon[];
|
||||
extern const struct EnumItem ENUM_PolitGovType[];
|
||||
extern const struct EnumItem ENUM_BodyType[];
|
||||
extern const struct EnumItem ENUM_BodySuperType[];
|
||||
extern const struct EnumItem ENUM_GameUIFaceFlags[];
|
||||
extern const struct EnumItem ENUM_DetailLevel[];
|
||||
extern const struct EnumItem ENUM_FileSystemRoot[];
|
||||
extern const struct EnumItem ENUM_PiGUIFaceFlags[];
|
||||
extern const struct EnumItem ENUM_ModelDebugFlags[];
|
||||
extern const struct EnumItem ENUM_ShipTypeThruster[];
|
||||
extern const struct EnumItem ENUM_PropulsionFuelStatus[];
|
||||
extern const struct EnumItem ENUM_ShipControllerFlightControlState[];
|
||||
extern const struct EnumItem ENUM_UIAlignDirection[];
|
||||
extern const struct EnumItem ENUM_UIAnimationType[];
|
||||
extern const struct EnumItem ENUM_UIAnimationEasing[];
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "Ship.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Star.h"
|
||||
#include "SystemView.h"
|
||||
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "gameui/Lua.h"
|
||||
|
@ -71,6 +72,7 @@ namespace Lua {
|
|||
|
||||
LuaObject<StarSystem>::RegisterClass();
|
||||
LuaObject<SystemPath>::RegisterClass();
|
||||
LuaObject<SystemView>::RegisterClass();
|
||||
LuaObject<SystemBody>::RegisterClass();
|
||||
LuaObject<Random>::RegisterClass();
|
||||
LuaObject<Faction>::RegisterClass();
|
||||
|
@ -107,9 +109,6 @@ namespace Lua {
|
|||
GameUI::Lua::Init();
|
||||
SceneGraph::Lua::Init();
|
||||
|
||||
LuaObject<PiGui>::RegisterClass();
|
||||
PiGUI::Lua::Init();
|
||||
|
||||
// XXX load everything. for now, just modules
|
||||
lua_State *l = Lua::manager->GetLuaState();
|
||||
pi_lua_dofile(l, "libs/autoload.lua");
|
||||
|
|
|
@ -24,11 +24,12 @@
|
|||
#include "Ship.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Star.h"
|
||||
#include "HyperspaceCloud.h"
|
||||
|
||||
// Defined in LuaPiGui.h
|
||||
extern bool first_body_is_more_important_than(Body*, Body*);
|
||||
extern int pushOnScreenPositionDirection(lua_State *l, vector3d position);
|
||||
namespace PiGUI {
|
||||
// Defined in LuaPiGui.h
|
||||
extern bool first_body_is_more_important_than(Body *, Body *);
|
||||
extern int pushOnScreenPositionDirection(lua_State *l, vector3d position);
|
||||
} // namespace PiGUI
|
||||
|
||||
/*
|
||||
* Class: Body
|
||||
|
@ -246,7 +247,7 @@ static int l_body_is_more_important_than(lua_State *l)
|
|||
LuaPush<bool>(l, false);
|
||||
return 1;
|
||||
}
|
||||
LuaPush<bool>(l, first_body_is_more_important_than(body, other));
|
||||
LuaPush<bool>(l, PiGUI::first_body_is_more_important_than(body, other));
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
|
@ -653,7 +654,7 @@ static int l_body_get_projected_screen_position(lua_State *l)
|
|||
Body *b = LuaObject<Body>::CheckFromLua(1);
|
||||
WorldView *wv = Pi::game->GetWorldView();
|
||||
vector3d p = wv->WorldSpaceToScreenSpace(b);
|
||||
return pushOnScreenPositionDirection(l, p);
|
||||
return PiGUI::pushOnScreenPositionDirection(l, p);
|
||||
}
|
||||
|
||||
static int l_body_get_atmospheric_state(lua_State *l)
|
||||
|
@ -685,7 +686,7 @@ static int l_body_get_target_indicator_screen_position(lua_State *l)
|
|||
Body *b = LuaObject<Body>::CheckFromLua(1);
|
||||
WorldView *wv = Pi::game->GetWorldView();
|
||||
vector3d p = wv->GetTargetIndicatorScreenPosition(b);
|
||||
return pushOnScreenPositionDirection(l, p);
|
||||
return PiGUI::pushOnScreenPositionDirection(l, p);
|
||||
}
|
||||
|
||||
static bool push_body_to_lua(Body *body)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Intro.h"
|
||||
#include "KeyBindings.h"
|
||||
#include "Lang.h"
|
||||
#include "LuaColor.h"
|
||||
#include "LuaConstants.h"
|
||||
#include "LuaObject.h"
|
||||
#include "LuaPiGui.h"
|
||||
|
@ -116,7 +117,7 @@ static int l_engine_attr_ui(lua_State *l)
|
|||
*/
|
||||
static int l_engine_attr_pigui(lua_State *l)
|
||||
{
|
||||
LuaObject<PiGui>::PushToLua(Pi::pigui.Get());
|
||||
LuaObject<PiGui::Instance>::PushToLua(Pi::pigui);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -336,6 +337,14 @@ static int l_engine_set_fullscreen(lua_State *l)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int l_engine_get_enum_value(lua_State *l)
|
||||
{
|
||||
auto enum_name = LuaPull<const char *>(l, 1);
|
||||
auto enum_tag = LuaPull<const char *>(l, 2);
|
||||
LuaPush<int>(l, EnumStrings::GetValue(enum_name, enum_tag));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_engine_get_disable_screenshot_info(lua_State *l)
|
||||
{
|
||||
LuaPush<bool>(l, Pi::config->Int("DisableScreenshotInfo") != 0);
|
||||
|
@ -785,7 +794,7 @@ static int l_engine_world_space_to_screen_space(lua_State *l)
|
|||
{
|
||||
vector3d pos = LuaPull<vector3d>(l, 1);
|
||||
|
||||
TScreenSpace res = lua_world_space_to_screen_space(pos); // defined in LuaPiGui.cpp
|
||||
PiGUI::TScreenSpace res = PiGUI::lua_world_space_to_screen_space(pos); // defined in LuaPiGui.cpp
|
||||
|
||||
LuaPush<bool>(l, res._onScreen);
|
||||
LuaPush<vector2d>(l, res._screenPosition);
|
||||
|
@ -1077,7 +1086,7 @@ static int l_engine_get_sector_map_factions(lua_State *l)
|
|||
lua_setfield(l, -2, "faction");
|
||||
lua_pushboolean(l, hidden.count(f) == 0);
|
||||
lua_setfield(l, -2, "visible"); // inner table
|
||||
lua_settable(l, -3); // outer table
|
||||
lua_settable(l, -3); // outer table
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1195,16 +1204,14 @@ void LuaEngine::Register()
|
|||
{ "SectorMapMoveRouteItemUp", l_engine_sector_map_move_route_item_up },
|
||||
{ "SectorMapMoveRouteItemDown", l_engine_sector_map_move_route_item_down },
|
||||
{ "SectorMapRemoveRouteItem", l_engine_sector_map_remove_route_item },
|
||||
|
||||
{ "SectorMapClearRoute", l_engine_sector_map_clear_route },
|
||||
{ "SectorMapAddToRoute", l_engine_sector_map_add_to_route },
|
||||
|
||||
{ "SearchNearbyStarSystemsByName", l_engine_search_nearby_star_systems_by_name },
|
||||
|
||||
{ "ShipSpaceToScreenSpace", l_engine_ship_space_to_screen_space },
|
||||
{ "CameraSpaceToScreenSpace", l_engine_camera_space_to_screen_space },
|
||||
{ "WorldSpaceToScreenSpace", l_engine_world_space_to_screen_space },
|
||||
{ "WorldSpaceToShipSpace", l_engine_world_space_to_ship_space },
|
||||
{ "GetEnumValue", l_engine_get_enum_value },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -336,6 +336,28 @@ static int l_game_attr_system(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attribute: systemView
|
||||
*
|
||||
* The <SystemView> object for the system map view class
|
||||
*
|
||||
* Availability:
|
||||
*
|
||||
* February 2020
|
||||
*
|
||||
* Status:
|
||||
*
|
||||
* experiment
|
||||
*/
|
||||
static int l_game_attr_systemview(lua_State *l)
|
||||
{
|
||||
if (!Pi::game)
|
||||
lua_pushnil(l);
|
||||
else
|
||||
LuaObject<SystemView>::PushToLua(Pi::game->GetSystemView());
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attribute: time
|
||||
*
|
||||
|
@ -613,7 +635,7 @@ static int l_game_get_hyperspace_travelled_percentage(lua_State *l)
|
|||
|
||||
static int l_game_get_parts_from_date_time(lua_State *l)
|
||||
{
|
||||
float time = LuaPull<float>(l, 1);
|
||||
double time = LuaPull<double>(l, 1);
|
||||
Time::DateTime t(time);
|
||||
int year, month, day, hour, minute, second;
|
||||
t.GetDateParts(&year, &month, &day);
|
||||
|
@ -662,6 +684,7 @@ void LuaGame::Register()
|
|||
static const luaL_Reg l_attrs[] = {
|
||||
{ "player", l_game_attr_player },
|
||||
{ "system", l_game_attr_system },
|
||||
{ "systemView", l_game_attr_systemview },
|
||||
{ "time", l_game_attr_time },
|
||||
{ "paused", l_game_attr_paused },
|
||||
{ 0, 0 }
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "graphics/Graphics.h"
|
||||
#include "pigui/LuaFlags.h"
|
||||
#include "pigui/PiGui.h"
|
||||
#include "pigui/PiGuiLua.h"
|
||||
#include "ship/PlayerShipController.h"
|
||||
#include "sound/Sound.h"
|
||||
#include "ui/Context.h"
|
||||
|
@ -77,7 +78,7 @@ void pi_lua_generic_pull(lua_State *l, int index, ImVec2 &vec)
|
|||
vec = ImVec2(tr.x, tr.y);
|
||||
}
|
||||
|
||||
int pushOnScreenPositionDirection(lua_State *l, vector3d position)
|
||||
int PiGUI::pushOnScreenPositionDirection(lua_State *l, vector3d position)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
const int width = Graphics::GetScreenWidth();
|
||||
|
@ -1381,7 +1382,7 @@ static int l_pigui_is_mouse_clicked(lua_State *l)
|
|||
static int l_pigui_push_font(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
PiGui *pigui = LuaObject<PiGui>::CheckFromLua(1);
|
||||
PiGui::Instance *pigui = LuaObject<PiGui::Instance>::CheckFromLua(1);
|
||||
std::string fontname = LuaPull<std::string>(l, 2);
|
||||
int size = LuaPull<int>(l, 3);
|
||||
ImFont *font = pigui->GetFont(fontname, size);
|
||||
|
@ -1560,7 +1561,7 @@ static int l_pigui_get_mouse_clicked_pos(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
TScreenSpace lua_world_space_to_screen_space(const vector3d &pos)
|
||||
PiGUI::TScreenSpace PiGUI::lua_world_space_to_screen_space(const vector3d &pos)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
const WorldView *wv = Pi::game->GetWorldView();
|
||||
|
@ -1569,13 +1570,13 @@ TScreenSpace lua_world_space_to_screen_space(const vector3d &pos)
|
|||
const int height = Graphics::GetScreenHeight();
|
||||
const vector3d direction = (p - vector3d(width / 2, height / 2, 0)).Normalized();
|
||||
if (vector3d(0, 0, 0) == p || p.x < 0 || p.y < 0 || p.x > width || p.y > height || p.z > 0) {
|
||||
return TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1));
|
||||
return PiGUI::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1));
|
||||
} else {
|
||||
return TScreenSpace(true, vector2d(p.x, p.y), direction);
|
||||
return PiGUI::TScreenSpace(true, vector2d(p.x, p.y), direction);
|
||||
}
|
||||
}
|
||||
|
||||
TScreenSpace lua_world_space_to_screen_space(const Body *body)
|
||||
PiGUI::TScreenSpace lua_world_space_to_screen_space(const Body *body)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
const WorldView *wv = Pi::game->GetWorldView();
|
||||
|
@ -1584,13 +1585,13 @@ TScreenSpace lua_world_space_to_screen_space(const Body *body)
|
|||
const int height = Graphics::GetScreenHeight();
|
||||
const vector3d direction = (p - vector3d(width / 2, height / 2, 0)).Normalized();
|
||||
if (vector3d(0, 0, 0) == p || p.x < 0 || p.y < 0 || p.x > width || p.y > height || p.z > 0) {
|
||||
return TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1));
|
||||
return PiGUI::TScreenSpace(false, vector2d(0, 0), direction * (p.z > 0 ? -1 : 1));
|
||||
} else {
|
||||
return TScreenSpace(true, vector2d(p.x, p.y), direction);
|
||||
return PiGUI::TScreenSpace(true, vector2d(p.x, p.y), direction);
|
||||
}
|
||||
}
|
||||
|
||||
bool first_body_is_more_important_than(Body *body, Body *other)
|
||||
bool PiGUI::first_body_is_more_important_than(Body *body, Body *other)
|
||||
{
|
||||
|
||||
Object::Type a = body->GetType();
|
||||
|
@ -1720,7 +1721,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l)
|
|||
const double cluster_size = LuaPull<double>(l, 1);
|
||||
const double ship_max_distance = LuaPull<double>(l, 2);
|
||||
|
||||
TSS_vector filtered;
|
||||
PiGUI::TSS_vector filtered;
|
||||
filtered.reserve(Pi::game->GetSpace()->GetNumBodies());
|
||||
|
||||
for (Body *body : Pi::game->GetSpace()->GetBodies()) {
|
||||
|
@ -1728,7 +1729,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l)
|
|||
if (body->GetType() == Object::PROJECTILE) continue;
|
||||
if (body->GetType() == Object::SHIP &&
|
||||
body->GetPositionRelTo(Pi::player).Length() > ship_max_distance) continue;
|
||||
const TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp
|
||||
const PiGUI::TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp
|
||||
if (!res._onScreen) continue;
|
||||
filtered.emplace_back(res);
|
||||
filtered.back()._body = body;
|
||||
|
@ -1757,7 +1758,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l)
|
|||
const Body *combat_target = Pi::game->GetPlayer()->GetCombatTarget();
|
||||
const Body *setspeed_target = Pi::game->GetPlayer()->GetSetSpeedTarget();
|
||||
|
||||
for (TScreenSpace &obj : filtered) {
|
||||
for (PiGUI::TScreenSpace &obj : filtered) {
|
||||
bool inserted = false;
|
||||
|
||||
// never collapse combat target
|
||||
|
@ -1773,7 +1774,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l)
|
|||
group.m_hasNavTarget = true;
|
||||
group.m_mainBody = obj._body;
|
||||
group.m_screenCoords = obj._screenPosition;
|
||||
} else if (!group.m_hasNavTarget && first_body_is_more_important_than(obj._body, group.m_mainBody)) {
|
||||
} else if (!group.m_hasNavTarget && PiGUI::first_body_is_more_important_than(obj._body, group.m_mainBody)) {
|
||||
group.m_mainBody = obj._body;
|
||||
group.m_screenCoords = obj._screenPosition;
|
||||
}
|
||||
|
@ -1797,7 +1798,7 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l)
|
|||
for (GroupInfo &group : groups) {
|
||||
std::sort(begin(group.m_bodies), end(group.m_bodies),
|
||||
[](Body *a, Body *b) {
|
||||
return first_body_is_more_important_than(a, b);
|
||||
return PiGUI::first_body_is_more_important_than(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1826,19 +1827,19 @@ static int l_pigui_get_projected_bodies_grouped(lua_State *l)
|
|||
static int l_pigui_get_projected_bodies(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
TSS_vector filtered;
|
||||
PiGUI::TSS_vector filtered;
|
||||
filtered.reserve(Pi::game->GetSpace()->GetNumBodies());
|
||||
for (Body *body : Pi::game->GetSpace()->GetBodies()) {
|
||||
if (body == Pi::game->GetPlayer()) continue;
|
||||
if (body->GetType() == Object::PROJECTILE) continue;
|
||||
const TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp
|
||||
const PiGUI::TScreenSpace res = lua_world_space_to_screen_space(body); // defined in LuaPiGui.cpp
|
||||
if (!res._onScreen) continue;
|
||||
filtered.emplace_back(res);
|
||||
filtered.back()._body = body;
|
||||
}
|
||||
|
||||
LuaTable result(l, 0, filtered.size());
|
||||
for (TScreenSpace &res : filtered) {
|
||||
for (PiGUI::TScreenSpace &res : filtered) {
|
||||
LuaTable object(l, 0, 3);
|
||||
|
||||
object.Set("onscreen", res._onScreen);
|
||||
|
@ -1941,23 +1942,23 @@ static int l_pigui_should_show_labels(lua_State *l)
|
|||
static int l_attr_handlers(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
PiGui *pigui = LuaObject<PiGui>::CheckFromLua(1);
|
||||
pigui->GetHandlers().PushCopyToStack();
|
||||
PiGui::Instance *pigui = LuaObject<PiGui::Instance>::CheckFromLua(1);
|
||||
PiGUI::GetHandlers().PushCopyToStack();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_attr_keys(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
PiGui *pigui = LuaObject<PiGui>::CheckFromLua(1);
|
||||
pigui->GetKeys().PushCopyToStack();
|
||||
PiGui::Instance *pigui = LuaObject<PiGui::Instance>::CheckFromLua(1);
|
||||
PiGUI::GetKeys().PushCopyToStack();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_attr_screen_width(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// PiGui *pigui = LuaObject<PiGui>::CheckFromLua(1);
|
||||
// PiGui::Instance *pigui = LuaObject<PiGui::Instance>::CheckFromLua(1);
|
||||
LuaPush<int>(l, Graphics::GetScreenWidth());
|
||||
return 1;
|
||||
}
|
||||
|
@ -1993,7 +1994,7 @@ static int l_attr_key_alt(lua_State *l)
|
|||
static int l_attr_screen_height(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// PiGui *pigui = LuaObject<PiGui>::CheckFromLua(1);
|
||||
// PiGui::Instance *pigui = LuaObject<PiGui::Instance>::CheckFromLua(1);
|
||||
LuaPush<int>(l, Graphics::GetScreenHeight());
|
||||
return 1;
|
||||
}
|
||||
|
@ -2365,11 +2366,11 @@ static int l_pigui_add_convex_poly_filled(lua_State *l)
|
|||
static int l_pigui_load_texture_from_svg(lua_State *l)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
PiGui *pigui = LuaObject<PiGui>::CheckFromLua(1);
|
||||
PiGui::Instance *pigui = LuaObject<PiGui::Instance>::CheckFromLua(1);
|
||||
std::string svg_filename = LuaPull<std::string>(l, 2);
|
||||
int width = LuaPull<int>(l, 3);
|
||||
int height = LuaPull<int>(l, 4);
|
||||
ImTextureID id = pigui->RenderSVG(svg_filename, width, height);
|
||||
ImTextureID id = PiGui::RenderSVG(Pi::renderer, svg_filename, width, height);
|
||||
// LuaPush(l, id);
|
||||
lua_pushlightuserdata(l, id);
|
||||
return 1;
|
||||
|
@ -2467,11 +2468,21 @@ static int l_pigui_push_text_wrap_pos(lua_State *l)
|
|||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *LuaObject<PiGui>::s_type = "PiGui";
|
||||
void PiGUI::RunHandler(double delta, std::string handler)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ScopedTable t(GetHandlers());
|
||||
if (t.Get<bool>(handler)) {
|
||||
t.Call<bool>(handler, delta);
|
||||
Pi::renderer->CheckRenderErrors(__FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void LuaObject<PiGui>::RegisterClass()
|
||||
const char *LuaObject<PiGui::Instance>::s_type = "PiGui";
|
||||
|
||||
template <>
|
||||
void LuaObject<PiGui::Instance>::RegisterClass()
|
||||
{
|
||||
static const luaL_Reg l_methods[] = {
|
||||
{ "Begin", l_pigui_begin },
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#ifndef _LUAPIGUI_H
|
||||
#define _LUAPIGUI_H
|
||||
|
||||
#include "LuaObject.h"
|
||||
#include "LuaPushPull.h"
|
||||
|
||||
|
@ -11,19 +12,25 @@
|
|||
|
||||
class Body;
|
||||
|
||||
bool first_body_is_more_important_than(Body* body, Body* other);
|
||||
namespace PiGUI {
|
||||
bool first_body_is_more_important_than(Body *body, Body *other);
|
||||
|
||||
struct TScreenSpace
|
||||
{
|
||||
TScreenSpace(const bool onScreen, const vector2d &screenPos, const vector3d &direction) : _onScreen(onScreen), _screenPosition(screenPos), _direction(direction) {}
|
||||
bool _onScreen;
|
||||
vector2d _screenPosition;
|
||||
vector3d _direction;
|
||||
Body *_body;
|
||||
};
|
||||
struct TScreenSpace {
|
||||
TScreenSpace(const bool onScreen, const vector2d &screenPos, const vector3d &direction) :
|
||||
_onScreen(onScreen), _screenPosition(screenPos), _direction(direction) {}
|
||||
bool _onScreen;
|
||||
vector2d _screenPosition;
|
||||
vector3d _direction;
|
||||
Body *_body;
|
||||
};
|
||||
|
||||
typedef std::vector<TScreenSpace> TSS_vector;
|
||||
typedef std::vector<TScreenSpace> TSS_vector;
|
||||
|
||||
int pushOnScreenPositionDirection(lua_State *l, vector3d position);
|
||||
TScreenSpace lua_world_space_to_screen_space(const vector3d &pos);
|
||||
|
||||
// Run a lua PiGui handler.
|
||||
void RunHandler(double delta, std::string handler = "GAME");
|
||||
} // namespace PiGUI
|
||||
|
||||
int pushOnScreenPositionDirection(lua_State *l, vector3d position);
|
||||
TScreenSpace lua_world_space_to_screen_space(const vector3d &pos);
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "LuaObject.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "SectorView.h"
|
||||
#include "Space.h"
|
||||
#include "galaxy/Galaxy.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
|
@ -655,6 +656,27 @@ static int l_sbody_attr_children(lua_State *l)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int l_sbody_attr_is_moon(lua_State *l)
|
||||
{
|
||||
LuaPush<bool>(l, LuaObject<SystemBody>::CheckFromLua(1)->IsMoon());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_sbody_attr_physics_body(lua_State *l)
|
||||
{
|
||||
SystemBody *b = LuaObject<SystemBody>::CheckFromLua(1);
|
||||
Body *physbody = nullptr;
|
||||
SystemPath headpath = Pi::game->GetSectorView()->GetSelected().SystemOnly();
|
||||
SystemPath gamepath = Pi::game->GetSpace()->GetStarSystem()->GetPath();
|
||||
if (headpath == gamepath) {
|
||||
RefCountedPtr<StarSystem> ss = Pi::game->GetGalaxy()->GetStarSystem(headpath);
|
||||
SystemPath path = ss->GetPathOf(b);
|
||||
physbody = Pi::game->GetSpace()->FindBodyForPath(&path);
|
||||
}
|
||||
LuaObject<Body>::PushToLua(physbody);
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *LuaObject<SystemBody>::s_type = "SystemBody";
|
||||
|
||||
|
@ -694,6 +716,8 @@ void LuaObject<SystemBody>::RegisterClass()
|
|||
{ "path", l_sbody_attr_path },
|
||||
{ "body", l_sbody_attr_body },
|
||||
{ "children", l_sbody_attr_children },
|
||||
{ "isMoon", l_sbody_attr_is_moon },
|
||||
{ "physicsBody", l_sbody_attr_physics_body },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,436 @@
|
|||
// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "EnumStrings.h"
|
||||
#include "Game.h"
|
||||
#include "LuaColor.h"
|
||||
#include "LuaObject.h"
|
||||
#include "LuaVector.h"
|
||||
#include "LuaVector2.h"
|
||||
#include "Pi.h"
|
||||
#include "Player.h"
|
||||
#include "SystemView.h"
|
||||
#include "graphics/Graphics.h"
|
||||
|
||||
LuaTable projectable_to_lua_row(Projectable &p, lua_State *l)
|
||||
{
|
||||
LuaTable proj_table(l, 0, 3);
|
||||
proj_table.Set("type", int(p.type));
|
||||
if (p.type == Projectable::NONE) return proj_table;
|
||||
proj_table.Set("base", int(p.base));
|
||||
if (p.base == Projectable::SYSTEMBODY)
|
||||
proj_table.Set("ref", const_cast<SystemBody *>(p.ref.sbody));
|
||||
else
|
||||
proj_table.Set("ref", const_cast<Body *>(p.ref.body));
|
||||
return proj_table;
|
||||
}
|
||||
|
||||
static int l_systemview_set_color(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
auto color_index = static_cast<SystemView::ColorIndex>(EnumStrings::GetValue("SystemViewColorIndex", LuaPull<const char *>(l, 2)));
|
||||
auto color_value = LuaColor::CheckFromLua(l, 3);
|
||||
sv->SetColor(color_index, color_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_systemview_set_selected_object(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
Projectable::types type = static_cast<Projectable::types>(luaL_checkinteger(l, 2));
|
||||
Projectable::bases base = static_cast<Projectable::bases>(luaL_checkinteger(l, 3));
|
||||
if (base == Projectable::SYSTEMBODY)
|
||||
sv->SetSelectedObject(type, base, LuaObject<SystemBody>::CheckFromLua(4));
|
||||
else
|
||||
sv->SetSelectedObject(type, base, LuaObject<Body>::CheckFromLua(4));
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool too_near(const vector3d &a, const vector3d &b, const vector2d &gain)
|
||||
{
|
||||
return std::abs(a.x - b.x) < gain.x && std::abs(a.y - b.y) < gain.y
|
||||
// we don’t want to group objects that simply overlap and are located at different distances
|
||||
// therefore, depth is also taken into account, we have z_NDC (normalized device coordinates)
|
||||
// in order to make a strict translation of delta z_NDC into delta "pixels", one also needs to know
|
||||
// the z coordinates in the camera space. I plan to implement this later
|
||||
// at the moment I just picked up a number that works well (6.0)
|
||||
&& std::abs(a.z - b.z) * Graphics::GetScreenWidth() * 6.0 < gain.x;
|
||||
};
|
||||
|
||||
/*
|
||||
* Method: GetProjectedGrouped
|
||||
*
|
||||
* Get a table of projected point objects from the SystemView class, having
|
||||
* previously grouped them.
|
||||
*
|
||||
* In the process of rendering the current frame in a SystemView class, an
|
||||
* array of visible point objects (centers of planets, ships, special points
|
||||
* of orbits) is created. This function creates a lua table based on this
|
||||
* array, after grouping them according to certain criteria.
|
||||
*
|
||||
* Resulting table:
|
||||
*
|
||||
* {
|
||||
* *** ORBIT ICONS (apoapsis, periapsis) ***
|
||||
*
|
||||
* { screenCoordinates: vector2d
|
||||
* mainObject (see struct Projectable in SystemView.h)
|
||||
* { type: Projectable::types
|
||||
* base: Projectable::bases
|
||||
* ref: SystemBody* or Body*
|
||||
* }
|
||||
* objects (if multiple only, main object is duplicated there)
|
||||
* {
|
||||
* {type, base, ref}
|
||||
* {type, base, ref}
|
||||
* ...
|
||||
* }
|
||||
* hasPlayer: boolean
|
||||
* hasCombatTarget: boolean
|
||||
* hasNavTarget: boolean
|
||||
* }
|
||||
* { screencoordinates, mainobject, ... }
|
||||
* { screencoordinates, mainobject, ... }
|
||||
* ...
|
||||
*
|
||||
* *** LAGRANGE ICONS ***
|
||||
* { screenCoordinates, mainObject, ... }
|
||||
* { screenCoordinates, mainObject, ... }
|
||||
* ...
|
||||
*
|
||||
* *** BODY ICONS (stars, planets, ships) ***
|
||||
* { screenCoordinates, mainObject, ... }
|
||||
* { screenCoordinates, mainObject, ... }
|
||||
* ...
|
||||
*
|
||||
* }
|
||||
*
|
||||
*
|
||||
* Availability:
|
||||
*
|
||||
* 2020-03
|
||||
*
|
||||
* Status:
|
||||
*
|
||||
* experimental
|
||||
*/
|
||||
|
||||
static int l_systemview_get_projected_grouped(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
const vector2d gap = LuaPull<vector2d>(l, 2);
|
||||
|
||||
std::vector<Projectable> projected = sv->GetProjected();
|
||||
|
||||
// types of special object
|
||||
const int NOT_SPECIAL = -1;
|
||||
const int SO_PLAYER = 0;
|
||||
const int SO_COMBATTARGET = 1;
|
||||
const int SO_NAVTARGET = 2;
|
||||
const int NUMBER_OF_SO_TYPES = 3;
|
||||
Projectable *special_object[NUMBER_OF_SO_TYPES] = { nullptr, nullptr, nullptr };
|
||||
const char *special_object_lua_name[NUMBER_OF_SO_TYPES] = { "hasPlayer", "hasCombatTarget", "hasNavTarget" };
|
||||
|
||||
struct GroupInfo {
|
||||
Projectable m_mainObject;
|
||||
std::vector<Projectable> m_objects;
|
||||
bool m_hasSpecialObject[NUMBER_OF_SO_TYPES] = { false, false, false };
|
||||
|
||||
GroupInfo(Projectable p) :
|
||||
m_mainObject(p)
|
||||
{
|
||||
m_objects.push_back(p);
|
||||
}
|
||||
};
|
||||
|
||||
// use forward_list to concatenate
|
||||
std::vector<GroupInfo> bodyIcons;
|
||||
std::vector<GroupInfo> orbitIcons;
|
||||
std::vector<GroupInfo> lagrangeIcons;
|
||||
|
||||
const Body *nav_target = Pi::game->GetPlayer()->GetNavTarget();
|
||||
const Body *combat_target = Pi::game->GetPlayer()->GetCombatTarget();
|
||||
const Body *player_body = static_cast<Body *>(Pi::game->GetPlayer());
|
||||
|
||||
for (Projectable &p : projected) {
|
||||
// --- icons---
|
||||
if (p.type == Projectable::APOAPSIS || p.type == Projectable::PERIAPSIS)
|
||||
// orbit icons - just take all
|
||||
orbitIcons.push_back(GroupInfo(p));
|
||||
else if (p.type == Projectable::L4 || p.type == Projectable::L5) {
|
||||
// lagrange icons - take only those who don't intersect with other lagrange icons
|
||||
bool intersect = false;
|
||||
for (GroupInfo &group : lagrangeIcons) {
|
||||
if (too_near(p.screenpos, group.m_mainObject.screenpos, gap)) {
|
||||
intersect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!intersect) lagrangeIcons.push_back(GroupInfo(p));
|
||||
} else {
|
||||
// --- real objects ---
|
||||
int object_type = NOT_SPECIAL;
|
||||
bool inserted = false;
|
||||
// check if p is special object, and remember it's type
|
||||
if (p.base == Projectable::SYSTEMBODY) {
|
||||
if (nav_target && p.ref.sbody == nav_target->GetSystemBody()) object_type = SO_NAVTARGET;
|
||||
//system body can't be a combat target and can't be a player
|
||||
} else {
|
||||
if (nav_target && p.ref.body == nav_target)
|
||||
object_type = SO_NAVTARGET;
|
||||
else if (combat_target && p.ref.body == combat_target)
|
||||
object_type = SO_COMBATTARGET;
|
||||
else if (p.base == Projectable::PLAYER)
|
||||
object_type = SO_PLAYER;
|
||||
}
|
||||
for (GroupInfo &group : bodyIcons) {
|
||||
if (too_near(p.screenpos, group.m_mainObject.screenpos, gap)) {
|
||||
// object inside group boundaries
|
||||
// special object is not added
|
||||
// special objects must be added to nearest group, this group could be not nearest
|
||||
if (object_type == NOT_SPECIAL) {
|
||||
group.m_objects.push_back(p);
|
||||
} else
|
||||
// remember it separately
|
||||
special_object[object_type] = &p;
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inserted) {
|
||||
// object is not inside a group
|
||||
// special object is nearest to itself, so we remember it as a new group
|
||||
// create new group
|
||||
GroupInfo newgroup(p);
|
||||
if (object_type != NOT_SPECIAL) newgroup.m_hasSpecialObject[object_type] = true;
|
||||
bodyIcons.push_back(std::move(newgroup));
|
||||
}
|
||||
}
|
||||
} // for (Projectable &p : projected)
|
||||
|
||||
// adding overlapping special object to nearest group
|
||||
for (int object_type = 0; object_type < NUMBER_OF_SO_TYPES; object_type++)
|
||||
if (special_object[object_type]) {
|
||||
std::vector<GroupInfo *> touchedGroups;
|
||||
// first we get all groups, touched this object
|
||||
for (GroupInfo &group : bodyIcons)
|
||||
if (too_near(special_object[object_type]->screenpos, group.m_mainObject.screenpos, gap))
|
||||
// object inside group boundaries: remember this group
|
||||
touchedGroups.push_back(&group);
|
||||
//now select the nearest group (if have)
|
||||
if (touchedGroups.size()) {
|
||||
GroupInfo *nearest;
|
||||
double min_length = 1e64;
|
||||
for (GroupInfo *&g : touchedGroups) {
|
||||
double this_length = (g->m_mainObject.screenpos - special_object[object_type]->screenpos).Length();
|
||||
if (this_length < min_length) {
|
||||
nearest = g;
|
||||
min_length = this_length;
|
||||
}
|
||||
}
|
||||
nearest->m_hasSpecialObject[object_type] = true;
|
||||
nearest->m_objects.push_back(*special_object[object_type]);
|
||||
} else {
|
||||
//don't touching any group, create a new one
|
||||
GroupInfo newgroup(*special_object[object_type]);
|
||||
newgroup.m_hasSpecialObject[object_type] = true;
|
||||
bodyIcons.push_back(std::move(newgroup));
|
||||
}
|
||||
}
|
||||
|
||||
//no need to sort, because the bodies are so recorded in good order
|
||||
//because they are written recursively starting from the root
|
||||
//body of the system, and ships go after the system bodies
|
||||
|
||||
LuaTable result(l, orbitIcons.size() + lagrangeIcons.size() + bodyIcons.size(), 0);
|
||||
int index = 1;
|
||||
//the sooner is displayed, the more in the background
|
||||
// so it goes orbitIcons->lagrangeIcons->bodies
|
||||
for (auto groups : { orbitIcons, lagrangeIcons, bodyIcons }) {
|
||||
for (GroupInfo &group : groups) {
|
||||
LuaTable info_table(l, 0, 6);
|
||||
info_table.Set("screenCoordinates", group.m_mainObject.screenpos);
|
||||
info_table.Set("mainObject", projectable_to_lua_row(group.m_mainObject, l));
|
||||
lua_pop(l, 1);
|
||||
if (group.m_objects.size() > 1) {
|
||||
LuaTable objects_table(l, group.m_objects.size(), 0);
|
||||
int objects_table_index = 1;
|
||||
for (Projectable &pj : group.m_objects) {
|
||||
objects_table.Set(objects_table_index++, projectable_to_lua_row(pj, l));
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
info_table.Set("objects", objects_table);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
for (int object_type = 0; object_type < NUMBER_OF_SO_TYPES; object_type++)
|
||||
info_table.Set(special_object_lua_name[object_type], group.m_hasSpecialObject[object_type]);
|
||||
result.Set(index++, info_table);
|
||||
lua_pop(l, 1);
|
||||
}
|
||||
}
|
||||
LuaPush(l, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_systemview_get_selected_object(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
Projectable *p = sv->GetSelectedObject();
|
||||
LuaPush(l, projectable_to_lua_row(*p, l));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_systemview_set_visibility(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
sv->SetVisibility(LuaPull<std::string>(l, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_systemview_get_orbit_planner_start_time(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
double t = sv->GetOrbitPlannerStartTime();
|
||||
if (std::fabs(t) < 1.)
|
||||
lua_pushnil(l);
|
||||
else
|
||||
LuaPush<double>(l, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_systemview_get_orbit_planner_time(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
double t = sv->GetOrbitPlannerTime();
|
||||
LuaPush<double>(l, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_systemview_accelerate_time(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
if (lua_isnil(l, 2))
|
||||
sv->SetRealTime();
|
||||
else {
|
||||
double step = LuaPull<double>(l, 2);
|
||||
sv->AccelerateTime(step);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_systemview_set_rotate_mode(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
bool b = LuaPull<bool>(l, 2);
|
||||
sv->SetRotateMode(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_systemview_set_zoom_mode(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
bool b = LuaPull<bool>(l, 2);
|
||||
sv->SetZoomMode(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_systemview_transfer_planner_get(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
std::string key = LuaPull<std::string>(l, 2);
|
||||
|
||||
TransferPlanner *planner = sv->GetTransferPlanner();
|
||||
if (key == "prograde") {
|
||||
LuaPush<double>(l, planner->GetDv(BurnDirection::PROGRADE));
|
||||
} else if (key == "normal") {
|
||||
LuaPush<double>(l, planner->GetDv(BurnDirection::NORMAL));
|
||||
} else if (key == "radial") {
|
||||
LuaPush<double>(l, planner->GetDv(BurnDirection::RADIAL));
|
||||
} else if (key == "starttime") {
|
||||
LuaPush<double>(l, planner->GetStartTime());
|
||||
} else if (key == "factor") {
|
||||
LuaPush<double>(l, planner->GetFactor() * 10); // factor is shown as "x 10"
|
||||
} else {
|
||||
Warning("Unknown transfer planner key %s\n", key.c_str());
|
||||
lua_pushnil(l);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_systemview_transfer_planner_add(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
std::string key = LuaPull<std::string>(l, 2);
|
||||
double delta = LuaPull<double>(l, 3);
|
||||
|
||||
TransferPlanner *planner = sv->GetTransferPlanner();
|
||||
if (key == "prograde") {
|
||||
planner->AddDv(BurnDirection::PROGRADE, delta);
|
||||
} else if (key == "normal") {
|
||||
planner->AddDv(BurnDirection::NORMAL, delta);
|
||||
} else if (key == "radial") {
|
||||
planner->AddDv(BurnDirection::RADIAL, delta);
|
||||
} else if (key == "starttime") {
|
||||
planner->AddStartTime(delta);
|
||||
} else if (key == "factor") {
|
||||
if (delta > 0)
|
||||
planner->IncreaseFactor();
|
||||
else
|
||||
planner->DecreaseFactor();
|
||||
} else {
|
||||
Warning("Unknown transfer planner key %s\n", key.c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_systemview_transfer_planner_reset(lua_State *l)
|
||||
{
|
||||
SystemView *sv = LuaObject<SystemView>::CheckFromLua(1);
|
||||
std::string key = LuaPull<std::string>(l, 2);
|
||||
|
||||
TransferPlanner *planner = sv->GetTransferPlanner();
|
||||
if (key == "prograde") {
|
||||
planner->ResetDv(BurnDirection::PROGRADE);
|
||||
} else if (key == "normal") {
|
||||
planner->ResetDv(BurnDirection::NORMAL);
|
||||
} else if (key == "radial") {
|
||||
planner->ResetDv(BurnDirection::RADIAL);
|
||||
} else if (key == "starttime") {
|
||||
planner->ResetStartTime();
|
||||
} else if (key == "factor") {
|
||||
planner->ResetFactor();
|
||||
} else {
|
||||
Warning("Unknown transfer planner key %s\n", key.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
const char *LuaObject<SystemView>::s_type = "SystemView";
|
||||
|
||||
template <>
|
||||
void LuaObject<SystemView>::RegisterClass()
|
||||
{
|
||||
static const luaL_Reg l_methods[] = {
|
||||
|
||||
{ "GetProjectedGrouped", l_systemview_get_projected_grouped },
|
||||
{ "GetSelectedObject", l_systemview_get_selected_object },
|
||||
{ "GetOrbitPlannerStartTime", l_systemview_get_orbit_planner_start_time },
|
||||
{ "GetOrbitPlannerTime", l_systemview_get_orbit_planner_time },
|
||||
{ "AccelerateTime", l_systemview_accelerate_time },
|
||||
{ "SetSelectedObject", l_systemview_set_selected_object },
|
||||
{ "SetVisibility", l_systemview_set_visibility },
|
||||
{ "SetColor", l_systemview_set_color },
|
||||
{ "SetRotateMode", l_systemview_set_rotate_mode },
|
||||
{ "SetZoomMode" , l_systemview_set_zoom_mode },
|
||||
|
||||
{ "TransferPlannerAdd", l_systemview_transfer_planner_add },
|
||||
{ "TransferPlannerGet", l_systemview_transfer_planner_get },
|
||||
{ "TransferPlannerReset", l_systemview_transfer_planner_reset },
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
LuaObjectBase::CreateClass(s_type, nullptr, l_methods, 0, 0);
|
||||
}
|
|
@ -205,7 +205,9 @@ start:
|
|||
std::string modelName;
|
||||
if (argc > 2)
|
||||
modelName = argv[2];
|
||||
ModelViewer::Run(modelName);
|
||||
auto modelViewer = ModelViewerApp();
|
||||
modelViewer.SetInitialModel(modelName);
|
||||
modelViewer.Run();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#define PIGUI_FACE_H
|
||||
|
||||
#include "FaceParts.h"
|
||||
#include "SmartPtr.h"
|
||||
#include "Pi.h"
|
||||
#include "SmartPtr.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Texture.h"
|
||||
|
||||
|
@ -14,12 +14,12 @@ namespace PiGUI {
|
|||
|
||||
class Face : public RefCounted {
|
||||
public:
|
||||
Face(FaceParts::FaceDescriptor& face, Uint32 seed = 0);
|
||||
Face(FaceParts::FaceDescriptor &face, Uint32 seed = 0);
|
||||
|
||||
Uint32 GetTextureId();
|
||||
vector2f GetTextureSize();
|
||||
|
||||
enum Flags { // <enum scope='GameUI::Face' name=GameUIFaceFlags public>
|
||||
enum Flags { // <enum scope='PiGUI::Face' name=PiGUIFaceFlags public>
|
||||
RAND = 0,
|
||||
MALE = (1 << 0),
|
||||
FEMALE = (1 << 1),
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include "Input.h"
|
||||
#include "Pi.h"
|
||||
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/opengl/RendererGL.h"
|
||||
#include "graphics/opengl/TextureGL.h" // nasty, usage of GL is implementation specific
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
|
@ -12,9 +15,6 @@
|
|||
#define IMGUI_IMPL_OPENGL_LOADER_GLEW 1
|
||||
#include "imgui/examples/imgui_impl_opengl3.h"
|
||||
#include "imgui/examples/imgui_impl_sdl.h"
|
||||
// to get ImVec2 + ImVec2
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS true
|
||||
#include "imgui/imgui_internal.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
|
@ -24,38 +24,36 @@
|
|||
#define NANOSVGRAST_IMPLEMENTATION
|
||||
#include "nanosvg/nanosvgrast.h"
|
||||
|
||||
std::vector<Graphics::Texture *> PiGui::m_svg_textures;
|
||||
using namespace PiGui;
|
||||
|
||||
static int to_keycode(int key)
|
||||
std::vector<Graphics::Texture *> m_svg_textures;
|
||||
|
||||
std::vector<Graphics::Texture *> &PiGui::GetSVGTextures()
|
||||
{
|
||||
/*if(key & SDLK_SCANCODE_MASK) {
|
||||
return (key & ~SDLK_SCANCODE_MASK) | 0x100;
|
||||
}*/
|
||||
return key;
|
||||
return m_svg_textures;
|
||||
}
|
||||
|
||||
static std::vector<std::pair<std::string, int>> keycodes = {
|
||||
{ "left", to_keycode(SDLK_LEFT) },
|
||||
{ "right", to_keycode(SDLK_RIGHT) },
|
||||
{ "up", to_keycode(SDLK_UP) },
|
||||
{ "down", to_keycode(SDLK_DOWN) },
|
||||
{ "escape", to_keycode(SDLK_ESCAPE) },
|
||||
{ "f1", to_keycode(SDLK_F1) },
|
||||
{ "f2", to_keycode(SDLK_F2) },
|
||||
{ "f3", to_keycode(SDLK_F3) },
|
||||
{ "f4", to_keycode(SDLK_F4) },
|
||||
{ "f5", to_keycode(SDLK_F5) },
|
||||
{ "f6", to_keycode(SDLK_F6) },
|
||||
{ "f7", to_keycode(SDLK_F7) },
|
||||
{ "f8", to_keycode(SDLK_F8) },
|
||||
{ "f9", to_keycode(SDLK_F9) },
|
||||
{ "f10", to_keycode(SDLK_F10) },
|
||||
{ "f11", to_keycode(SDLK_F11) },
|
||||
{ "f12", to_keycode(SDLK_F12) },
|
||||
{ "tab", to_keycode(SDLK_TAB) },
|
||||
};
|
||||
static ImTextureID makeTexture(Graphics::Renderer *renderer, unsigned char *pixels, int width, int height)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// this is not very pretty code
|
||||
// Texture descriptor defines the size, type.
|
||||
// Gone for LINEAR_CLAMP here and RGBA like the original code
|
||||
const vector2f texSize(1.0f, 1.0f);
|
||||
const vector3f dataSize(width, height, 0.0f);
|
||||
const Graphics::TextureDescriptor texDesc(Graphics::TEXTURE_RGBA_8888,
|
||||
dataSize, texSize, Graphics::LINEAR_CLAMP,
|
||||
false, false, false, 0, Graphics::TEXTURE_2D);
|
||||
// Create the texture, calling it via renderer directly avoids the caching call of TextureBuilder
|
||||
// However interestingly this gets called twice which would have been a WIN for the TextureBuilder :/
|
||||
Graphics::Texture *pTex = renderer->CreateTexture(texDesc);
|
||||
// Update it with the actual pixels, this is a two step process due to legacy code
|
||||
pTex->Update(pixels, dataSize, Graphics::TEXTURE_RGBA_8888);
|
||||
PiGui::GetSVGTextures().push_back(pTex); // store for cleanup later
|
||||
return reinterpret_cast<ImTextureID>(uintptr_t(pTex->GetTextureID()));
|
||||
}
|
||||
|
||||
ImTextureID PiGui::RenderSVG(std::string svgFilename, int width, int height)
|
||||
ImTextureID PiGui::RenderSVG(Graphics::Renderer *renderer, std::string svgFilename, int width, int height)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
Output("nanosvg: %s %dx%d\n", svgFilename.c_str(), width, height);
|
||||
|
@ -111,10 +109,44 @@ ImTextureID PiGui::RenderSVG(std::string svgFilename, int width, int height)
|
|||
}
|
||||
nsvgDeleteRasterizer(rast);
|
||||
nsvgDelete(image);
|
||||
return makeTexture(img, W, H);
|
||||
return makeTexture(renderer, img, W, H);
|
||||
}
|
||||
|
||||
ImFont *PiGui::GetFont(const std::string &name, int size)
|
||||
//
|
||||
// PiGui::Instance
|
||||
//
|
||||
|
||||
Instance::Instance() :
|
||||
m_should_bake_fonts(true)
|
||||
{
|
||||
// TODO: clang-format doesn't like list initializers inside function calls
|
||||
// clang-format off
|
||||
PiFont uiheading("orbiteer", {
|
||||
PiFace("DejaVuSans.ttf", /*18.0/20.0*/ 1.2),
|
||||
PiFace("wqy-microhei.ttc", 1.0),
|
||||
PiFace("Orbiteer-Bold.ttf", 1.0) // imgui only supports 0xffff, not 0x10ffff
|
||||
});
|
||||
AddFontDefinition(uiheading);
|
||||
|
||||
PiFont guifont("pionillium", {
|
||||
PiFace("DejaVuSans.ttf", 13.0 / 14.0),
|
||||
PiFace("wqy-microhei.ttc", 1.0),
|
||||
PiFace("PionilliumText22L-Medium.ttf", 1.0)
|
||||
});
|
||||
AddFontDefinition(guifont);
|
||||
// clang-format on
|
||||
|
||||
// Output("Fonts:\n");
|
||||
for (auto entry : m_font_definitions) {
|
||||
// Output(" entry %s:\n", entry.first.c_str());
|
||||
entry.second.describe();
|
||||
}
|
||||
|
||||
// ensure the tooltip font exists
|
||||
GetFont("pionillium", 14);
|
||||
};
|
||||
|
||||
ImFont *Instance::GetFont(const std::string &name, int size)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
auto iter = m_fonts.find(std::make_pair(name, size));
|
||||
|
@ -126,7 +158,7 @@ ImFont *PiGui::GetFont(const std::string &name, int size)
|
|||
return font;
|
||||
}
|
||||
|
||||
void PiGui::AddGlyph(ImFont *font, unsigned short glyph)
|
||||
void Instance::AddGlyph(ImFont *font, unsigned short glyph)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// range glyph..glyph
|
||||
|
@ -151,7 +183,7 @@ void PiGui::AddGlyph(ImFont *font, unsigned short glyph)
|
|||
Error("No face in font %s handles glyph %i\n", pifont.name().c_str(), glyph);
|
||||
}
|
||||
|
||||
ImFont *PiGui::AddFont(const std::string &name, int size)
|
||||
ImFont *Instance::AddFont(const std::string &name, int size)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
auto iter = m_font_definitions.find(name);
|
||||
|
@ -175,7 +207,7 @@ ImFont *PiGui::AddFont(const std::string &name, int size)
|
|||
return m_fonts[std::make_pair(name, size)];
|
||||
}
|
||||
|
||||
void PiGui::RefreshFontsTexture()
|
||||
void Instance::RefreshFontsTexture()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// TODO: fix this, do the right thing, don't just re-create *everything* :)
|
||||
|
@ -189,21 +221,11 @@ void PiDefaultStyle(ImGuiStyle &style)
|
|||
style.WindowBorderSize = 0.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
|
||||
}
|
||||
|
||||
void PiGui::Init(SDL_Window *window)
|
||||
// TODO: this isn't very RAII friendly, are we sure we need to call Init() seperately from creating the instance?
|
||||
void Instance::Init(Graphics::Renderer *renderer)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
m_handlers.Unref();
|
||||
|
||||
lua_State *l = Lua::manager->GetLuaState();
|
||||
lua_newtable(l);
|
||||
m_handlers = LuaRef(l, -1);
|
||||
|
||||
lua_newtable(l);
|
||||
m_keys = LuaRef(l, -1);
|
||||
LuaTable keys(l, -1);
|
||||
for (auto p : keycodes) {
|
||||
keys.Set(p.first, p.second);
|
||||
}
|
||||
m_renderer = renderer;
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
@ -211,14 +233,18 @@ void PiGui::Init(SDL_Window *window)
|
|||
// TODO: FIXME before upgrading! The sdl_gl_context parameter is currently
|
||||
// unused, but that is slated to change very soon.
|
||||
// We will need to fill this with a valid pointer to the OpenGL context.
|
||||
ImGui_ImplSDL2_InitForOpenGL(window, NULL);
|
||||
switch (Pi::renderer->GetRendererType()) {
|
||||
ImGui_ImplSDL2_InitForOpenGL(m_renderer->GetSDLWindow(), NULL);
|
||||
switch (m_renderer->GetRendererType()) {
|
||||
default:
|
||||
case Graphics::RENDERER_DUMMY:
|
||||
Error("RENDERER_DUMMY is not a valid renderer, aborting.");
|
||||
return;
|
||||
case Graphics::RENDERER_OPENGL_3x:
|
||||
#ifdef __APPLE__
|
||||
ImGui_ImplOpenGL3_Init("#version 140");
|
||||
#else
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -237,156 +263,18 @@ void PiGui::Init(SDL_Window *window)
|
|||
io.IniFilename = ioIniFilename;
|
||||
}
|
||||
|
||||
int PiGui::RadialPopupSelectMenu(const ImVec2 ¢er, std::string popup_id, int mouse_button, std::vector<ImTextureID> tex_ids, std::vector<std::pair<ImVec2, ImVec2>> uvs, unsigned int size, std::vector<std::string> tooltips)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// return:
|
||||
// 0 - n for item selected
|
||||
// -1 for nothing chosen, but menu open
|
||||
// -2 for menu closed without an icon chosen
|
||||
// -3 for menu not open
|
||||
int ret = -3;
|
||||
|
||||
// FIXME: Missing a call to query if Popup is open so we can move the PushStyleColor inside the BeginPopupBlock (e.g. IsPopupOpen() in imgui.cpp)
|
||||
// FIXME: Our PathFill function only handle convex polygons, so we can't have items spanning an arc too large else inner concave edge artifact is too visible, hence the ImMax(7,items_count)
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::BeginPopup(popup_id.c_str())) {
|
||||
ret = -1;
|
||||
const ImVec2 drag_delta = ImVec2(ImGui::GetIO().MousePos.x - center.x, ImGui::GetIO().MousePos.y - center.y);
|
||||
const float drag_dist2 = drag_delta.x * drag_delta.x + drag_delta.y * drag_delta.y;
|
||||
|
||||
const ImGuiStyle &style = ImGui::GetStyle();
|
||||
const float RADIUS_MIN = 20.0f;
|
||||
const float RADIUS_MAX = 90.0f;
|
||||
const float RADIUS_INTERACT_MIN = 20.0f;
|
||||
const int ITEMS_MIN = 4;
|
||||
const float border_inout = 12.0f;
|
||||
const float border_thickness = 4.0f;
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->PushClipRectFullScreen();
|
||||
draw_list->PathArcTo(center, (RADIUS_MIN + RADIUS_MAX) * 0.5f, 0.0f, IM_PI * 2.0f * 0.99f, 64); // FIXME: 0.99f look like full arc with closed thick stroke has a bug now
|
||||
draw_list->PathStroke(ImColor(18, 44, 67, 210), true, RADIUS_MAX - RADIUS_MIN);
|
||||
|
||||
const float item_arc_span = 2 * IM_PI / ImMax<int>(ITEMS_MIN, tex_ids.size());
|
||||
float drag_angle = atan2f(drag_delta.y, drag_delta.x);
|
||||
if (drag_angle < -0.5f * item_arc_span)
|
||||
drag_angle += 2.0f * IM_PI;
|
||||
|
||||
int item_hovered = -1;
|
||||
int item_n = 0;
|
||||
for (ImTextureID tex_id : tex_ids) {
|
||||
const char *tooltip = tooltips.at(item_n).c_str();
|
||||
const float inner_spacing = style.ItemInnerSpacing.x / RADIUS_MIN / 2;
|
||||
const float item_inner_ang_min = item_arc_span * (item_n - 0.5f + inner_spacing);
|
||||
const float item_inner_ang_max = item_arc_span * (item_n + 0.5f - inner_spacing);
|
||||
const float item_outer_ang_min = item_arc_span * (item_n - 0.5f + inner_spacing * (RADIUS_MIN / RADIUS_MAX));
|
||||
const float item_outer_ang_max = item_arc_span * (item_n + 0.5f - inner_spacing * (RADIUS_MIN / RADIUS_MAX));
|
||||
|
||||
bool hovered = false;
|
||||
if (drag_dist2 >= RADIUS_INTERACT_MIN * RADIUS_INTERACT_MIN) {
|
||||
if (drag_angle >= item_inner_ang_min && drag_angle < item_inner_ang_max)
|
||||
hovered = true;
|
||||
}
|
||||
bool selected = false;
|
||||
|
||||
int arc_segments = static_cast<int>((64 * item_arc_span / (2 * IM_PI))) + 1;
|
||||
draw_list->PathArcTo(center, RADIUS_MAX - border_inout, item_outer_ang_min, item_outer_ang_max, arc_segments);
|
||||
draw_list->PathArcTo(center, RADIUS_MIN + border_inout, item_inner_ang_max, item_inner_ang_min, arc_segments);
|
||||
|
||||
draw_list->PathFillConvex(hovered ? ImColor(102, 147, 189) : selected ? ImColor(48, 81, 111) : ImColor(48, 81, 111));
|
||||
if (hovered) {
|
||||
// draw outer / inner extra segments
|
||||
draw_list->PathArcTo(center, RADIUS_MAX - border_thickness, item_outer_ang_min, item_outer_ang_max, arc_segments);
|
||||
draw_list->PathStroke(ImColor(102, 147, 189), false, border_thickness);
|
||||
draw_list->PathArcTo(center, RADIUS_MIN + border_thickness, item_outer_ang_min, item_outer_ang_max, arc_segments);
|
||||
draw_list->PathStroke(ImColor(102, 147, 189), false, border_thickness);
|
||||
}
|
||||
ImVec2 text_size = ImVec2(size, size);
|
||||
ImVec2 text_pos = ImVec2(
|
||||
center.x + cosf((item_inner_ang_min + item_inner_ang_max) * 0.5f) * (RADIUS_MIN + RADIUS_MAX) * 0.5f - text_size.x * 0.5f,
|
||||
center.y + sinf((item_inner_ang_min + item_inner_ang_max) * 0.5f) * (RADIUS_MIN + RADIUS_MAX) * 0.5f - text_size.y * 0.5f);
|
||||
draw_list->AddImage(tex_id, text_pos, ImVec2(text_pos.x + size, text_pos.y + size), uvs[item_n].first, uvs[item_n].second);
|
||||
ImGui::SameLine();
|
||||
if (hovered) {
|
||||
item_hovered = item_n;
|
||||
ImGui::SetTooltip("%s", tooltip);
|
||||
}
|
||||
item_n++;
|
||||
}
|
||||
draw_list->PopClipRect();
|
||||
|
||||
if (ImGui::IsMouseReleased(mouse_button)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
if (item_hovered == -1)
|
||||
ret = -2;
|
||||
else
|
||||
ret = item_hovered;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
// Output("WARNING: RadialPopupSelectMenu BeginPopup failed: %s\n", popup_id.c_str());
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PiGui::CircularSlider(const ImVec2 ¢er, float *v, float v_min, float v_max)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID("circularslider");
|
||||
draw_list->AddCircle(center, 17, ImColor(100, 100, 100), 128, 12.0);
|
||||
draw_list->PathArcTo(center, 17, 0, M_PI * 2.0 * (*v - v_min) / (v_max - v_min), 64);
|
||||
draw_list->PathStroke(ImColor(200, 200, 200), false, 12.0);
|
||||
ImRect grab_bb;
|
||||
return ImGui::SliderBehavior(ImRect(center.x - 17, center.y - 17, center.x + 17, center.y + 17),
|
||||
id, ImGuiDataType_Float, v, &v_min, &v_max, "%.4f", 1.0, ImGuiSliderFlags_None, &grab_bb);
|
||||
}
|
||||
|
||||
bool PiGui::ProcessEvent(SDL_Event *event)
|
||||
bool Instance::ProcessEvent(SDL_Event *event)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImGui_ImplSDL2_ProcessEvent(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void *PiGui::makeTexture(unsigned char *pixels, int width, int height)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// this is not very pretty code and uses the Graphics::TextureGL class directly
|
||||
// Texture descriptor defines the size, type.
|
||||
// Gone for LINEAR_CLAMP here and RGBA like the original code
|
||||
const vector2f texSize(1.0f, 1.0f);
|
||||
const vector3f dataSize(width, height, 0.0f);
|
||||
const Graphics::TextureDescriptor texDesc(Graphics::TEXTURE_RGBA_8888,
|
||||
dataSize, texSize, Graphics::LINEAR_CLAMP,
|
||||
false, false, false, 0, Graphics::TEXTURE_2D);
|
||||
// Create the texture, calling it via renderer directly avoids the caching call of TextureBuilder
|
||||
// However interestingly this gets called twice which would have been a WIN for the TextureBuilder :/
|
||||
Graphics::Texture *pTex = Pi::renderer->CreateTexture(texDesc);
|
||||
// Update it with the actual pixels, this is a two step process due to legacy code
|
||||
pTex->Update(pixels, dataSize, Graphics::TEXTURE_RGBA_8888);
|
||||
// nasty bit as I invoke the TextureGL
|
||||
Graphics::OGL::TextureGL *pGLTex = reinterpret_cast<Graphics::OGL::TextureGL *>(pTex);
|
||||
Uint32 result = pGLTex->GetTextureID();
|
||||
m_svg_textures.push_back(pTex); // store for cleanup later
|
||||
return reinterpret_cast<void *>(result);
|
||||
}
|
||||
|
||||
void PiGui::NewFrame(SDL_Window *window)
|
||||
void Instance::NewFrame()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
|
||||
// Ask ImGui to hide OS cursor if we're capturing it for input:
|
||||
// it will do this if GetMouseCursor == ImGuiMouseCursor_None.
|
||||
if (Pi::input->IsCapturingMouse()) {
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
|
||||
}
|
||||
|
||||
switch (Pi::renderer->GetRendererType()) {
|
||||
switch (m_renderer->GetRendererType()) {
|
||||
default:
|
||||
case Graphics::RENDERER_DUMMY:
|
||||
Error("RENDERER_DUMMY is not a valid renderer, aborting.");
|
||||
|
@ -395,24 +283,14 @@ void PiGui::NewFrame(SDL_Window *window)
|
|||
ImGui_ImplOpenGL3_NewFrame();
|
||||
break;
|
||||
}
|
||||
ImGui_ImplSDL2_NewFrame(window);
|
||||
ImGui_ImplSDL2_NewFrame(m_renderer->GetSDLWindow());
|
||||
ImGui::NewFrame();
|
||||
|
||||
Pi::renderer->CheckRenderErrors(__FUNCTION__, __LINE__);
|
||||
m_renderer->CheckRenderErrors(__FUNCTION__, __LINE__);
|
||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow);
|
||||
}
|
||||
|
||||
void PiGui::RunHandler(double delta, std::string handler)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ScopedTable t(m_handlers);
|
||||
if (t.Get<bool>(handler)) {
|
||||
t.Call<bool>(handler, delta);
|
||||
Pi::renderer->CheckRenderErrors(__FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
void PiGui::EndFrame()
|
||||
void Instance::EndFrame()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
|
||||
|
@ -439,14 +317,14 @@ void PiGui::EndFrame()
|
|||
}
|
||||
}
|
||||
|
||||
void PiGui::Render()
|
||||
void Instance::Render()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
EndFrame();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
switch (Pi::renderer->GetRendererType()) {
|
||||
switch (m_renderer->GetRendererType()) {
|
||||
default:
|
||||
case Graphics::RENDERER_DUMMY:
|
||||
return;
|
||||
|
@ -456,7 +334,7 @@ void PiGui::Render()
|
|||
}
|
||||
}
|
||||
|
||||
void PiGui::ClearFonts()
|
||||
void Instance::ClearFonts()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
@ -466,7 +344,7 @@ void PiGui::ClearFonts()
|
|||
io.Fonts->Clear();
|
||||
}
|
||||
|
||||
void PiGui::BakeFont(PiFont &font)
|
||||
void Instance::BakeFont(PiFont &font)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImGuiIO &io = ImGui::GetIO();
|
||||
|
@ -507,7 +385,7 @@ void PiGui::BakeFont(PiFont &font)
|
|||
imfont->MissingGlyphs.clear();
|
||||
}
|
||||
|
||||
void PiGui::BakeFonts()
|
||||
void Instance::BakeFonts()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// Output("Baking fonts\n");
|
||||
|
@ -534,199 +412,14 @@ void PiGui::BakeFonts()
|
|||
RefreshFontsTexture();
|
||||
}
|
||||
|
||||
static void drawThrust(ImDrawList *draw_list, const ImVec2 ¢er, const ImVec2 &up, float value, const ImColor &fg, const ImColor &bg)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
float factor = 0.1; // how much to offset from center
|
||||
const ImVec2 step(up.x * 0.5, up.y * 0.5);
|
||||
const ImVec2 left(-step.y * (1.0 - factor), step.x * (1.0 - factor));
|
||||
const ImVec2 u(up.x * (1.0 - factor), up.y * (1.0 - factor));
|
||||
const ImVec2 c(center + ImVec2(u.x * factor, u.y * factor));
|
||||
const ImVec2 right(-left.x, -left.y);
|
||||
const ImVec2 leftmiddle = c + step + left;
|
||||
const ImVec2 rightmiddle = c + step + right;
|
||||
const ImVec2 bb_lowerright = c + right;
|
||||
const ImVec2 bb_upperleft = c + left + ImVec2(u.x * value, u.y * value);
|
||||
const ImVec2 lefttop = c + u + left;
|
||||
const ImVec2 righttop = c + u + right;
|
||||
const ImVec2 minimum(fmin(bb_upperleft.x, bb_lowerright.x), fmin(bb_upperleft.y, bb_lowerright.y));
|
||||
const ImVec2 maximum(fmax(bb_upperleft.x, bb_lowerright.x), fmax(bb_upperleft.y, bb_lowerright.y));
|
||||
ImVec2 points[] = { c, leftmiddle, lefttop, righttop, rightmiddle };
|
||||
draw_list->AddConvexPolyFilled(points, 5, bg);
|
||||
draw_list->PushClipRect(minimum - ImVec2(1, 1), maximum + ImVec2(1, 1));
|
||||
draw_list->AddConvexPolyFilled(points, 5, fg);
|
||||
draw_list->PopClipRect();
|
||||
}
|
||||
|
||||
void PiGui::ThrustIndicator(const std::string &id_string, const ImVec2 &size_arg, const ImVec4 &thrust, const ImVec4 &velocity, const ImVec4 &bg_col, int frame_padding, ImColor vel_fg, ImColor vel_bg, ImColor thrust_fg, ImColor thrust_bg)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext &g = *GImGui;
|
||||
const ImGuiStyle &style = g.Style;
|
||||
const ImGuiID id = window->GetID(id_string.c_str());
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
// if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
|
||||
// pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
|
||||
ImVec2 size = ImGui::CalcItemSize(size_arg, style.FramePadding.x * 2.0f, style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2(static_cast<float>(frame_padding), static_cast<float>(frame_padding)) : style.FramePadding;
|
||||
const ImRect bb(pos, pos + size + padding * 2);
|
||||
const ImRect inner_bb(pos + padding, pos + padding + size);
|
||||
|
||||
ImGui::ItemSize(bb, style.FramePadding.y);
|
||||
if (!ImGui::ItemAdd(bb, id))
|
||||
return;
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32(static_cast<ImGuiCol>(ImGuiCol_Button));
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
if (bg_col.w > 0.0f)
|
||||
draw_list->AddRectFilled(inner_bb.Min, inner_bb.Max, ImGui::GetColorU32(bg_col));
|
||||
const ImVec2 leftupper = inner_bb.Min;
|
||||
const ImVec2 rightlower = inner_bb.Max;
|
||||
const ImVec2 rightcenter((rightlower.x - leftupper.x) * 0.8 + leftupper.x, (rightlower.y + leftupper.y) / 2);
|
||||
const ImVec2 leftcenter((rightlower.x - leftupper.x) * 0.35 + leftupper.x, (rightlower.y + leftupper.y) / 2);
|
||||
const ImVec2 up(0, -std::abs(leftupper.y - rightlower.y) * 0.4);
|
||||
const ImVec2 left(-up.y, up.x);
|
||||
float thrust_fwd = fmax(thrust.z, 0);
|
||||
float thrust_bwd = fmax(-thrust.z, 0);
|
||||
float thrust_left = fmax(-thrust.x, 0);
|
||||
float thrust_right = fmax(thrust.x, 0);
|
||||
float thrust_up = fmax(-thrust.y, 0);
|
||||
float thrust_down = fmax(thrust.y, 0);
|
||||
// actual thrust
|
||||
drawThrust(draw_list, rightcenter, up, thrust_fwd, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, rightcenter, ImVec2(-up.x, -up.y), thrust_bwd, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, up, thrust_up, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, ImVec2(-up.x, -up.y), thrust_down, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, left, thrust_left, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, ImVec2(-left.x, -left.y), thrust_right, thrust_fg, thrust_bg);
|
||||
// forward/back velocity
|
||||
draw_list->AddLine(rightcenter + up, rightcenter - up, vel_bg, 3);
|
||||
draw_list->AddLine(rightcenter, rightcenter - up * velocity.z, vel_fg, 3);
|
||||
// left/right velocity
|
||||
draw_list->AddLine(leftcenter + left, leftcenter - left, vel_bg, 3);
|
||||
draw_list->AddLine(leftcenter, leftcenter + left * velocity.x, vel_fg, 3);
|
||||
// up/down velocity
|
||||
draw_list->AddLine(leftcenter + up, leftcenter - up, vel_bg, 3);
|
||||
draw_list->AddLine(leftcenter, leftcenter + up * velocity.y, vel_fg, 3);
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
// CloseCurrentPopup();
|
||||
}
|
||||
|
||||
bool PiGui::LowThrustButton(const char *id_string, const ImVec2 &size_arg, int thrust_level, const ImVec4 &bg_col, int frame_padding, ImColor gauge_fg, ImColor gauge_bg)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
std::string label = std::to_string(thrust_level);
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiContext &g = *GImGui;
|
||||
const ImGuiStyle &style = g.Style;
|
||||
const ImGuiID id = window->GetID(id_string);
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(label.c_str(), NULL, true);
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
// if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
|
||||
// pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
|
||||
ImVec2 size = ImGui::CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2(static_cast<float>(frame_padding), static_cast<float>(frame_padding)) : style.FramePadding;
|
||||
const ImRect bb(pos, pos + size + padding * 2);
|
||||
const ImRect inner_bb(pos + padding, pos + padding + size);
|
||||
|
||||
ImGui::ItemSize(bb, style.FramePadding.y);
|
||||
if (!ImGui::ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
// if (window->DC.ButtonRepeat) flags |= ImGuiButtonFlags_Repeat;
|
||||
bool hovered, held;
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0); // flags
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32(static_cast<ImGuiCol>((hovered && held) ? ImGuiCol_ButtonActive : (hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button)));
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||
const ImVec2 center = (inner_bb.Min + inner_bb.Max) / 2;
|
||||
float radius = (inner_bb.Max.x - inner_bb.Min.x) * 0.4;
|
||||
float thickness = 4;
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
if (bg_col.w > 0.0f)
|
||||
draw_list->AddRectFilled(inner_bb.Min, inner_bb.Max, ImGui::GetColorU32(bg_col));
|
||||
|
||||
draw_list->PathArcTo(center, radius, 0, IM_PI * 2, 16);
|
||||
draw_list->PathStroke(gauge_bg, false, thickness);
|
||||
|
||||
draw_list->PathArcTo(center, radius, IM_PI, IM_PI + IM_PI * 2 * (thrust_level / 100.0), 16);
|
||||
draw_list->PathStroke(gauge_fg, false, thickness);
|
||||
ImGui::RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label.c_str(), NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
// CloseCurrentPopup();
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
// frame_padding < 0: uses FramePadding from style (default)
|
||||
// frame_padding = 0: no framing
|
||||
// frame_padding > 0: set framing size
|
||||
// The color used are the button colors.
|
||||
bool PiGui::ButtonImageSized(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &imgSize, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, const ImVec4 &bg_col, const ImVec4 &tint_col)
|
||||
{
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiContext &g = *GImGui;
|
||||
const ImGuiStyle &style = g.Style;
|
||||
|
||||
// Default to using texture ID as ID. User can still push string/integer prefixes.
|
||||
// We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.
|
||||
ImGui::PushID((void *)user_texture_id);
|
||||
const ImGuiID id = window->GetID("#image");
|
||||
ImGui::PopID();
|
||||
|
||||
ImVec2 imgPadding = (size - imgSize) / 2;
|
||||
imgPadding.x = imgPadding.x < 0 || imgSize.x <= 0 ? 0 : imgPadding.x;
|
||||
imgPadding.y = imgPadding.y < 0 || imgSize.y <= 0 ? 0 : imgPadding.y;
|
||||
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
|
||||
const ImRect image_bb(window->DC.CursorPos + padding + imgPadding, window->DC.CursorPos + padding + size - imgPadding);
|
||||
ImGui::ItemSize(bb);
|
||||
if (!ImGui::ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
ImGui::RenderNavHighlight(bb, id);
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
|
||||
if (bg_col.w > 0.0f)
|
||||
window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, ImGui::GetColorU32(bg_col));
|
||||
window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, ImGui::GetColorU32(tint_col));
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
void PiGui::Cleanup()
|
||||
void Instance::Uninit()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
for (auto tex : m_svg_textures) {
|
||||
delete tex;
|
||||
}
|
||||
|
||||
switch (Pi::renderer->GetRendererType()) {
|
||||
switch (m_renderer->GetRendererType()) {
|
||||
default:
|
||||
case Graphics::RENDERER_DUMMY:
|
||||
return;
|
||||
|
@ -739,25 +432,9 @@ void PiGui::Cleanup()
|
|||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
PiGui::PiGui() :
|
||||
m_should_bake_fonts(true)
|
||||
{
|
||||
PiFont uiheading("orbiteer", {
|
||||
PiFace("DejaVuSans.ttf", /*18.0/20.0*/ 1.2), PiFace("wqy-microhei.ttc", 1.0), PiFace("Orbiteer-Bold.ttf", 1.0) // imgui only supports 0xffff, not 0x10ffff
|
||||
});
|
||||
PiFont guifont("pionillium", { PiFace("DejaVuSans.ttf", 13.0 / 14.0), PiFace("wqy-microhei.ttc", 1.0), PiFace("PionilliumText22L-Medium.ttf", 1.0) });
|
||||
AddFontDefinition(uiheading);
|
||||
AddFontDefinition(guifont);
|
||||
|
||||
// Output("Fonts:\n");
|
||||
for (auto entry : m_font_definitions) {
|
||||
// Output(" entry %s:\n", entry.first.c_str());
|
||||
entry.second.describe();
|
||||
}
|
||||
|
||||
// ensure the tooltip font exists
|
||||
GetFont("pionillium", 14);
|
||||
};
|
||||
//
|
||||
// PiGui::PiFace
|
||||
//
|
||||
|
||||
const bool PiFace::isValidGlyph(unsigned short glyph) const
|
||||
{
|
||||
|
|
|
@ -1,140 +1,149 @@
|
|||
// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/opengl/RendererGL.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "lua/Lua.h"
|
||||
#include "lua/LuaRef.h"
|
||||
#include "lua/LuaTable.h"
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
class PiFace {
|
||||
friend class PiGui; // need acces to some private data
|
||||
std::string m_ttfname; // only the ttf name, it is automatically sought in data/fonts/
|
||||
float m_sizefactor; // the requested pixelsize is multiplied by this factor
|
||||
std::unordered_set<unsigned short> m_invalid_glyphs;
|
||||
mutable std::vector<std::pair<unsigned short, unsigned short>> m_used_ranges;
|
||||
ImVector<ImWchar> m_imgui_ranges;
|
||||
namespace Graphics {
|
||||
class Texture;
|
||||
class Renderer;
|
||||
} // namespace Graphics
|
||||
|
||||
public:
|
||||
PiFace(const std::string &ttfname, float sizefactor) :
|
||||
m_ttfname(ttfname),
|
||||
m_sizefactor(sizefactor) {}
|
||||
const std::string &ttfname() const { return m_ttfname; }
|
||||
const float sizefactor() const { return m_sizefactor; }
|
||||
//std::unordered_map<unsigned short, unsigned short> &invalid_glyphs() const { return m_invalid_glyphs; }
|
||||
const std::vector<std::pair<unsigned short, unsigned short>> &used_ranges() const { return m_used_ranges; }
|
||||
const bool isValidGlyph(unsigned short glyph) const;
|
||||
void addGlyph(unsigned short glyph);
|
||||
void sortUsedRanges() const;
|
||||
};
|
||||
namespace PiGui {
|
||||
|
||||
class PiFont {
|
||||
std::string m_name;
|
||||
std::vector<PiFace> m_faces;
|
||||
int m_pixelsize;
|
||||
class PiFace {
|
||||
public:
|
||||
using UsedRange = std::pair<uint16_t, uint16_t>;
|
||||
PiFace(const std::string &ttfname, float sizefactor) :
|
||||
m_ttfname(ttfname),
|
||||
m_sizefactor(sizefactor) {}
|
||||
|
||||
public:
|
||||
PiFont(const std::string &name) :
|
||||
m_name(name) {}
|
||||
PiFont(const std::string &name, const std::vector<PiFace> &faces) :
|
||||
m_name(name),
|
||||
m_faces(faces) {}
|
||||
PiFont(const PiFont &other) :
|
||||
m_name(other.name()),
|
||||
m_faces(other.faces()) {}
|
||||
PiFont() :
|
||||
m_name("unknown") {}
|
||||
const std::vector<PiFace> &faces() const { return m_faces; }
|
||||
std::vector<PiFace> &faces() { return m_faces; }
|
||||
const std::string &name() const { return m_name; }
|
||||
int pixelsize() const { return m_pixelsize; }
|
||||
void setPixelsize(int pixelsize) { m_pixelsize = pixelsize; }
|
||||
void describe() const
|
||||
{
|
||||
Output("font %s:\n", name().c_str());
|
||||
for (const PiFace &face : faces()) {
|
||||
Output("- %s %f\n", face.ttfname().c_str(), face.sizefactor());
|
||||
const std::string &ttfname() const { return m_ttfname; }
|
||||
|
||||
const float sizefactor() const { return m_sizefactor; }
|
||||
|
||||
//std::unordered_map<unsigned short, unsigned short> &invalid_glyphs() const { return m_invalid_glyphs; }
|
||||
const std::vector<UsedRange> &used_ranges() const { return m_used_ranges; }
|
||||
|
||||
const bool isValidGlyph(unsigned short glyph) const;
|
||||
void addGlyph(unsigned short glyph);
|
||||
void sortUsedRanges() const;
|
||||
|
||||
private:
|
||||
friend class Instance; // need access to some private data
|
||||
|
||||
std::string m_ttfname; // only the ttf name, it is automatically sought in data/fonts/
|
||||
float m_sizefactor; // the requested pixelsize is multiplied by this factor
|
||||
|
||||
std::unordered_set<unsigned short> m_invalid_glyphs;
|
||||
mutable std::vector<UsedRange> m_used_ranges;
|
||||
|
||||
ImVector<ImWchar> m_imgui_ranges;
|
||||
};
|
||||
|
||||
class PiFont {
|
||||
public:
|
||||
PiFont(const std::string &name) :
|
||||
m_name(name) {}
|
||||
PiFont(const std::string &name, const std::vector<PiFace> &faces) :
|
||||
m_name(name),
|
||||
m_faces(faces) {}
|
||||
PiFont(const PiFont &other) :
|
||||
m_name(other.name()),
|
||||
m_faces(other.faces()) {}
|
||||
PiFont() :
|
||||
m_name("unknown") {}
|
||||
|
||||
const std::vector<PiFace> &faces() const { return m_faces; }
|
||||
std::vector<PiFace> &faces() { return m_faces; }
|
||||
|
||||
const std::string &name() const { return m_name; }
|
||||
|
||||
int pixelsize() const { return m_pixelsize; }
|
||||
void setPixelsize(int pixelsize) { m_pixelsize = pixelsize; }
|
||||
|
||||
void describe() const
|
||||
{
|
||||
Output("font %s:\n", name().c_str());
|
||||
for (const PiFace &face : faces()) {
|
||||
Output("- %s %f\n", face.ttfname().c_str(), face.sizefactor());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Class to wrap ImGui. */
|
||||
class PiGui : public RefCounted {
|
||||
std::map<std::pair<std::string, int>, ImFont *> m_fonts;
|
||||
std::map<ImFont *, std::pair<std::string, int>> m_im_fonts;
|
||||
std::map<std::pair<std::string, int>, PiFont> m_pi_fonts;
|
||||
bool m_should_bake_fonts;
|
||||
private:
|
||||
std::string m_name;
|
||||
std::vector<PiFace> m_faces;
|
||||
int m_pixelsize;
|
||||
};
|
||||
|
||||
std::map<std::string, PiFont> m_font_definitions;
|
||||
/* Class to wrap ImGui. */
|
||||
class Instance : public RefCounted {
|
||||
public:
|
||||
Instance();
|
||||
|
||||
void BakeFonts();
|
||||
void BakeFont(PiFont &font);
|
||||
void AddFontDefinition(const PiFont &font) { m_font_definitions[font.name()] = font; }
|
||||
void ClearFonts();
|
||||
void Init(Graphics::Renderer *renderer);
|
||||
void Uninit();
|
||||
|
||||
public:
|
||||
PiGui();
|
||||
// Call at the start of every frame. Calls ImGui::NewFrame() internally.
|
||||
void NewFrame();
|
||||
|
||||
LuaRef GetHandlers() const { return m_handlers; }
|
||||
// Call at the end of a frame that you're not going to render the results of
|
||||
void EndFrame();
|
||||
|
||||
LuaRef GetKeys() const { return m_keys; }
|
||||
// Calls ImGui::EndFrame() internally and does book-keeping before rendering.
|
||||
void Render();
|
||||
|
||||
void RunHandler(double delta, std::string handler = "GAME");
|
||||
ImFont *AddFont(const std::string &name, int size);
|
||||
ImFont *GetFont(const std::string &name, int size);
|
||||
|
||||
// Call at the start of every frame. Calls ImGui::NewFrame() internally.
|
||||
void NewFrame(SDL_Window *window);
|
||||
void AddGlyph(ImFont *font, unsigned short glyph);
|
||||
|
||||
// Call at the end of a frame that you're not going to render the results of
|
||||
void EndFrame();
|
||||
bool ProcessEvent(SDL_Event *event);
|
||||
|
||||
// Calls ImGui::EndFrame() internally and does book-keeping before rendering.
|
||||
void Render();
|
||||
void RefreshFontsTexture();
|
||||
|
||||
void Init(SDL_Window *window);
|
||||
private:
|
||||
Graphics::Renderer *m_renderer;
|
||||
|
||||
ImFont *GetFont(const std::string &name, int size);
|
||||
std::map<std::pair<std::string, int>, ImFont *> m_fonts;
|
||||
std::map<ImFont *, std::pair<std::string, int>> m_im_fonts;
|
||||
std::map<std::pair<std::string, int>, PiFont> m_pi_fonts;
|
||||
bool m_should_bake_fonts;
|
||||
|
||||
void Uninit()
|
||||
{
|
||||
Cleanup();
|
||||
m_handlers.Unref();
|
||||
m_keys.Unref();
|
||||
}
|
||||
ImFont *AddFont(const std::string &name, int size);
|
||||
std::map<std::string, PiFont> m_font_definitions;
|
||||
|
||||
void AddGlyph(ImFont *font, unsigned short glyph);
|
||||
void BakeFonts();
|
||||
void BakeFont(PiFont &font);
|
||||
void AddFontDefinition(const PiFont &font) { m_font_definitions[font.name()] = font; }
|
||||
void ClearFonts();
|
||||
};
|
||||
|
||||
static ImTextureID RenderSVG(std::string svgFilename, int width, int height);
|
||||
int RadialPopupSelectMenu(const ImVec2 ¢er, std::string popup_id, int mouse_button, std::vector<ImTextureID> tex_ids, std::vector<std::pair<ImVec2, ImVec2>> uvs, unsigned int size, std::vector<std::string> tooltips);
|
||||
bool CircularSlider(const ImVec2 ¢er, float *v, float v_min, float v_max);
|
||||
|
||||
static bool ProcessEvent(SDL_Event *event);
|
||||
bool LowThrustButton(const char *label, const ImVec2 &size_arg, int thrust_level, const ImVec4 &bg_col, int frame_padding, ImColor gauge_fg, ImColor gauge_bg);
|
||||
bool ButtonImageSized(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &imgSize, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, const ImVec4 &bg_col, const ImVec4 &tint_col);
|
||||
|
||||
void RefreshFontsTexture();
|
||||
void ThrustIndicator(const std::string &id_string, const ImVec2 &size, const ImVec4 &thrust, const ImVec4 &velocity, const ImVec4 &bg_col, int frame_padding, ImColor vel_fg, ImColor vel_bg, ImColor thrust_fg, ImColor thrust_bg);
|
||||
|
||||
static void *makeTexture(unsigned char *pixels, int width, int height);
|
||||
|
||||
static bool WantCaptureMouse()
|
||||
inline bool WantCaptureMouse()
|
||||
{
|
||||
return ImGui::GetIO().WantCaptureMouse;
|
||||
}
|
||||
|
||||
static bool WantCaptureKeyboard()
|
||||
inline bool WantCaptureKeyboard()
|
||||
{
|
||||
return ImGui::GetIO().WantCaptureKeyboard;
|
||||
}
|
||||
static int RadialPopupSelectMenu(const ImVec2 ¢er, std::string popup_id, int mouse_button, std::vector<ImTextureID> tex_ids, std::vector<std::pair<ImVec2, ImVec2>> uvs, unsigned int size, std::vector<std::string> tooltips);
|
||||
static bool CircularSlider(const ImVec2 ¢er, float *v, float v_min, float v_max);
|
||||
|
||||
void Cleanup();
|
||||
static bool LowThrustButton(const char *label, const ImVec2 &size_arg, int thrust_level, const ImVec4 &bg_col, int frame_padding, ImColor gauge_fg, ImColor gauge_bg);
|
||||
static bool ButtonImageSized(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &imgSize, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, const ImVec4 &bg_col, const ImVec4 &tint_col);
|
||||
std::vector<Graphics::Texture *> &GetSVGTextures();
|
||||
ImTextureID RenderSVG(Graphics::Renderer *renderer, std::string svgFilename, int width, int height);
|
||||
|
||||
static void ThrustIndicator(const std::string &id_string, const ImVec2 &size, const ImVec4 &thrust, const ImVec4 &velocity, const ImVec4 &bg_col, int frame_padding, ImColor vel_fg, ImColor vel_bg, ImColor thrust_fg, ImColor thrust_bg);
|
||||
|
||||
private:
|
||||
LuaRef m_handlers;
|
||||
LuaRef m_keys;
|
||||
static std::vector<Graphics::Texture *> m_svg_textures;
|
||||
};
|
||||
} //namespace PiGui
|
||||
|
|
|
@ -5,17 +5,65 @@
|
|||
#include "Face.h"
|
||||
#include "Image.h"
|
||||
#include "ModelSpinner.h"
|
||||
#include "lua/LuaTable.h"
|
||||
|
||||
static std::vector<std::pair<std::string, int>> m_keycodes = {
|
||||
{ "left", SDLK_LEFT },
|
||||
{ "right", SDLK_RIGHT },
|
||||
{ "up", SDLK_UP },
|
||||
{ "down", SDLK_DOWN },
|
||||
{ "escape", SDLK_ESCAPE },
|
||||
{ "f1", SDLK_F1 },
|
||||
{ "f2", SDLK_F2 },
|
||||
{ "f3", SDLK_F3 },
|
||||
{ "f4", SDLK_F4 },
|
||||
{ "f5", SDLK_F5 },
|
||||
{ "f6", SDLK_F6 },
|
||||
{ "f7", SDLK_F7 },
|
||||
{ "f8", SDLK_F8 },
|
||||
{ "f9", SDLK_F9 },
|
||||
{ "f10", SDLK_F10 },
|
||||
{ "f11", SDLK_F11 },
|
||||
{ "f12", SDLK_F12 },
|
||||
{ "tab", SDLK_TAB },
|
||||
};
|
||||
|
||||
static LuaRef m_handlers;
|
||||
static LuaRef m_keys;
|
||||
|
||||
namespace PiGUI {
|
||||
|
||||
namespace Lua {
|
||||
|
||||
void Init()
|
||||
{
|
||||
LuaObject<PiGui::Instance>::RegisterClass();
|
||||
|
||||
lua_State *l = ::Lua::manager->GetLuaState();
|
||||
lua_newtable(l);
|
||||
m_handlers = LuaRef(l, -1);
|
||||
|
||||
lua_newtable(l);
|
||||
m_keys = LuaRef(l, -1);
|
||||
LuaTable keys(l, -1);
|
||||
for (auto p : m_keycodes) {
|
||||
keys.Set(p.first, p.second);
|
||||
}
|
||||
|
||||
LuaObject<PiGUI::Image>::RegisterClass();
|
||||
LuaObject<PiGUI::Face>::RegisterClass();
|
||||
LuaObject<PiGUI::ModelSpinner>::RegisterClass();
|
||||
RegisterSandbox();
|
||||
}
|
||||
|
||||
void Uninit()
|
||||
{
|
||||
m_handlers.Unref();
|
||||
m_keys.Unref();
|
||||
}
|
||||
|
||||
} // namespace Lua
|
||||
|
||||
LuaRef GetHandlers() { return m_handlers; }
|
||||
LuaRef GetKeys() { return m_keys; }
|
||||
} // namespace PiGUI
|
||||
|
|
|
@ -7,12 +7,18 @@
|
|||
#include "lua/LuaObject.h"
|
||||
|
||||
namespace PiGUI {
|
||||
void RegisterSandbox();
|
||||
|
||||
// Get registered PiGui handlers.
|
||||
LuaRef GetHandlers();
|
||||
// Get a table of key name to SDL-keycode mappings
|
||||
LuaRef GetKeys();
|
||||
|
||||
namespace Lua {
|
||||
void RegisterSandbox();
|
||||
|
||||
void Init();
|
||||
}
|
||||
void Uninit();
|
||||
} // namespace Lua
|
||||
} // namespace PiGUI
|
||||
|
||||
#endif
|
||||
|
|
|
@ -132,7 +132,7 @@ luaL_Reg l_stack_functions[] = {
|
|||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
void PiGUI::RegisterSandbox()
|
||||
void PiGUI::Lua::RegisterSandbox()
|
||||
{
|
||||
lua_State *L = ::Lua::manager->GetLuaState();
|
||||
LUA_DEBUG_START(L);
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
// Copyright © 2008-2020 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "PiGui.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
// to get ImVec2 + ImVec2
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS true
|
||||
#include "imgui/imgui_internal.h"
|
||||
|
||||
int PiGui::RadialPopupSelectMenu(const ImVec2 ¢er, std::string popup_id, int mouse_button, std::vector<ImTextureID> tex_ids, std::vector<std::pair<ImVec2, ImVec2>> uvs, unsigned int size, std::vector<std::string> tooltips)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// return:
|
||||
// 0 - n for item selected
|
||||
// -1 for nothing chosen, but menu open
|
||||
// -2 for menu closed without an icon chosen
|
||||
// -3 for menu not open
|
||||
int ret = -3;
|
||||
|
||||
// FIXME: Missing a call to query if Popup is open so we can move the PushStyleColor inside the BeginPopupBlock (e.g. IsPopupOpen() in imgui.cpp)
|
||||
// FIXME: Our PathFill function only handle convex polygons, so we can't have items spanning an arc too large else inner concave edge artifact is too visible, hence the ImMax(7,items_count)
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
||||
if (ImGui::BeginPopup(popup_id.c_str())) {
|
||||
ret = -1;
|
||||
const ImVec2 drag_delta = ImVec2(ImGui::GetIO().MousePos.x - center.x, ImGui::GetIO().MousePos.y - center.y);
|
||||
const float drag_dist2 = drag_delta.x * drag_delta.x + drag_delta.y * drag_delta.y;
|
||||
|
||||
const ImGuiStyle &style = ImGui::GetStyle();
|
||||
const float RADIUS_MIN = 20.0f;
|
||||
const float RADIUS_MAX = 90.0f;
|
||||
const float RADIUS_INTERACT_MIN = 20.0f;
|
||||
const int ITEMS_MIN = 4;
|
||||
const float border_inout = 12.0f;
|
||||
const float border_thickness = 4.0f;
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
draw_list->PushClipRectFullScreen();
|
||||
draw_list->PathArcTo(center, (RADIUS_MIN + RADIUS_MAX) * 0.5f, 0.0f, IM_PI * 2.0f * 0.99f, 64); // FIXME: 0.99f look like full arc with closed thick stroke has a bug now
|
||||
draw_list->PathStroke(ImColor(18, 44, 67, 210), true, RADIUS_MAX - RADIUS_MIN);
|
||||
|
||||
const float item_arc_span = 2 * IM_PI / ImMax<int>(ITEMS_MIN, tex_ids.size());
|
||||
float drag_angle = atan2f(drag_delta.y, drag_delta.x);
|
||||
if (drag_angle < -0.5f * item_arc_span)
|
||||
drag_angle += 2.0f * IM_PI;
|
||||
|
||||
int item_hovered = -1;
|
||||
int item_n = 0;
|
||||
for (ImTextureID tex_id : tex_ids) {
|
||||
const char *tooltip = tooltips.at(item_n).c_str();
|
||||
const float inner_spacing = style.ItemInnerSpacing.x / RADIUS_MIN / 2;
|
||||
const float item_inner_ang_min = item_arc_span * (item_n - 0.5f + inner_spacing);
|
||||
const float item_inner_ang_max = item_arc_span * (item_n + 0.5f - inner_spacing);
|
||||
const float item_outer_ang_min = item_arc_span * (item_n - 0.5f + inner_spacing * (RADIUS_MIN / RADIUS_MAX));
|
||||
const float item_outer_ang_max = item_arc_span * (item_n + 0.5f - inner_spacing * (RADIUS_MIN / RADIUS_MAX));
|
||||
|
||||
bool hovered = false;
|
||||
if (drag_dist2 >= RADIUS_INTERACT_MIN * RADIUS_INTERACT_MIN) {
|
||||
if (drag_angle >= item_inner_ang_min && drag_angle < item_inner_ang_max)
|
||||
hovered = true;
|
||||
}
|
||||
bool selected = false;
|
||||
|
||||
int arc_segments = static_cast<int>((64 * item_arc_span / (2 * IM_PI))) + 1;
|
||||
draw_list->PathArcTo(center, RADIUS_MAX - border_inout, item_outer_ang_min, item_outer_ang_max, arc_segments);
|
||||
draw_list->PathArcTo(center, RADIUS_MIN + border_inout, item_inner_ang_max, item_inner_ang_min, arc_segments);
|
||||
|
||||
draw_list->PathFillConvex(hovered ? ImColor(102, 147, 189) : selected ? ImColor(48, 81, 111) : ImColor(48, 81, 111));
|
||||
if (hovered) {
|
||||
// draw outer / inner extra segments
|
||||
draw_list->PathArcTo(center, RADIUS_MAX - border_thickness, item_outer_ang_min, item_outer_ang_max, arc_segments);
|
||||
draw_list->PathStroke(ImColor(102, 147, 189), false, border_thickness);
|
||||
draw_list->PathArcTo(center, RADIUS_MIN + border_thickness, item_outer_ang_min, item_outer_ang_max, arc_segments);
|
||||
draw_list->PathStroke(ImColor(102, 147, 189), false, border_thickness);
|
||||
}
|
||||
ImVec2 text_size = ImVec2(size, size);
|
||||
ImVec2 text_pos = ImVec2(
|
||||
center.x + cosf((item_inner_ang_min + item_inner_ang_max) * 0.5f) * (RADIUS_MIN + RADIUS_MAX) * 0.5f - text_size.x * 0.5f,
|
||||
center.y + sinf((item_inner_ang_min + item_inner_ang_max) * 0.5f) * (RADIUS_MIN + RADIUS_MAX) * 0.5f - text_size.y * 0.5f);
|
||||
draw_list->AddImage(tex_id, text_pos, ImVec2(text_pos.x + size, text_pos.y + size), uvs[item_n].first, uvs[item_n].second);
|
||||
ImGui::SameLine();
|
||||
if (hovered) {
|
||||
item_hovered = item_n;
|
||||
ImGui::SetTooltip("%s", tooltip);
|
||||
}
|
||||
item_n++;
|
||||
}
|
||||
draw_list->PopClipRect();
|
||||
|
||||
if (ImGui::IsMouseReleased(mouse_button)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
if (item_hovered == -1)
|
||||
ret = -2;
|
||||
else
|
||||
ret = item_hovered;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
} else {
|
||||
// Output("WARNING: RadialPopupSelectMenu BeginPopup failed: %s\n", popup_id.c_str());
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PiGui::CircularSlider(const ImVec2 ¢er, float *v, float v_min, float v_max)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
const ImGuiID id = window->GetID("circularslider");
|
||||
draw_list->AddCircle(center, 17, ImColor(100, 100, 100), 128, 12.0);
|
||||
draw_list->PathArcTo(center, 17, 0, M_PI * 2.0 * (*v - v_min) / (v_max - v_min), 64);
|
||||
draw_list->PathStroke(ImColor(200, 200, 200), false, 12.0);
|
||||
ImRect grab_bb;
|
||||
return ImGui::SliderBehavior(ImRect(center.x - 17, center.y - 17, center.x + 17, center.y + 17),
|
||||
id, ImGuiDataType_Float, v, &v_min, &v_max, "%.4f", 1.0, ImGuiSliderFlags_None, &grab_bb);
|
||||
}
|
||||
|
||||
static void drawThrust(ImDrawList *draw_list, const ImVec2 ¢er, const ImVec2 &up, float value, const ImColor &fg, const ImColor &bg)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
float factor = 0.1; // how much to offset from center
|
||||
const ImVec2 step(up.x * 0.5, up.y * 0.5);
|
||||
const ImVec2 left(-step.y * (1.0 - factor), step.x * (1.0 - factor));
|
||||
const ImVec2 u(up.x * (1.0 - factor), up.y * (1.0 - factor));
|
||||
const ImVec2 c(center + ImVec2(u.x * factor, u.y * factor));
|
||||
const ImVec2 right(-left.x, -left.y);
|
||||
const ImVec2 leftmiddle = c + step + left;
|
||||
const ImVec2 rightmiddle = c + step + right;
|
||||
const ImVec2 bb_lowerright = c + right;
|
||||
const ImVec2 bb_upperleft = c + left + ImVec2(u.x * value, u.y * value);
|
||||
const ImVec2 lefttop = c + u + left;
|
||||
const ImVec2 righttop = c + u + right;
|
||||
const ImVec2 minimum(fmin(bb_upperleft.x, bb_lowerright.x), fmin(bb_upperleft.y, bb_lowerright.y));
|
||||
const ImVec2 maximum(fmax(bb_upperleft.x, bb_lowerright.x), fmax(bb_upperleft.y, bb_lowerright.y));
|
||||
ImVec2 points[] = { c, leftmiddle, lefttop, righttop, rightmiddle };
|
||||
draw_list->AddConvexPolyFilled(points, 5, bg);
|
||||
draw_list->PushClipRect(minimum - ImVec2(1, 1), maximum + ImVec2(1, 1));
|
||||
draw_list->AddConvexPolyFilled(points, 5, fg);
|
||||
draw_list->PopClipRect();
|
||||
}
|
||||
|
||||
void PiGui::ThrustIndicator(const std::string &id_string, const ImVec2 &size_arg, const ImVec4 &thrust, const ImVec4 &velocity, const ImVec4 &bg_col, int frame_padding, ImColor vel_fg, ImColor vel_bg, ImColor thrust_fg, ImColor thrust_bg)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext &g = *GImGui;
|
||||
const ImGuiStyle &style = g.Style;
|
||||
const ImGuiID id = window->GetID(id_string.c_str());
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
// if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
|
||||
// pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
|
||||
ImVec2 size = ImGui::CalcItemSize(size_arg, style.FramePadding.x * 2.0f, style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2(static_cast<float>(frame_padding), static_cast<float>(frame_padding)) : style.FramePadding;
|
||||
const ImRect bb(pos, pos + size + padding * 2);
|
||||
const ImRect inner_bb(pos + padding, pos + padding + size);
|
||||
|
||||
ImGui::ItemSize(bb, style.FramePadding.y);
|
||||
if (!ImGui::ItemAdd(bb, id))
|
||||
return;
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32(static_cast<ImGuiCol>(ImGuiCol_Button));
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
if (bg_col.w > 0.0f)
|
||||
draw_list->AddRectFilled(inner_bb.Min, inner_bb.Max, ImGui::GetColorU32(bg_col));
|
||||
const ImVec2 leftupper = inner_bb.Min;
|
||||
const ImVec2 rightlower = inner_bb.Max;
|
||||
const ImVec2 rightcenter((rightlower.x - leftupper.x) * 0.8 + leftupper.x, (rightlower.y + leftupper.y) / 2);
|
||||
const ImVec2 leftcenter((rightlower.x - leftupper.x) * 0.35 + leftupper.x, (rightlower.y + leftupper.y) / 2);
|
||||
const ImVec2 up(0, -std::abs(leftupper.y - rightlower.y) * 0.4);
|
||||
const ImVec2 left(-up.y, up.x);
|
||||
float thrust_fwd = fmax(thrust.z, 0);
|
||||
float thrust_bwd = fmax(-thrust.z, 0);
|
||||
float thrust_left = fmax(-thrust.x, 0);
|
||||
float thrust_right = fmax(thrust.x, 0);
|
||||
float thrust_up = fmax(-thrust.y, 0);
|
||||
float thrust_down = fmax(thrust.y, 0);
|
||||
// actual thrust
|
||||
drawThrust(draw_list, rightcenter, up, thrust_fwd, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, rightcenter, ImVec2(-up.x, -up.y), thrust_bwd, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, up, thrust_up, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, ImVec2(-up.x, -up.y), thrust_down, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, left, thrust_left, thrust_fg, thrust_bg);
|
||||
drawThrust(draw_list, leftcenter, ImVec2(-left.x, -left.y), thrust_right, thrust_fg, thrust_bg);
|
||||
// forward/back velocity
|
||||
draw_list->AddLine(rightcenter + up, rightcenter - up, vel_bg, 3);
|
||||
draw_list->AddLine(rightcenter, rightcenter - up * velocity.z, vel_fg, 3);
|
||||
// left/right velocity
|
||||
draw_list->AddLine(leftcenter + left, leftcenter - left, vel_bg, 3);
|
||||
draw_list->AddLine(leftcenter, leftcenter + left * velocity.x, vel_fg, 3);
|
||||
// up/down velocity
|
||||
draw_list->AddLine(leftcenter + up, leftcenter - up, vel_bg, 3);
|
||||
draw_list->AddLine(leftcenter, leftcenter + up * velocity.y, vel_fg, 3);
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
// CloseCurrentPopup();
|
||||
}
|
||||
|
||||
bool PiGui::LowThrustButton(const char *id_string, const ImVec2 &size_arg, int thrust_level, const ImVec4 &bg_col, int frame_padding, ImColor gauge_fg, ImColor gauge_bg)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
std::string label = std::to_string(thrust_level);
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiContext &g = *GImGui;
|
||||
const ImGuiStyle &style = g.Style;
|
||||
const ImGuiID id = window->GetID(id_string);
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(label.c_str(), NULL, true);
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
// if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
|
||||
// pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
|
||||
ImVec2 size = ImGui::CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2(static_cast<float>(frame_padding), static_cast<float>(frame_padding)) : style.FramePadding;
|
||||
const ImRect bb(pos, pos + size + padding * 2);
|
||||
const ImRect inner_bb(pos + padding, pos + padding + size);
|
||||
|
||||
ImGui::ItemSize(bb, style.FramePadding.y);
|
||||
if (!ImGui::ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
// if (window->DC.ButtonRepeat) flags |= ImGuiButtonFlags_Repeat;
|
||||
bool hovered, held;
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0); // flags
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32(static_cast<ImGuiCol>((hovered && held) ? ImGuiCol_ButtonActive : (hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button)));
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||
const ImVec2 center = (inner_bb.Min + inner_bb.Max) / 2;
|
||||
float radius = (inner_bb.Max.x - inner_bb.Min.x) * 0.4;
|
||||
float thickness = 4;
|
||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
||||
if (bg_col.w > 0.0f)
|
||||
draw_list->AddRectFilled(inner_bb.Min, inner_bb.Max, ImGui::GetColorU32(bg_col));
|
||||
|
||||
draw_list->PathArcTo(center, radius, 0, IM_PI * 2, 16);
|
||||
draw_list->PathStroke(gauge_bg, false, thickness);
|
||||
|
||||
draw_list->PathArcTo(center, radius, IM_PI, IM_PI + IM_PI * 2 * (thrust_level / 100.0), 16);
|
||||
draw_list->PathStroke(gauge_fg, false, thickness);
|
||||
ImGui::RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label.c_str(), NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
// CloseCurrentPopup();
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
// frame_padding < 0: uses FramePadding from style (default)
|
||||
// frame_padding = 0: no framing
|
||||
// frame_padding > 0: set framing size
|
||||
// The color used are the button colors.
|
||||
bool PiGui::ButtonImageSized(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &imgSize, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, const ImVec4 &bg_col, const ImVec4 &tint_col)
|
||||
{
|
||||
ImGuiWindow *window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiContext &g = *GImGui;
|
||||
const ImGuiStyle &style = g.Style;
|
||||
|
||||
// Default to using texture ID as ID. User can still push string/integer prefixes.
|
||||
// We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.
|
||||
ImGui::PushID((void *)user_texture_id);
|
||||
const ImGuiID id = window->GetID("#image");
|
||||
ImGui::PopID();
|
||||
|
||||
ImVec2 imgPadding = (size - imgSize) / 2;
|
||||
imgPadding.x = imgPadding.x < 0 || imgSize.x <= 0 ? 0 : imgPadding.x;
|
||||
imgPadding.y = imgPadding.y < 0 || imgSize.y <= 0 ? 0 : imgPadding.y;
|
||||
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
|
||||
const ImRect image_bb(window->DC.CursorPos + padding + imgPadding, window->DC.CursorPos + padding + size - imgPadding);
|
||||
ImGui::ItemSize(bb);
|
||||
if (!ImGui::ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
ImGui::RenderNavHighlight(bb, id);
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
|
||||
if (bg_col.w > 0.0f)
|
||||
window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, ImGui::GetColorU32(bg_col));
|
||||
window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, ImGui::GetColorU32(tint_col));
|
||||
|
||||
return pressed;
|
||||
}
|
|
@ -488,6 +488,7 @@
|
|||
<ClCompile Include="..\..\src\pigui\PiGuiLua.cpp" />
|
||||
<ClCompile Include="..\..\src\pigui\LuaFace.cpp" />
|
||||
<ClCompile Include="..\..\src\pigui\PiGuiSandbox.cpp" />
|
||||
<ClCompile Include="..\..\src\pigui\Widgets.cpp" />
|
||||
<ClCompile Include="..\..\src\Plane.cpp" />
|
||||
<ClCompile Include="..\..\src\Planet.cpp" />
|
||||
<ClCompile Include="..\..\src\Player.cpp" />
|
||||
|
@ -679,10 +680,12 @@
|
|||
<ClInclude Include="..\..\src\Pi.h" />
|
||||
<ClInclude Include="..\..\src\pigui\Face.h" />
|
||||
<ClInclude Include="..\..\src\pigui\Image.h" />
|
||||
<ClInclude Include="..\..\src\pigui\LuaFlags.h" />
|
||||
<ClInclude Include="..\..\src\pigui\ModelSpinner.h" />
|
||||
<ClInclude Include="..\..\src\pigui\PerfInfo.h" />
|
||||
<ClInclude Include="..\..\src\pigui\PiGui.h" />
|
||||
<ClInclude Include="..\..\src\pigui\PiGuiLua.h" />
|
||||
<ClInclude Include="..\..\src\pigui\View.h" />
|
||||
<ClInclude Include="..\..\src\Plane.h" />
|
||||
<ClInclude Include="..\..\src\Planet.h" />
|
||||
<ClInclude Include="..\..\src\Player.h" />
|
||||
|
|
|
@ -561,6 +561,9 @@
|
|||
<ClCompile Include="..\..\src\core\Application.cpp">
|
||||
<Filter>src\core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\pigui\Widgets.cpp">
|
||||
<Filter>src\pigui</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\Aabb.h">
|
||||
|
@ -1106,6 +1109,12 @@
|
|||
<ClInclude Include="..\..\src\core\GuiApplication.h">
|
||||
<Filter>src\core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\pigui\View.h">
|
||||
<Filter>src\pigui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\pigui\LuaFlags.h">
|
||||
<Filter>src\pigui</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\src\win32\pioneer.rc">
|
||||
|
|
Loading…
Reference in New Issue