Main.qml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. import QtQuick.Window 2.15
  4. ApplicationWindow {
  5. id: mainWindow
  6. property alias gameView: gameViewItem
  7. property bool menuVisible: true
  8. property bool gameStarted: false
  9. property bool gamePaused: false
  10. property bool edgeScrollDisabled: false
  11. width: 1280
  12. height: 720
  13. visibility: Window.FullScreen
  14. visible: true
  15. title: "Standard of Iron - RTS Game"
  16. GameView {
  17. id: gameViewItem
  18. anchors.fill: parent
  19. z: 0
  20. focus: !mainWindow.menuVisible
  21. visible: gameStarted
  22. }
  23. HUD {
  24. id: hud
  25. anchors.fill: parent
  26. z: 1
  27. visible: !mainWindow.menuVisible && gameStarted
  28. onActiveFocusChanged: {
  29. if (activeFocus)
  30. gameViewItem.forceActiveFocus();
  31. }
  32. onPauseToggled: {
  33. mainWindow.gamePaused = !mainWindow.gamePaused;
  34. gameViewItem.setPaused(mainWindow.gamePaused);
  35. gameViewItem.forceActiveFocus();
  36. }
  37. onSpeedChanged: function(speed) {
  38. gameViewItem.setGameSpeed(speed);
  39. gameViewItem.forceActiveFocus();
  40. }
  41. onCommandModeChanged: function(mode) {
  42. console.log("Main: Command mode changed to:", mode);
  43. if (typeof game !== 'undefined') {
  44. console.log("Main: Setting game.cursorMode property to", mode);
  45. game.cursorMode = mode;
  46. } else {
  47. console.log("Main: game is undefined");
  48. }
  49. gameViewItem.forceActiveFocus();
  50. }
  51. onRecruit: function(unitType) {
  52. if (typeof game !== 'undefined' && game.recruitNearSelected)
  53. game.recruitNearSelected(unitType);
  54. gameViewItem.forceActiveFocus();
  55. }
  56. }
  57. Rectangle {
  58. id: pauseOverlay
  59. anchors.fill: parent
  60. z: 10
  61. visible: mainWindow.gamePaused && gameStarted
  62. color: "#80000000"
  63. Rectangle {
  64. anchors.centerIn: parent
  65. width: 300
  66. height: 150
  67. color: "#2c3e50"
  68. radius: 8
  69. border.color: "#34495e"
  70. border.width: 2
  71. Column {
  72. anchors.centerIn: parent
  73. spacing: 20
  74. Text {
  75. text: "PAUSED"
  76. color: "#ecf0f1"
  77. font.pixelSize: 36
  78. font.bold: true
  79. anchors.horizontalCenter: parent.horizontalCenter
  80. }
  81. Text {
  82. text: "Press Space to resume"
  83. color: "#bdc3c7"
  84. font.pixelSize: 14
  85. anchors.horizontalCenter: parent.horizontalCenter
  86. }
  87. }
  88. }
  89. }
  90. MainMenu {
  91. id: mainMenu
  92. anchors.fill: parent
  93. z: 20
  94. visible: mainWindow.menuVisible
  95. Component.onCompleted: {
  96. if (mainWindow.menuVisible)
  97. mainMenu.forceActiveFocus();
  98. }
  99. onVisibleChanged: {
  100. if (visible) {
  101. mainMenu.forceActiveFocus();
  102. gameViewItem.focus = false;
  103. } else if (gameStarted) {
  104. gameViewItem.forceActiveFocus();
  105. }
  106. }
  107. onOpenSkirmish: function() {
  108. mapSelect.visible = true;
  109. mainWindow.menuVisible = false;
  110. }
  111. onOpenSettings: function() {
  112. if (typeof game !== 'undefined' && game.openSettings)
  113. game.openSettings();
  114. }
  115. onLoadSave: function() {
  116. if (typeof game !== 'undefined' && game.loadSave)
  117. game.loadSave();
  118. }
  119. onExitRequested: function() {
  120. if (typeof game !== 'undefined' && game.exitGame)
  121. game.exitGame();
  122. }
  123. }
  124. MapSelect {
  125. id: mapSelect
  126. anchors.fill: parent
  127. z: 21
  128. visible: false
  129. onVisibleChanged: {
  130. if (visible) {
  131. mapSelect.forceActiveFocus();
  132. gameViewItem.focus = false;
  133. }
  134. }
  135. onMapChosen: function(mapPath, playerConfigs) {
  136. console.log("Main: onMapChosen received", mapPath, "with", playerConfigs.length, "player configs");
  137. if (typeof game !== 'undefined' && game.startSkirmish)
  138. game.startSkirmish(mapPath, playerConfigs);
  139. mapSelect.visible = false;
  140. mainWindow.menuVisible = false;
  141. mainWindow.gameStarted = true;
  142. mainWindow.gamePaused = false;
  143. gameViewItem.forceActiveFocus();
  144. }
  145. onCancelled: function() {
  146. mapSelect.visible = false;
  147. mainWindow.menuVisible = true;
  148. }
  149. }
  150. Item {
  151. id: edgeScrollOverlay
  152. property real horzThreshold: 120
  153. property real horzMaxSpeed: 0.15
  154. property real vertThreshold: 100
  155. property real verticalDeadZone: 45
  156. property real vertMaxSpeed: 0.01
  157. property real xPos: -1
  158. property real yPos: -1
  159. property int verticalShift: 6
  160. function inHudZone(x, y) {
  161. var topH = (typeof hud !== 'undefined' && hud && hud.topPanelHeight) ? hud.topPanelHeight : 0;
  162. var bottomH = (typeof hud !== 'undefined' && hud && hud.bottomPanelHeight) ? hud.bottomPanelHeight : 0;
  163. if (y < topH)
  164. return true;
  165. if (y > (height - bottomH))
  166. return true;
  167. return false;
  168. }
  169. anchors.fill: parent
  170. z: 2
  171. visible: !mainWindow.menuVisible && !mapSelect.visible
  172. enabled: visible
  173. MouseArea {
  174. anchors.fill: parent
  175. hoverEnabled: true
  176. acceptedButtons: Qt.NoButton
  177. propagateComposedEvents: true
  178. preventStealing: false
  179. onPositionChanged: function(mouse) {
  180. edgeScrollOverlay.xPos = mouse.x;
  181. edgeScrollOverlay.yPos = mouse.y;
  182. if (typeof game !== 'undefined' && game.setHoverAtScreen) {
  183. if (!edgeScrollOverlay.inHudZone(mouse.x, mouse.y))
  184. game.setHoverAtScreen(mouse.x, mouse.y);
  185. else
  186. game.setHoverAtScreen(-1, -1);
  187. }
  188. }
  189. onEntered: function() {
  190. edgeScrollTimer.start();
  191. if (typeof game !== 'undefined' && game.setHoverAtScreen) {
  192. if (!edgeScrollOverlay.inHudZone(edgeScrollOverlay.xPos, edgeScrollOverlay.yPos))
  193. game.setHoverAtScreen(edgeScrollOverlay.xPos, edgeScrollOverlay.yPos);
  194. else
  195. game.setHoverAtScreen(-1, -1);
  196. }
  197. }
  198. onExited: function() {
  199. edgeScrollTimer.stop();
  200. edgeScrollOverlay.xPos = -1;
  201. edgeScrollOverlay.yPos = -1;
  202. if (typeof game !== 'undefined' && game.setHoverAtScreen)
  203. game.setHoverAtScreen(-1, -1);
  204. }
  205. }
  206. Timer {
  207. id: edgeScrollTimer
  208. interval: 16
  209. repeat: true
  210. onTriggered: {
  211. if (typeof game === 'undefined')
  212. return ;
  213. const w = edgeScrollOverlay.width;
  214. const h = edgeScrollOverlay.height;
  215. const x = edgeScrollOverlay.xPos;
  216. const y = edgeScrollOverlay.yPos;
  217. if (x < 0 || y < 0)
  218. return ;
  219. if (edgeScrollOverlay.inHudZone(x, y) || mainWindow.edgeScrollDisabled) {
  220. if (game.setHoverAtScreen)
  221. game.setHoverAtScreen(-1, -1);
  222. return ;
  223. }
  224. if (game.setHoverAtScreen)
  225. game.setHoverAtScreen(x, y);
  226. const th = edgeScrollOverlay.horzThreshold;
  227. const tv = edgeScrollOverlay.vertThreshold;
  228. const vdz = edgeScrollOverlay.verticalDeadZone;
  229. const clamp = function clamp(v, lo, hi) {
  230. return Math.max(lo, Math.min(hi, v));
  231. };
  232. const dl = x;
  233. const dr = w - x;
  234. const topBar = (typeof hud !== 'undefined' && hud && hud.topPanelHeight) ? hud.topPanelHeight : 0;
  235. const bottomBar = (typeof hud !== 'undefined' && hud && hud.bottomPanelHeight) ? hud.bottomPanelHeight : 0;
  236. const topEdge = topBar + edgeScrollOverlay.verticalShift;
  237. const bottomEdge = h - bottomBar - edgeScrollOverlay.verticalShift;
  238. const dt = Math.max(0, (y - topEdge) - vdz);
  239. const db = Math.max(0, (bottomEdge - y) - vdz);
  240. const il = clamp(1 - dl / th, 0, 1);
  241. const ir = clamp(1 - dr / th, 0, 1);
  242. const iu = clamp(1 - dt / tv, 0, 1);
  243. const id = clamp(1 - db / tv, 0, 1);
  244. if (il === 0 && ir === 0 && iu === 0 && id === 0)
  245. return ;
  246. const curveH = function curveH(a) {
  247. return a * a;
  248. };
  249. const curveV = function curveV(a) {
  250. return a * a * a;
  251. };
  252. const rawDx = (curveH(ir) - curveH(il)) * edgeScrollOverlay.horzMaxSpeed;
  253. const rawDz = (curveV(iu) - curveV(id)) * edgeScrollOverlay.vertMaxSpeed;
  254. const dx = rawDx / edgeScrollOverlay.horzMaxSpeed;
  255. const dz = rawDz / edgeScrollOverlay.vertMaxSpeed;
  256. if (dx !== 0 || dz !== 0)
  257. game.cameraMove(dx, dz);
  258. }
  259. }
  260. }
  261. Dialog {
  262. id: errorDialog
  263. anchors.centerIn: parent
  264. width: Math.min(parent.width * 0.6, 500)
  265. title: "Error"
  266. modal: true
  267. standardButtons: Dialog.Ok
  268. onAccepted: {
  269. if (game)
  270. game.clearError();
  271. }
  272. contentItem: Rectangle {
  273. color: "#2a2a2a"
  274. implicitHeight: errorText.implicitHeight + 40
  275. Text {
  276. id: errorText
  277. anchors.centerIn: parent
  278. width: parent.width - 40
  279. text: game ? game.lastError : ""
  280. color: "#ffcccc"
  281. wrapMode: Text.WordWrap
  282. font.pixelSize: 14
  283. }
  284. }
  285. }
  286. Connections {
  287. function onLastErrorChanged() {
  288. if (game.lastError !== "")
  289. errorDialog.open();
  290. }
  291. target: game
  292. }
  293. }