File: HUD.h

package info (click to toggle)
jazz2-native 3.5.0-2
  • links: PTS, VCS
  • area: contrib
  • in suites: forky
  • size: 16,912 kB
  • sloc: cpp: 172,557; xml: 113; python: 36; makefile: 5; sh: 2
file content (210 lines) | stat: -rw-r--r-- 7,065 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#pragma once

#include "Canvas.h"
#include "Font.h"
#include "../LevelHandler.h"
#include "../Actors/Player.h"
#include "../Input/ControlScheme.h"
#include "../Input/RgbLights.h"
#include "../Rendering/PlayerViewport.h"

#include "../../nCine/Input/InputEvents.h"

#if defined(WITH_ANGELSCRIPT)
namespace Jazz2::Scripting
{
	class LevelScriptLoader;
}

namespace Jazz2::Scripting::Legacy
{
	struct jjCANVAS;
}
#endif

namespace Jazz2::UI
{
	/** @brief Player HUD */
	class HUD : public Canvas
	{
#if defined(WITH_ANGELSCRIPT)
		friend class Scripting::LevelScriptLoader;
		friend struct Scripting::Legacy::jjCANVAS;
#endif

	public:
#ifndef DOXYGEN_GENERATING_OUTPUT
		static constexpr float DpadLeft = 0.02f;
		static constexpr float DpadBottom = 0.1f;
		static constexpr float DpadThreshold = 0.09f;
		static constexpr float DpadSize = 0.37f;
		static constexpr float ButtonSize = 0.172f;
		static constexpr float SmallButtonSize = 0.098f;
#endif

		HUD(LevelHandler* levelHandler);
		~HUD();

		void OnUpdate(float timeMult) override;
		bool OnDraw(RenderQueue& renderQueue) override;
		void OnTouchEvent(const TouchEvent& event, std::uint32_t& overrideActions);

		/** @brief Shows a text notification */
		void ShowLevelText(StringView text);
		/** @brief Shows a notification about coins */
		void ShowCoins(std::int32_t count);
		/** @brief Shows a notification about gems */
		void ShowGems(std::uint8_t gemType, std::int32_t count);

		/** @brief Begins a fullscreen fade-in transition */
		void BeginFadeIn(bool skip);
		/** @brief Begins a fullscreen face-out transition */
		void BeginFadeOut(float delay = 0.0f);

		/** @brief Returns `true` if weapon wheel is visible */
		bool IsWeaponWheelVisible(std::int32_t playerIndex) const;

	protected:
#ifndef DOXYGEN_GENERATING_OUTPUT
		// Doxygen 1.12.0 outputs also private structs/unions even if it shouldn't
		struct TouchButtonInfo {
			PlayerAction Action;

			float Left;
			float Top;
			float Width;
			float Height;

			GraphicResource* Graphics;
			std::int32_t CurrentPointerId;
			Alignment Align;
		};

		struct Vertex {
			float X, Y;
			float U, V;

			Vertex()
				: X(0.0f), Y(0.0f), U(0.0f), V(0.0f) {}
			Vertex(float x, float y, float u, float v)
				: X(x), Y(y), U(u), V(v) {}
		};

		struct WeaponWheelState {
			SmallVector<std::unique_ptr<RenderCommand>, 0> RenderCommands;
			std::unique_ptr<Vertex[]> Vertices;
			std::int32_t WeaponCount;
			std::int32_t  RenderCommandsCount;
			std::int32_t VerticesCount;
			std::int32_t LastIndex;
			float Anim;
			bool Shown;

			WeaponWheelState();
		};
#endif

		/** @{ @name Constants */

		/** @brief Main layer */
		static constexpr std::uint16_t MainLayer = 100;
		/** @brief Shadow for main layer */
		static constexpr std::uint16_t ShadowLayer = 80;
		/** @brief Font layer */
		static constexpr std::uint16_t FontLayer = 200;
		/** @brief Shadow for font layer */
		static constexpr std::uint16_t FontShadowLayer = 120;
		/** @brief Touch buttons layer */
		static constexpr std::uint16_t TouchButtonsLayer = 400;

		/** @} */
		
#ifndef DOXYGEN_GENERATING_OUTPUT
		LevelHandler* _levelHandler;
		Metadata* _metadata;
		Font* _smallFont;

