summary refs log tree commit diff
path: root/layout.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--layout.h113
1 files changed, 113 insertions, 0 deletions
diff --git a/layout.h b/layout.h
new file mode 100644
index 0000000..1f55967
--- /dev/null
+++ b/layout.h
@@ -0,0 +1,113 @@
+/* Copyright (C) 2019  C. McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LAYOUT_H
+#define LAYOUT_H
+
+#include <SDL_rect.h>
+#include <assert.h>
+
+#include "stack.h"
+
+#ifndef LAYOUT_CAP
+#define LAYOUT_CAP 64
+#endif
+
+typedef unsigned uint;
+
+struct Item {
+	SDL_Rect rect;
+	Card card;
+};
+
+struct List {
+	uint len;
+	struct Item items[LAYOUT_CAP];
+};
+
+static inline void
+listPush(struct List *list, const struct SDL_Rect *rect, Card card) {
+	assert(list->len < LAYOUT_CAP);
+	struct Item item = { *rect, card };
+	list->items[list->len++] = item;
+}
+
+static inline struct Item *listFind(struct List *list, const SDL_Point *point) {
+	for (uint i = list->len - 1; i < list->len; --i) {
+		if (SDL_PointInRect(point, &list->items[i].rect)) {
+			return &list->items[i];
+		}
+	}
+	return NULL;
+}
+
+struct Layout {
+	struct List main;
+	struct List drag;
+	struct Item dragItem;
+};
+
+static inline void layoutClear(struct Layout *layout) {
+	layout->main.len = 0;
+	layout->drag.len = 0;
+}
+
+struct Style {
+	uint increment;
+	int deltaXBack;
+	int deltaYBack;
+	int deltaXFront;
+	int deltaYFront;
+};
+
+static inline void
+layoutStack(
+	struct Layout *layout, SDL_Rect *rect,
+	const struct Stack *stack, const struct Style *style
+) {
+	struct List *list = &layout->main;
+	for (uint i = 0; i < stack->len; ++i) {
+		Card card = stack->cards[i];
+		if (card == layout->dragItem.card) {
+			list = &layout->drag;
+			*rect = layout->dragItem.rect;
+		}
+		listPush(list, rect, card);
+		if ((i + 1) % style->increment == 0) {
+			rect->x += (card > 0 ? style->deltaXFront : style->deltaXBack);
+			rect->y += (card > 0 ? style->deltaYFront : style->deltaYBack);
+		}
+	}
+}
+
+enum {
+	SquareIncrement = 24 / 3,
+	SquareDeltaX = 2,
+	SquareDeltaY = 1,
+
+	FanDownDeltaX = 0,
+	FanDownDeltaYBack = 3,
+	FanDownDeltaYFront = 15,
+};
+
+static const struct Style Square = {
+	SquareIncrement, SquareDeltaX, SquareDeltaY, SquareDeltaX, SquareDeltaY,
+};
+static const struct Style FanDown = {
+	1, FanDownDeltaX, FanDownDeltaYBack, FanDownDeltaX, FanDownDeltaYFront,
+};
+
+#endif