1 /**
2  * Copyright:       Copyright (C) 2018 Gabriel Gheorghe, All Rights Reserved
3  * Authors:         $(Gabriel Gheorghe)
4  * License:         $(LINK2 https://www.gnu.org/licenses/gpl-3.0.txt, GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007)
5  * Source:          $(LINK2 https://github.com/GabyForceQ/LibertyEngine/blob/master/source/liberty/framework/gui/tilemap.d)
6  * Documentation:
7  * Coverage:
8 **/
9 module liberty.framework.gui.tilemap;
10 
11 import std.container.array : Array;
12 import std.conv : to;
13 import std.typecons : tuple, Tuple;
14 
15 import liberty.framework.gui.meta;
16 
17 import liberty.math.vector;
18 import liberty.framework.gui.event;
19 import liberty.framework.gui.impl;
20 import liberty.math.transform;
21 import liberty.framework.gui.widget;
22 
23 import liberty.framework.gui.controls;
24 
25 /**
26  *
27 **/
28 final class TileMap : Widget {
29   mixin WidgetEventProps!([
30     Event.MouseLeftClick,
31     Event.MouseMiddleClick,
32     Event.MouseRightClick,
33     Event.MouseOver,
34     Event.MouseMove,
35     Event.MouseEnter,
36     Event.MouseLeave,
37     Event.Update,
38   ], "custom");
39 
40   mixin WidgetConstructor;
41 
42   private {
43     Vector2I dimension = Vector2I.zero;
44     Button[] tiles;
45 
46     static foreach (member; getEventArrayString())
47       mixin("Tuple!(Button, Event)[] eventMap" ~ member ~ ";");
48   }
49 
50   /**
51    *
52   **/
53   TileMap setZIndex(int index)   {
54     foreach (tile; tiles)
55       tile.setZIndex(index);
56     
57     return this;
58   }
59 
60   /**
61    *
62   **/
63   TileMap build(int xStartLocation, int yStartLocation, int xDimension, int yDimension,
64     int xScale = 64, int yScale = 64, int xSpaceBetween = 0, int ySpaceBetween = 0)
65   do {
66     return build(
67       Vector2I(xStartLocation, yStartLocation),
68       Vector2I(xDimension, yDimension),
69       Vector2I(xScale, yScale),
70       Vector2I(xSpaceBetween, ySpaceBetween)
71     );
72   }
73 
74   /**
75    *
76   **/
77   TileMap build(Vector2I startLocation, Vector2I dimension,
78     Vector2I scale = Vector2I(64, 64), Vector2I spaceBetween = Vector2I.zero)
79   do {
80     this.dimension = dimension;
81     component!Transform
82       .setLocation(Vector3F(startLocation.x, startLocation.y, 0.0f));
83 
84     foreach (i; 0..dimension.x)
85       foreach (j; 0..dimension.y) {
86         tiles ~= new Button(id ~ "_Tile_" ~ i.to!string ~ "_" ~ j.to!string, getGui);
87         
88         tiles[$ - 1]
89           .setIndex(i, j)
90           .component!Transform
91           .setLocation(
92             i * (scale.x + spaceBetween.x) + component!Transform.getLocation.x,
93             -j * (scale.y + spaceBetween.y) - component!Transform.getLocation.y,
94             0.0f)
95           .setScale(Vector3F(scale.x / 2.0f, scale.y / 2.0f, 1.0f));
96       }
97     
98     return this;
99   }
100 
101   /**
102    *
103   **/
104   Button[] getTiles()   {
105     return tiles;
106   }
107 
108   /**
109    *
110   **/
111   Button getTile(int x, int y) {
112     return getTile(Vector2I(x, y));
113   }
114 
115   /**
116    *
117   **/
118   Button getTile(Vector2I index) {
119     return tiles[dimension.y * index.x + index.y];
120   }
121 
122   /**
123    *
124   **/
125   Vector2I getDimension()   {
126     return dimension;
127   }
128 
129   static foreach (member; getEventArrayString())
130     /**
131      *
132     **/
133     mixin("TileMap create" ~ member ~ "Event()   {"
134       ~ "foreach (i; 0..dimension.x * dimension.y)"
135       ~ "eventMap" ~ member ~ "~= tuple(tiles[i], Event." ~ member ~ ");"
136       ~ "return this; }");
137 
138   static foreach (member; getEventArrayString())
139     /**
140      *
141     **/
142     mixin("Tuple!(Button, Event)[] get" ~ member ~ "Event()  "
143       ~ "{ return eventMap" ~ member ~ "; }");
144 }