		String _levelText;
		float _levelTextTime;
		std::int32_t _coins;
		std::int32_t _gems;
		float _coinsTime;
		float _gemsTime;
		std::uint8_t _gemsLastType;
		float _activeBossTime;
#endif

		/** @brief Called when health of the player needs to be drawn */
		virtual void OnDrawHealth(const Rectf& view, const Rectf& adjustedView, Actors::Player* player);
		/** @brief Called when score of the player needs to be drawn */
		virtual void OnDrawScore(const Rectf& view, Actors::Player* player);
		/** @brief Called when weapon ammo of the player needs to be drawn */
		virtual void OnDrawWeaponAmmo(const Rectf& adjustedView, Actors::Player* player);
		/** @brief Called when health of the active boss needs to be drawn */
		virtual void OnDrawActiveBoss(const Rectf& adjustedView);
		/** @brief Called when a text notification needs to be drawn */
		virtual void OnDrawLevelText(std::int32_t& charOffset);
		/** @brief Called when a notification about coins of the player needs to be drawn */
		virtual void OnDrawCoins(const Rectf& view, std::int32_t& charOffset);
		/** @brief Called when a notification about gems of the player needs to be drawn */
		virtual void OnDrawGems(const Rectf& view, std::int32_t& charOffset);
		/** @brief Called when touch buttons need to be drawn */
		void OnDrawTouchButtons(Actors::Player* player);

		/** @brief Draws carrotized health bar (Reforged) */
		void DrawHealthCarrots(float x, float y, std::int32_t health);
		/** @brief Draws separators of split-screen viewports */
		void DrawViewportSeparators();
		/** @brief Draws a textured element */
		void DrawElement(AnimState state, std::int32_t frame, float x, float y, std::uint16_t z, Alignment align, const Colorf& color,
			float scaleX = 1.0f, float scaleY = 1.0f, bool additiveBlending = false, float angle = 0.0f);
		/** @brief Draws a textured element with clipping */
		void DrawElementClipped(AnimState state, std::int32_t frame, float x, float y, std::uint16_t z, Alignment align,
			const Colorf& color, float clipX, float clipY);
	
	private:
		enum class TransitionState {
			None,
			WaitingForFadeIn,
			FadeIn,
			FadeOut,
			WaitingForFadeOut
		};

		static constexpr std::uint32_t VertexBytes = sizeof(Vertex);
		static constexpr std::uint32_t VertexFloats = VertexBytes / sizeof(float);

		static constexpr Alignment Fixed = (Alignment)0x40;
		static constexpr Alignment AllowRollover = (Alignment)0x80;

		static constexpr std::int32_t TouchButtonsCount = 11;
		static constexpr float WeaponWheelAnimDuration = 20.0f;
		static constexpr std::int32_t WeaponWheelMaxVertices = 768;

		float _rgbAmbientLight;
		float _rgbHealthLast;

		WeaponWheelState _weaponWheel[ControlScheme::MaxSupportedPlayers];
		float _rgbLightsAnim;
		float _rgbLightsTime;
		TransitionState _transitionState;
		float _transitionTime;

		TouchButtonInfo _touchButtons[TouchButtonsCount];
		float _touchButtonsTimer;

		AnimState GetCurrentWeapon(Actors::Player* player, WeaponType weapon, Vector2f& offset);
		void DrawWeaponWheel(const Rectf& view, Actors::Player* player);
		void UpdateWeaponWheel(float timeMult);
		bool PrepareWeaponWheel(Actors::Player* player, std::int32_t& weaponCount);
		static std::int32_t GetWeaponCount(Actors::Player* player);
		void DrawWeaponWheelSegment(WeaponWheelState& state, float x, float y, float width, float height, std::uint16_t z, float minAngle, float maxAngle, const Texture& texture, const Colorf& color);

		TouchButtonInfo CreateTouchButton(PlayerAction action, AnimState state, Alignment align, float x, float y, float w, float h);
		bool IsOnButton(const TouchButtonInfo& button, float x, float y);

		void UpdateRgbLights(float timeMult, Rendering::PlayerViewport* viewport);
		static Color ApplyRgbGradientAlpha(Color color, std::int32_t x, std::int32_t y, float animProgress, float ambientLight);
		static AuraLight KeyToAuraLight(Keys key);
	};
}