summaryrefslogtreecommitdiff
path: root/src/FLD.hpp
blob: a9aed5e9c3c8e17515768d13e4bc1ea474a57ee0 (plain)
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
#pragma once
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_scancode.h>
#include <SDL2/SDL_gamecontroller.h>
#include <string>
#include <map>
#include <array>
#include <climits>
#include "soloud.h"

#define READONLY(T, X, V) private: T _##X = V; public: decltype(_##X) const& X = _##X

class FLD {
public:
	using Error = int;
	using Uint = unsigned int;
	using MainLoop = int (*)(FLD& fld, void *udata);
	enum class InputState {
		Up,
		Down,
		Release,
		Press
	};
	struct Config {
		int width = 640;
		int height = 480;
		int scale = 1;
		int target_fps = 60;
		bool pixel_perfect = true;
		bool hide_cursor = true;
		std::string title = "FLD project";
	};
	struct Color {
		float r = -1.0f;
		float g = -1.0f;
		float b = -1.0f;
		float a = -1.0f;
	};
	struct Point {
		int x;
		int y;
	};
	struct Rectangle {
		int x;
		int y;
		int w;
		int h;
	};
	struct DrawImageOpts {
		const Point& p;
		int ix = 0;
		int iy = 0;
		int w = INT_MIN;
		int h = INT_MIN;
		float r = 0.0f;
		float sx = 1.0f;
		float sy = 1.0f;
		Uint f = NONE;
	};
	struct Image {
		FLD *fld = nullptr;
		std::string path = "";
		bool valid = true;
		SDL_Texture *ptr = nullptr;
		int width = 0;
		int height = 0;

		[[nodiscard]] Error invalid() const;
		Error draw(const DrawImageOpts& opts) const;
		Error setScaleMode(SDL_ScaleMode scale_mode) const;
	};
	enum DrawFlag {
		NONE = 0,
		FILL = 1,
		CENTER = 2,
		FLIP_X = 4,
		FLIP_Y = 8,
	};
	static constexpr Color BLACK {0.0f, 0.0f, 0.0f, -1.0f};
	static constexpr Color RED {1.0f, 0.0f, 0.0f, -1.0f};
	static constexpr Color GREEN {0.0f, 1.0f, 0.0f, -1.0f};
	static constexpr Color BLUE {0.0f, 0.0f, 1.0f, -1.0f};
	static constexpr Color YELLOW {1.0f, 1.0f, 0.0f, -1.0f};
	static constexpr Color PURPLE {1.0f, 0.0f, 1.0f, -1.0f};
	static constexpr Color CYAN {0.0f, 1.0f, 1.0f, -1.0f};
	static constexpr Color WHITE {1.0f, 1.0f, 1.0f, -1.0f};
	Point viewport = {0, 0};

	const Config config;
	SoLoud::Soloud soloud = {};
	READONLY(SDL_Window *, window, nullptr);
	READONLY(SDL_Renderer *, renderer, nullptr);
	READONLY(SDL_Texture *, target, nullptr);
	READONLY(unsigned long, tick, 0);
	READONLY(Color, drawColor, Color({0, 0, 0, 1}));
public:
	explicit FLD(const Config& config);
	explicit FLD(const Config&& config);
	~FLD();

	[[nodiscard]] Error init();
	[[nodiscard]] Error init(MainLoop main_loop, void *udata=nullptr);
	void run(MainLoop main_loop, void *udata = nullptr);

	[[nodiscard]] Error drawBegin() const;
	[[nodiscard]] Error drawEnd();
	Error drawSetColor(const Color& c);
	Error drawClear() const;
	Error drawPoint(const Point& p) const;
	Error drawLine(const Point& p0, const Point& p1) const;
	Error drawRectangle(const Rectangle& rect, Uint flags=NONE) const;

	[[nodiscard]] Image& image(const std::string& path);

	[[nodiscard]] InputState keyGet(SDL_Scancode sc) const;
	[[nodiscard]] bool keyDown(SDL_Scancode sc) const;
	[[nodiscard]] bool keyUp(SDL_Scancode sc) const;
	[[nodiscard]] bool keyPressed(SDL_Scancode sc) const;
	[[nodiscard]] bool keyReleased(SDL_Scancode sc) const;

	[[nodiscard]] InputState mouseGet(Uint8 btn) const;
	[[nodiscard]] bool mouseDown(Uint8 btn) const;
	[[nodiscard]] bool mouseUp(Uint8 btn) const;
	[[nodiscard]] bool mousePressed(Uint8 btn) const;
	[[nodiscard]] bool mouseReleased(Uint8 btn) const;

	[[nodiscard]] InputState joyGet(Uint8 btn) const;
	[[nodiscard]] bool joyDown(Uint8 btn) const;
	[[nodiscard]] bool joyUp(Uint8 btn) const;
	[[nodiscard]] bool joyPressed(Uint8 btn) const;
	[[nodiscard]] bool joyReleased(Uint8 btn) const;
private:
	bool shouldQuit = false;
	struct {
		bool managed = false;
		Uint64 min_dt;
		Uint64 next_time;
	} fps;
	struct {
		float scale = 1.0;
		int off_x = 0;
		int off_y = 0;
	} transform;
	std::map<const std::string, Image> images = {};
	std::array<InputState, SDL_NUM_SCANCODES> keystates = {};
	std::array<InputState, 256> mousestates = {};
	std::array<InputState, SDL_CONTROLLER_BUTTON_MAX> joystates = {};

	Error sdlError(const std::string& msg="") const;
	Error soloudError(SoLoud::result result) const;
	[[nodiscard]] Error initBasepath() const;
	[[nodiscard]] Error initWindow();
	[[nodiscard]] Error initRenderer();
	[[nodiscard]] Error initTarget();
	[[nodiscard]] Error initSoloud();
	void cycleEvents();
};