630 | function InputHelpDisplay:animateShow() |
631 | InputHelpDisplay:superClass().setVisible(self, true) |
632 | |
633 | local transX, transY = self:getHidingTranslation() |
634 | |
635 | local sequence = TweenSequence.new(self) |
636 | local moveIn = MultiValueTween.new(self.setAnimationOffset, {transX, transY}, {0, 0}, HUDDisplayElement.MOVE_ANIMATION_DURATION) |
637 | local unfoldEntries = Tween.new(self.setAnimationAvailableHeight, 0, self:getAvailableHeight(), HUDDisplayElement.MOVE_ANIMATION_DURATION) |
638 | |
639 | sequence:addTween(moveIn) |
640 | sequence:addTween(unfoldEntries) |
641 | sequence:addCallback(self.onAnimateVisibilityFinished, true) |
642 | |
643 | sequence:start() |
644 | self.animation = sequence |
645 | end |
1010 | function InputHelpDisplay:createComboHeader(hudAtlasPath, frameX, frameY, combos, boxSize, separatorPositions) |
1011 | local width, height = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.HEADER) |
1012 | local posY = frameY - height |
1013 | local bgOverlay = Overlay.new(nil, frameX, posY, width, height) |
1014 | local headerElement = HUDElement.new(bgOverlay) |
1015 | |
1016 | local entryOffset, _ = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.HELP_ENTRY_OFFSET) |
1017 | local headerItemWidth = (width - entryOffset * (#combos - 1)) / #combos |
1018 | |
1019 | local glyphWidth, glyphHeight = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.COMBO_GLYPH) |
1020 | local boxWidth, boxHeight = self:scalePixelToScreenVector(boxSize) |
1021 | local count = 0 |
1022 | for i, combo in ipairs(combos) do |
1023 | -- Background |
1024 | local overlay = Overlay.new(g_baseUIFilename, frameX + headerItemWidth * (i - 1) + entryOffset * (i - 1), posY, headerItemWidth, height) |
1025 | overlay:setUVs(g_colorBgUVs) |
1026 | overlay:setColor(0, 0, 0, 0.56) |
1027 | headerElement:addChild(HUDElement.new(overlay)) |
1028 | |
1029 | local actionName = combo.controls |
1030 | local glyphElement = self:createComboInputGlyph(0, 0, glyphWidth, glyphHeight, actionName) |
1031 | local glyphModifiedWidth = glyphElement:getGlyphWidth() -- get modified width based on action |
1032 | |
1033 | local glyphPosX = frameX + boxWidth * count + (boxWidth - glyphModifiedWidth) * 0.5 |
1034 | local glyphPosY = posY + (boxHeight - glyphHeight) * 0.5 |
1035 | |
1036 | -- align left and right outer combo icons with help entry icons |
1037 | if i == 1 then -- leftmost |
1038 | local offX = self:scalePixelToScreenWidth(InputHelpDisplay.POSITION.INPUT_GLYPH[1]) |
1039 | glyphPosX = frameX + offX |
1040 | elseif i == #combos then -- rightmost |
1041 | local offX = self:scalePixelToScreenWidth(InputHelpDisplay.POSITION.AXIS_ICON[1]) - glyphModifiedWidth |
1042 | glyphPosX = frameX + boxWidth * i + offX |
1043 | end |
1044 | |
1045 | glyphElement:setPosition(glyphPosX, glyphPosY) |
1046 | headerElement:addChild(glyphElement) |
1047 | |
1048 | self.comboInputGlyphs[actionName] = glyphElement -- store by action name for visibility changes |
1049 | |
1050 | count = count + 1 |
1051 | end |
1052 | |
1053 | return headerElement |
1054 | end |
934 | function InputHelpDisplay:createComponents(hudAtlasPath) |
935 | local baseWidth, baseHeight = getNormalizedScreenValues(unpack(InputHelpDisplay.SIZE.HELP_ENTRY)) |
936 | |
937 | local baseX, baseY = self:getPosition() |
938 | local frame = self:createFrame(hudAtlasPath, baseX, baseY, baseWidth, baseHeight) |
939 | |
940 | local maxEntries = self:getMaxEntryCount(nil, true) |
941 | local frameX, frameY = frame:getPosition() |
942 | self:createEntries(hudAtlasPath, frameX, frameY, maxEntries) |
943 | |
944 | self:createMouseComboHeader(hudAtlasPath, frameX, frameY) |
945 | self:createControllerComboHeader(hudAtlasPath, frameX, frameY) |
946 | end |
1108 | function InputHelpDisplay:createEntries(hudAtlasPath, frameX, frameY, count) |
1109 | local posX, posY = frameX, frameY |
1110 | local entryWidth, entryHeight = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.HELP_ENTRY) |
1111 | local _, entryOffset = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.HELP_ENTRY_OFFSET) |
1112 | |
1113 | local overlay = Overlay.new(nil, posX, posY, entryWidth, entryHeight * count) |
1114 | local entriesFrame = HUDElement.new(overlay) |
1115 | self.entriesFrame = entriesFrame |
1116 | self:addChild(entriesFrame) |
1117 | |
1118 | local totalHeight = count * entryHeight |
1119 | for i = 1, count do |
1120 | posY = frameY + totalHeight - entryHeight * i |
1121 | local entry = self:createEntry(hudAtlasPath, posX, posY, entryWidth, entryHeight - entryOffset) |
1122 | table.insert(self.entries, entry) |
1123 | table.insert(self.entryGlyphWidths, 0) |
1124 | entriesFrame:addChild(entry) |
1125 | end |
1126 | end |
1078 | function InputHelpDisplay:createEntry(hudAtlasPath, posX, posY, width, height) |
1079 | local overlay = Overlay.new(g_baseUIFilename, posX, posY, width, height) |
1080 | overlay:setUVs(g_colorBgUVs) |
1081 | overlay:setColor(0, 0, 0, 0.56) |
1082 | local entryElement = HUDElement.new(overlay) |
1083 | |
1084 | local glyphWidth, glyphHeight = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.INPUT_GLYPH) |
1085 | local offX, offY = self:scalePixelToScreenWidth(InputHelpDisplay.POSITION.INPUT_GLYPH[1]), (height - glyphHeight) * 0.5 |
1086 | |
1087 | overlay = Overlay.new(g_baseUIFilename, posX, posY, glyphWidth + 2 * offX, height) |
1088 | overlay:setUVs(g_colorBgUVs) |
1089 | overlay:setColor(0, 0, 0, 0.6) |
1090 | local glyphBackground = HUDElement.new(overlay) |
1091 | entryElement:addChild(glyphBackground) |
1092 | |
1093 | local glyphElement = InputGlyphElement.new(self.inputDisplayManager, glyphWidth, glyphHeight) |
1094 | glyphElement:setPosition(posX + offX, posY + offY) |
1095 | glyphElement:setKeyboardGlyphColor(InputHelpDisplay.COLOR.INPUT_GLYPH) |
1096 | glyphElement.background = glyphBackground |
1097 | glyphElement.spacing = offX |
1098 | |
1099 | entryElement:addChild(glyphElement) |
1100 | table.insert(self.inputGlyphs, glyphElement) |
1101 | |
1102 | return entryElement |
1103 | end |
725 | function InputHelpDisplay:drawHelpInfos() |
726 | local framePosX, framePosY = self.entriesFrame:getPosition() |
727 | local entriesHeight = self.entriesFrame:getHeight() |
728 | for i, helpElement in ipairs(self.visibleHelpElements) do |
729 | local entryPosY = framePosY + entriesHeight - i * self.entryHeight |
730 | if helpElement.iconOverlay ~= nil then |
731 | local posX = framePosX + self.entryWidth - self.axisIconWidth + self.axisIconOffsetX |
732 | local posY = entryPosY + self.entryHeight * 0.5 |
733 | |
734 | helpElement.iconOverlay:setPosition(posX, posY) |
735 | helpElement.iconOverlay:setDimension(self.axisIconWidth, self.axisIconHeight) |
736 | helpElement.iconOverlay:render() |
737 | else |
738 | setTextBold(false) |
739 | setTextColor(unpack(InputHelpDisplay.COLOR.HELP_TEXT)) |
740 | |
741 | local text = "" |
742 | local posX, posY = framePosX, entryPosY |
743 | local textLeftX = 1 |
744 | if helpElement.textRight ~= "" then |
745 | setTextAlignment(RenderText.ALIGN_RIGHT) |
746 | text = helpElement.textRight |
747 | local textWidth = getTextWidth(self.helpTextSize, text) |
748 | posX = posX + self.entryWidth + self.helpTextOffsetX |
749 | posY = posY + (self.entryHeight - self.helpTextSize) * 0.5 + self.helpTextOffsetY |
750 | textLeftX = posX - textWidth |
751 | elseif helpElement.textLeft ~= "" then |
752 | setTextAlignment(RenderText.ALIGN_LEFT) |
753 | text = helpElement.textLeft |
754 | posX = posX + self.extraTextOffsetX |
755 | posY = posY + (self.entryHeight - self.helpTextSize) * 0.5 + self.extraTextOffsetY |
756 | textLeftX = posX |
757 | end |
758 | |
759 | -- check glyph width and re-align text if necessary |
760 | local glyphWidth = self.entryGlyphWidths[i] or 0 -- 0 -> no glyph to display for this entry |
761 | local glyphLeftX = glyphWidth ~= 0 and self.inputGlyphs[i]:getPosition() or 0 |
762 | local glyphRightX = glyphLeftX + glyphWidth |
763 | |
764 | if glyphRightX < textLeftX then |
765 | renderText(posX, posY, self.helpTextSize, text) |
766 | else |
767 | -- distribute text over two lines |
768 | local availableTextWidth = posX - glyphRightX - math.abs(self.helpTextOffsetX) |
769 | setTextWrapWidth(availableTextWidth) |
770 | setTextLineBounds(0, 2) -- start at first line (engine zero-indexed), for two lines |
771 | |
772 | -- center posY again when using two lines |
773 | posY = entryPosY + self.entryHeight * 0.5 + self.helpTextOffsetY |
774 | renderText(posX, posY, self.helpTextSize, text) |
775 | |
776 | -- reset uncommon text rendering state: |
777 | setTextWrapWidth(0) |
778 | setTextLineBounds(0, 0) |
779 | end |
780 | end |
781 | end |
782 | end |
786 | function InputHelpDisplay:drawVehicleHUDExtensions() |
787 | if self.extensionsHeight > 0 then |
788 | local leftPosX = self:getPosition() |
789 | local width = self:getWidth() |
790 | local posY = self.extensionsStartY |
791 | local usedHeight = 0 |
792 | for _, extension in pairs(self.vehicleHudExtensions) do |
793 | local extHeight = extension:getDisplayHeight() |
794 | if extension:canDraw() and usedHeight + extHeight <= self.extensionsHeight then |
795 | posY = posY - extHeight - self.entryOffsetY |
796 | |
797 | self.extensionBg:setPosition(leftPosX, posY) |
798 | self.extensionBg:setDimension(width, extHeight) |
799 | self.extensionBg:render() |
800 | |
801 | extension:draw(leftPosX + self.extraTextOffsetX, leftPosX + width + self.helpTextOffsetX, posY) |
802 | |
803 | usedHeight = usedHeight + extHeight |
804 | end |
805 | end |
806 | end |
807 | end |
543 | function InputHelpDisplay:getInputHelpElements(availableHeight, pressedComboMaskGamepad, pressedComboMaskMouse, useGamepadButtons) |
544 | local currentPressedMask = useGamepadButtons and pressedComboMaskGamepad or pressedComboMaskMouse |
545 | local isCombo = currentPressedMask ~= 0 |
546 | local isFillUp = false |
547 | |
548 | local eventHelpElements = self.inputDisplayManager:getEventHelpElements(currentPressedMask, useGamepadButtons) |
549 | if #eventHelpElements == 0 and not self.hasComboCommands and isCombo then |
550 | -- just load the base input list without modifier (pressed mask == 0) |
551 | eventHelpElements = self.inputDisplayManager:getEventHelpElements(0, useGamepadButtons) |
552 | isFillUp = true |
553 | end |
554 | |
555 | self.currentHelpElementCount = #eventHelpElements |
556 | local helpElements = {} |
557 | |
558 | local usedHeight = 0 |
559 | local i = 1 |
560 | while usedHeight + self.entryHeight <= availableHeight and i <= #eventHelpElements do |
561 | if not self:getIsHelpElementAllowed(helpElements, eventHelpElements[i]) then |
562 | break |
563 | end |
564 | |
565 | table.insert(helpElements, eventHelpElements[i]) |
566 | usedHeight = usedHeight + self.entryHeight |
567 | i = i + 1 |
568 | end |
569 | |
570 | local contextCustomElements = self.customHelpElements[self.inputManager:getContextName()] |
571 | if contextCustomElements ~= nil then |
572 | self.currentHelpElementCount = self.currentHelpElementCount + #contextCustomElements |
573 | |
574 | i = 1 |
575 | while usedHeight + self.entryHeight <= availableHeight and i <= #contextCustomElements do |
576 | local customHelpElement = contextCustomElements[i] |
577 | -- display custom element if bindings and controller symbols could be resolved, otherwise a null-element is |
578 | -- returned which we test against: |
579 | if customHelpElement ~= InputDisplayManager.NO_HELP_ELEMENT then |
580 | local action = self.inputManager:getActionByName(customHelpElement.actionName) |
581 | if action ~= nil then |
582 | local fitsComboMask = action.comboMaskGamepad == pressedComboMaskGamepad and action.comboMaskMouse == pressedComboMaskMouse |
583 | local noComboFillUp = action.comboMaskGamepad == 0 and action.comboMaskMouse == 0 and isFillUp |
584 | |
585 | if fitsComboMask or noComboFillUp then |
586 | table.insert(helpElements, customHelpElement) |
587 | usedHeight = usedHeight + self.entryHeight |
588 | end |
589 | end |
590 | end |
591 | |
592 | i = i + 1 |
593 | end |
594 | end |
595 | |
596 | return helpElements, usedHeight |
597 | end |
28 | function InputHelpDisplay.new(hudAtlasPath, messageCenter, inputManager, inputDisplayManager, ingameMap, communicationDisplay, ingameMessage, isConsoleVersion) |
29 | local backgroundOverlay = InputHelpDisplay.createBackground() |
30 | local self = InputHelpDisplay:superClass().new(backgroundOverlay, nil, InputHelpDisplay_mt) |
31 | |
32 | self.messageCenter = messageCenter |
33 | self.inputManager = inputManager |
34 | self.inputDisplayManager = inputDisplayManager |
35 | self.ingameMap = ingameMap |
36 | self.communicationDisplay = communicationDisplay |
37 | self.ingameMessage = ingameMessage |
38 | self.isConsoleVersion = isConsoleVersion |
39 | |
40 | self.isOverlayMenuVisible = false |
41 | |
42 | self.controlsLabelText = utf8ToUpper(g_i18n:getText(InputHelpDisplay.L10N_CONTROLS_LABEL)) |
43 | |
44 | self.vehicle = nil -- currently controlled vehicle |
45 | self.vehicleHudExtensions = {} -- known and active vehicle HUD extensions, specialization -> extension |
46 | |
47 | self.extraHelpTexts = {} |
48 | self.extraExtensionVehicleNodeIds = {} -- vehicle nodeIds to draw HUDExtensions for, which are not controlled by player |
49 | self.currentAvailableHeight = 0 |
50 | |
51 | self.comboInputGlyphs = {} -- actionName -> InputGlyphElement |
52 | self.entries = {} -- array of HUDElement |
53 | self.entryGlyphWidths = {} -- array of float -> synchronous with self.entries, stores the currently required glyph width |
54 | self.inputGlyphs = {} -- array of InputGlyphElement, synchronous with self.entries |
55 | self.horizontalSeparators = {} -- array of HUDElement |
56 | self.frame = nil -- HUDFrameElement for the background frame |
57 | self.entriesFrame = nil -- HUDElement which holds all help entries for repositioning |
58 | self.mouseComboHeader = nil |
59 | self.gamepadComboHeader = nil |
60 | self.customHelpElements = {} -- array of InputHelpElement |
61 | |
62 | self.headerHeight = 0 |
63 | self.entryWidth, self.entryHeight = 0, 0 |
64 | self.controlsLabelTextSize = 0 |
65 | self.controlsLabelOffsetX, self.controlsLabelOffsetY = 0, 0 |
66 | self.helpTextSize = 0 |
67 | self.helpTextOffsetX, self.helpTextOffsetY = 0, 0 |
68 | self.extraTextOffsetX, self.extraTextOffsetY = 0, 0 |
69 | self.axisIconOffsetX = 0 |
70 | self.axisIconWidth, self.axisIconHeight = 0, 0 |
71 | self.frameOffsetX, self.frameOffsetY = 0, 0 |
72 | self.frameBarOffsetY = 0 |
73 | |
74 | self.hasComboCommands = false |
75 | self.visibleHelpElements = {} -- current frame help elements |
76 | self.currentHelpElementCount = 0 -- maximum number of help elements which are currently active |
77 | self.requireHudExtensionsRefresh = false |
78 | self.numUsedEntries = 0 -- number of used entries in the current frame |
79 | self.extensionsHeight = 0 -- screen height of active HUDExensions in the current frame |
80 | self.extensionsStartY = 0 -- start Y position of vehicle extensions |
81 | self.comboIterator = {} |
82 | |
83 | self.animationAvailableHeight = math.huge |
84 | self.animationOffsetX = 0 |
85 | self.animationOffsetY = 0 |
86 | |
87 | self.extensionBg = Overlay.new(g_baseUIFilename, 0, 0, 1, 1) |
88 | self.extensionBg:setUVs(g_colorBgUVs) |
89 | self.extensionBg:setColor(0, 0, 0, 0.56) |
90 | |
91 | self:createComponents(hudAtlasPath) |
92 | self:subscribeMessages() |
93 | |
94 | return self |
95 | end |
655 | function InputHelpDisplay:onInputDevicesChanged() |
656 | for _, combos in pairs{InputBinding.ORDERED_MOUSE_COMBOS, InputBinding.ORDERED_GAMEPAD_COMBOS} do |
657 | for i, combo in ipairs(combos) do |
658 | local actionName = combo.controls |
659 | local glyphElement = self.comboInputGlyphs[actionName] |
660 | local prevWidth = glyphElement:getGlyphWidth() |
661 | glyphElement:setAction(actionName, nil, nil, false, true) -- no action text, use combo buttons, make copies of overlays |
662 | local glyphWidth = glyphElement:getGlyphWidth() -- get modified width based on action |
663 | |
664 | -- reposition glyphs |
665 | if prevWidth ~= glyphWidth then |
666 | if i > 1 then -- first (left) glyph is always correctly aligned, no correction needed |
667 | local posX, posY = glyphElement:getPosition() |
668 | if i == #combos then |
669 | posX = posX + prevWidth - glyphWidth |
670 | else |
671 | posX = posX + (prevWidth - glyphWidth) * 0.5 |
672 | end |
673 | |
674 | glyphElement:setPosition(posX, posY) |
675 | end |
676 | end |
677 | end |
678 | end |
679 | end |
270 | function InputHelpDisplay:refreshHUDExtensions() |
271 | --#profile g_remoteProfiler:ZoneBeginN(" InputHelpDisplay:refreshHUDExtensions") |
272 | for k, hudExtension in pairs(self.vehicleHudExtensions) do |
273 | hudExtension:delete() |
274 | self.vehicleHudExtensions[k] = nil |
275 | end |
276 | |
277 | local uiScale = self:getScale() |
278 | |
279 | local vehiclesAlreadyAdded = {} -- keep track of vehicles for which HUDExtensions were already added to avoid duplicates |
280 | |
281 | local function addExtensionForVehicle(vehicle, drawableWhileNotActive) |
282 | if vehiclesAlreadyAdded[vehicle] ~= nil then |
283 | return |
284 | end |
285 | for j=1, #vehicle.specializations do |
286 | local spec = vehicle.specializations[j] |
287 | local hudExtension = self.vehicleHudExtensions[spec] |
288 | if hudExtension == nil and VehicleHUDExtension.hasHUDExtensionForSpecialization(spec) then |
289 | hudExtension = VehicleHUDExtension.createHUDExtensionForSpecialization(spec, vehicle, uiScale, InputHelpDisplay.COLOR.HELP_TEXT, self.helpTextSize) |
290 | if drawableWhileNotActive then |
291 | hudExtension.canDraw = function() return g_currentMission.accessHandler:canPlayerAccess(hudExtension.vehicle) end |
292 | end |
293 | |
294 | table.addElement(self.vehicleHudExtensions, hudExtension) |
295 | vehiclesAlreadyAdded[vehicle] = true |
296 | end |
297 | end |
298 | end |
299 | |
300 | -- add extensions for currently controlled vehicle and attached implements |
301 | if self.vehicle ~= nil then |
302 | local vehicles = self.vehicle.rootVehicle.childVehicles |
303 | for i=1, #vehicles do |
304 | addExtensionForVehicle(vehicles[i]) |
305 | end |
306 | end |
307 | |
308 | -- add extensions for vehicles not currently controlled such as mixer wagons near the player |
309 | for i=#self.extraExtensionVehicleNodeIds, 1, -1 do |
310 | local vehicleNodeId = self.extraExtensionVehicleNodeIds[i] |
311 | local vehicle = g_currentMission.nodeToObject[vehicleNodeId] |
312 | if vehicle == nil then |
313 | table.remove(self.extraExtensionVehicleNodeIds, i) |
314 | elseif self.vehicle ~= vehicle then |
315 | if vehicle.getIsPlayerInTrigger == nil or (vehicle.getIsPlayerInTrigger and vehicle:getIsPlayerInTrigger()) then |
316 | addExtensionForVehicle(vehicle, true) |
317 | end |
318 | end |
319 | end |
320 | |
321 | table.sort(self.vehicleHudExtensions, VehicleHUDExtension.sortHUDExtensions) |
322 | --#profile g_remoteProfiler:ZoneEnd() |
323 | end |
823 | function InputHelpDisplay:storeScaledValues() |
824 | self.headerHeight = self:scalePixelToScreenHeight(InputHelpDisplay.SIZE.HEADER[2]) |
825 | self.entryWidth, self.entryHeight = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.HELP_ENTRY) |
826 | self.controlsLabelTextSize = self:scalePixelToScreenHeight(HUDElement.TEXT_SIZE.DEFAULT_TITLE) |
827 | self.controlsLabelOffsetX, self.controlsLabelOffsetY = self:scalePixelToScreenVector(InputHelpDisplay.POSITION.CONTROLS_LABEL) |
828 | self.helpTextSize = self:scalePixelToScreenHeight(HUDElement.TEXT_SIZE.DEFAULT_TEXT) |
829 | self.helpTextOffsetX, self.helpTextOffsetY = self:scalePixelToScreenVector(InputHelpDisplay.POSITION.HELP_TEXT) |
830 | self.extraTextOffsetX, self.extraTextOffsetY = self:scalePixelToScreenVector(InputHelpDisplay.POSITION.EXTRA_TEXT) |
831 | self.axisIconOffsetX = self:scalePixelToScreenWidth(InputHelpDisplay.POSITION.AXIS_ICON[1]) |
832 | self.axisIconWidth, self.axisIconHeight = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.AXIS_ICON) |
833 | self.frameOffsetX, self.frameOffsetY = self:scalePixelToScreenVector(InputHelpDisplay.POSITION.FRAME) |
834 | self.frameBarOffsetY = self:scalePixelToScreenHeight(HUDFrameElement.THICKNESS.BAR) |
835 | self.minimumMapSpacingY = self:scalePixelToScreenHeight(InputHelpDisplay.MIN_MAP_SPACING) |
836 | self.entryOffsetX, self.entryOffsetY = self:scalePixelToScreenVector(InputHelpDisplay.SIZE.HELP_ENTRY_OFFSET) |
837 | |
838 | for _, element in ipairs(self.inputGlyphs) do |
839 | element.spacing = self:scalePixelToScreenWidth(InputHelpDisplay.POSITION.INPUT_GLYPH[1]) |
840 | end |
841 | end |
511 | function InputHelpDisplay:updateComboInputGlyphs(comboActionStatus, pressedComboMaskMouse, pressedComboMaskGamepad) |
512 | self.comboIterator[InputBinding.MOUSE_COMBOS] = pressedComboMaskMouse |
513 | self.comboIterator[InputBinding.GAMEPAD_COMBOS] = pressedComboMaskGamepad |
514 | |
515 | -- apply visibility settings to combo buttons |
516 | for actionCombos, pressedComboMask in pairs(self.comboIterator) do |
517 | for actionName, comboData in pairs(actionCombos) do |
518 | local comboGlyph = self.comboInputGlyphs[actionName] |
519 | if comboActionStatus[actionName] then |
520 | comboGlyph:setVisible(true) |
521 | |
522 | local isPressed = bitAND(pressedComboMask, comboData.mask) ~= 0 |
523 | if isPressed then |
524 | comboGlyph:setButtonGlyphColor(InputHelpDisplay.COLOR.COMBO_GLYPH_PRESSED) |
525 | else |
526 | comboGlyph:setButtonGlyphColor(InputHelpDisplay.COLOR.COMBO_GLYPH) |
527 | end |
528 | else |
529 | comboGlyph:setVisible(false) |
530 | end |
531 | end |
532 | end |
533 | end |
435 | function InputHelpDisplay:updateEntries(helpElements) |
436 | local usedCount = 0 |
437 | |
438 | local entryCount = #self.entries |
439 | local separatorCount = math.min(#helpElements - 1, entryCount - 1) |
440 | if self.extensionsHeight > 0 and not self.ingameMap:getIsLarge() then |
441 | separatorCount = separatorCount + 1 |
442 | end |
443 | |
444 | for i = 1, entryCount do |
445 | local entry = self.entries[i] |
446 | if i <= #helpElements then |
447 | usedCount = usedCount + 1 |
448 | |
449 | local helpElement = helpElements[i] |
450 | |
451 | local showInput = #helpElement.buttons > 0 or #helpElement.keys > 0 |
452 | local showText = helpElement.textLeft ~= "" |
453 | |
454 | entry:setVisible(showInput or showText) |
455 | self.inputGlyphs[i]:setVisible(not showText) |
456 | self.inputGlyphs[i].background:setVisible(not showText) |
457 | |
458 | if helpElement.actionName ~= "" then |
459 | if helpElement.actionName2 ~= "" then |
460 | self.inputGlyphs[i]:setActions({helpElement.actionName, helpElement.actionName2}, nil, nil, helpElement.inlineModifierButtons) |
461 | else |
462 | self.inputGlyphs[i]:setAction(helpElement.actionName, nil, nil, helpElement.inlineModifierButtons) -- no action text, do not show combo buttons |
463 | end |
464 | |
465 | self.entryGlyphWidths[i] = self.inputGlyphs[i]:getGlyphWidth() |
466 | |
467 | self.inputGlyphs[i].background:setDimension(self.entryGlyphWidths[i] + 2 * self.inputGlyphs[i].spacing) |
468 | else |
469 | self.entryGlyphWidths[i] = 0 |
470 | end |
471 | else |
472 | entry:setVisible(false) |
473 | end |
474 | end |
475 | |
476 | for i = 1, #self.horizontalSeparators do |
477 | local separator = self.horizontalSeparators[i] |
478 | separator:setVisible(i <= separatorCount) |
479 | end |
480 | |
481 | self.sizeAndPositionDirty = self.sizeAndPositionDirty or self.numUsedEntries ~= usedCount |
482 | self.numUsedEntries = usedCount |
483 | end |
327 | function InputHelpDisplay:updateHUDExtensions() |
328 | if self.vehicle ~= nil then -- update HUD extensions, can change when implements are attached / detached |
329 | local currentHash = self:getCurrentVehicleTypeHash(self.vehicle) |
330 | if currentHash ~= self.lastVehicleSpecHash then |
331 | self.requireHudExtensionsRefresh = true |
332 | self.lastVehicleSpecHash = currentHash |
333 | end |
334 | else |
335 | self.lastVehicleSpecHash = nil |
336 | end |
337 | |
338 | -- check if vehicle for nodeId still exists |
339 | for i=#self.extraExtensionVehicleNodeIds, 1, -1 do |
340 | local nodeId = self.extraExtensionVehicleNodeIds[i] |
341 | if g_currentMission.nodeToObject[nodeId] == nil then |
342 | table.remove(self.extraExtensionVehicleNodeIds, i) |
343 | self.requireHudExtensionsRefresh = true |
344 | end |
345 | end |
346 | |
347 | -- refresh extensions if number of vehicles changed |
348 | local count = table.size(self.extraExtensionVehicleNodeIds) |
349 | if self.lastExtraExtensionVehiclesCount ~= count then |
350 | self.lastExtraExtensionVehiclesCount = count |
351 | self.requireHudExtensionsRefresh = true |
352 | end |
353 | |
354 | if self.requireHudExtensionsRefresh then |
355 | self:refreshHUDExtensions() |
356 | self.requireHudExtensionsRefresh = false |
357 | end |
358 | |
359 | local extensionsHeight = 0 |
360 | for _, hudExtension in pairs(self.vehicleHudExtensions) do |
361 | local height = hudExtension:getDisplayHeight() |
362 | if hudExtension:canDraw() and extensionsHeight + height <= self.currentAvailableHeight then |
363 | extensionsHeight = extensionsHeight + height |
364 | end |
365 | end |
366 | |
367 | self.sizeAndPositionDirty = self.sizeAndPositionDirty or self.extensionsHeight ~= extensionsHeight |
368 | self.extensionsHeight = extensionsHeight |
369 | end |
400 | function InputHelpDisplay:updateInputContext() |
401 | local availableHeight = self:getAvailableHeight() |
402 | if not self.animation:getFinished() then |
403 | availableHeight = math.min(availableHeight, self.animationAvailableHeight) |
404 | end |
405 | |
406 | local pressedComboMaskGamepad, pressedComboMaskMouse = self.inputManager:getComboCommandPressedMask() |
407 | local useGamepadButtons = self.isConsoleVersion or (self.inputManager:getInputHelpMode() == GS_INPUT_HELP_MODE_GAMEPAD) |
408 | |
409 | self:updateComboHeaders(useGamepadButtons, pressedComboMaskMouse, pressedComboMaskGamepad) |
410 | if self.hasComboCommands then |
411 | availableHeight = availableHeight - self.headerHeight |
412 | end |
413 | |
414 | local helpElements, usedHeight = self:getInputHelpElements(availableHeight, pressedComboMaskGamepad, pressedComboMaskMouse, useGamepadButtons) |
415 | self.visibleHelpElements = helpElements |
416 | availableHeight = availableHeight - usedHeight |
417 | |
418 | for _, text in pairs(self.extraHelpTexts) do |
419 | if availableHeight - self.entryHeight >= 0 then |
420 | local extraTextHelpElement = InputHelpElement.new(nil, nil, nil, nil, nil, text) |
421 | table.insert(helpElements, extraTextHelpElement) |
422 | availableHeight = availableHeight - self.entryHeight |
423 | else |
424 | break |
425 | end |
426 | end |
427 | |
428 | self:updateEntries(helpElements) |
429 | self.currentAvailableHeight = availableHeight -- store remainder for dynamic components (e.g. HUD extensions) |
430 | end |
234 | function InputHelpDisplay:updateSizeAndPositions() |
235 | local totalSize = 0--- self.frameOffsetY |
236 | |
237 | local baseX, baseTopY = self:getTopLeftPosition() |
238 | local frameX, frameTopY = baseX + self.frameOffsetX, baseTopY + self.frameOffsetY |
239 | local entriesHeight = self.entriesFrame:getHeight() |
240 | local entriesPosY = frameTopY - entriesHeight |
241 | |
242 | if self.hasComboCommands then |
243 | totalSize = totalSize + self.headerHeight |
244 | entriesPosY = entriesPosY - self.headerHeight |
245 | end |
246 | |
247 | totalSize = totalSize + self.numUsedEntries * self.entryHeight |
248 | self.extensionsStartY = frameTopY - totalSize -- store the extensions starting Y position for drawing |
249 | |
250 | totalSize = totalSize + self.extensionsHeight |
251 | |
252 | self:setDimension(self:getWidth(), totalSize) |
253 | self:setPosition(baseX, baseTopY - totalSize) |
254 | |
255 | if self:getVisible() and not self.animation:getFinished() then |
256 | self:storeOriginalPosition() |
257 | end |
258 | |
259 | -- need to adjust header positions to keep them anchored to top left |
260 | self.mouseComboHeader:setPosition(frameX, frameTopY - self.headerHeight) |
261 | self.gamepadComboHeader:setPosition(frameX, frameTopY - self.headerHeight) |
262 | |
263 | self.entriesFrame:setPosition(frameX, entriesPosY) -- moves up or down depending on header visibility |
264 | local frameHeight = self:getHeight() + self.frameOffsetY + self.frameBarOffsetY |
265 | self.frame:setPosition(frameX, frameTopY - frameHeight) |
266 | end |