PlayerConfigPanel.qml 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import QtQuick 2.15
  2. import QtQuick.Controls 2.15
  3. Item {
  4. id: root
  5. property var colors: ({
  6. })
  7. property var playersModel: null
  8. property var teamIcons: []
  9. property var currentMapData: null
  10. property string mapTitle: "Select a map"
  11. property string mapPreview: ""
  12. signal addCPUClicked()
  13. signal removePlayerClicked(int index)
  14. signal playerColorClicked(int index)
  15. signal playerTeamClicked(int index)
  16. signal playerFactionClicked(int index)
  17. anchors.fill: parent
  18. Component {
  19. id: playerListItemComponent
  20. Loader {
  21. property var itemColors: root.colors
  22. property var itemPlayerData: model
  23. property var itemTeamIcons: root.teamIcons
  24. property bool itemCanRemove: !model.isHuman
  25. source: "./PlayerListItem.qml"
  26. onLoaded: {
  27. item.colors = Qt.binding(function() {
  28. return itemColors;
  29. });
  30. item.playerData = Qt.binding(function() {
  31. return itemPlayerData;
  32. });
  33. item.teamIcons = Qt.binding(function() {
  34. return itemTeamIcons;
  35. });
  36. item.canRemove = Qt.binding(function() {
  37. return itemCanRemove;
  38. });
  39. item.removeClicked.connect(function() {
  40. root.removePlayerClicked(index);
  41. });
  42. item.colorClicked.connect(function() {
  43. root.playerColorClicked(index);
  44. });
  45. item.teamClicked.connect(function() {
  46. root.playerTeamClicked(index);
  47. });
  48. item.factionClicked.connect(function() {
  49. root.playerFactionClicked(index);
  50. });
  51. }
  52. }
  53. }
  54. Text {
  55. id: title
  56. text: root.mapTitle
  57. color: colors.textMain
  58. font.pixelSize: 20
  59. font.bold: true
  60. elide: Text.ElideRight
  61. anchors {
  62. top: parent.top
  63. left: parent.left
  64. right: parent.right
  65. }
  66. }
  67. Item {
  68. id: playerSection
  69. height: Math.min(350, parent.height * 0.6)
  70. anchors {
  71. top: title.bottom
  72. topMargin: 16
  73. left: parent.left
  74. right: parent.right
  75. }
  76. Text {
  77. id: playerSectionTitle
  78. text: "Players (" + (playersModel ? playersModel.count : 0) + ")"
  79. color: colors.textMain
  80. font.pixelSize: 16
  81. font.bold: true
  82. }
  83. Text {
  84. id: playerSectionHint
  85. text: "Click color/team to cycle"
  86. color: colors.textSubLite
  87. font.pixelSize: 11
  88. font.italic: true
  89. anchors {
  90. left: playerSectionTitle.right
  91. leftMargin: 10
  92. verticalCenter: playerSectionTitle.verticalCenter
  93. }
  94. }
  95. Rectangle {
  96. id: playerListFrame
  97. radius: 8
  98. color: colors.cardBaseA
  99. border.color: colors.panelBr
  100. border.width: 1
  101. clip: true
  102. anchors {
  103. top: playerSectionTitle.bottom
  104. topMargin: 10
  105. left: parent.left
  106. right: parent.right
  107. bottom: addCPUBtn.top
  108. bottomMargin: 8
  109. }
  110. ListView {
  111. id: playerListView
  112. anchors.fill: parent
  113. anchors.margins: 8
  114. model: root.playersModel
  115. spacing: 6
  116. clip: true
  117. boundsBehavior: Flickable.StopAtBounds
  118. delegate: playerListItemComponent
  119. Item {
  120. anchors.fill: parent
  121. visible: !playersModel || playersModel.count === 0
  122. Text {
  123. anchors.centerIn: parent
  124. text: "Select a map to configure players"
  125. color: colors.textSub
  126. font.pixelSize: 13
  127. }
  128. }
  129. ScrollBar.vertical: ScrollBar {
  130. policy: ScrollBar.AsNeeded
  131. }
  132. }
  133. }
  134. Button {
  135. id: addCPUBtn
  136. text: "+ Add CPU"
  137. enabled: {
  138. if (!currentMapData || !currentMapData.player_ids)
  139. return false;
  140. if (!playersModel)
  141. return false;
  142. return playersModel.count < currentMapData.player_ids.length;
  143. }
  144. hoverEnabled: true
  145. onClicked: root.addCPUClicked()
  146. anchors {
  147. bottom: parent.bottom
  148. left: parent.left
  149. }
  150. MouseArea {
  151. id: addHover
  152. anchors.fill: parent
  153. hoverEnabled: true
  154. acceptedButtons: Qt.NoButton
  155. cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
  156. }
  157. ToolTip {
  158. visible: addHover.containsMouse && enabled
  159. text: "Add AI player to the game"
  160. delay: 500
  161. }
  162. contentItem: Text {
  163. text: addCPUBtn.text
  164. font.pixelSize: 12
  165. font.bold: true
  166. color: enabled ? colors.addColor : colors.textSub
  167. horizontalAlignment: Text.AlignHCenter
  168. verticalAlignment: Text.AlignVCenter
  169. }
  170. background: Rectangle {
  171. implicitWidth: 100
  172. implicitHeight: 32
  173. radius: 6
  174. color: enabled ? (addCPUBtn.down ? Qt.darker(colors.addColor, 1.3) : (addHover.containsMouse ? Qt.darker(colors.addColor, 1.1) : colors.cardBaseA)) : colors.cardBaseA
  175. border.width: 1
  176. border.color: enabled ? colors.addColor : colors.thumbBr
  177. Behavior on color {
  178. ColorAnimation {
  179. duration: 150
  180. }
  181. }
  182. }
  183. }
  184. Text {
  185. text: {
  186. if (!currentMapData || !currentMapData.player_ids)
  187. return "";
  188. if (!playersModel)
  189. return "";
  190. var available = currentMapData.player_ids.length - playersModel.count;
  191. if (available <= 0)
  192. return "Max players reached";
  193. return available + " slot" + (available > 1 ? "s" : "") + " available";
  194. }
  195. color: colors.textSubLite
  196. font.pixelSize: 11
  197. anchors {
  198. left: addCPUBtn.right
  199. leftMargin: 10
  200. verticalCenter: addCPUBtn.verticalCenter
  201. }
  202. }
  203. }
  204. Rectangle {
  205. id: preview
  206. radius: 8
  207. color: "#031314"
  208. border.color: colors.thumbBr
  209. border.width: 1
  210. clip: true
  211. anchors {
  212. top: playerSection.bottom
  213. topMargin: 16
  214. left: parent.left
  215. right: parent.right
  216. bottom: parent.bottom
  217. }
  218. Image {
  219. id: previewImage
  220. anchors.fill: parent
  221. source: root.mapPreview
  222. asynchronous: true
  223. fillMode: Image.PreserveAspectFit
  224. visible: status === Image.Ready
  225. }
  226. Text {
  227. anchors.centerIn: parent
  228. visible: !previewImage.visible
  229. text: "(map preview)"
  230. color: colors.hint
  231. font.pixelSize: 14
  232. }
  233. }
  234. }