]> git.localhorst.tv Git - l2e.git/blob - src/graphics/Frame.cpp
46fa1b59db7c799255c282f90e9fe92c654a509d
[l2e.git] / src / graphics / Frame.cpp
1 /*
2  * Frame.cpp
3  *
4  *  Created on: Aug 7, 2012
5  *      Author: holy
6  */
7
8 #include "Frame.h"
9
10 #include "../loader/Interpreter.h"
11 #include "../loader/TypeDescription.h"
12
13 using geometry::Vector;
14 using loader::FieldDescription;
15 using loader::Interpreter;
16 using loader::TypeDescription;
17
18 namespace graphics {
19
20 // TODO: maybe create a cache for frames?
21 void Frame::Draw(SDL_Surface *dest, const Vector<int> &position, int width, int height) const {
22         if (!surface) {
23                 SDL_Rect rect;
24                 rect.x = position.X();
25                 rect.y = position.Y();
26                 rect.w = width;
27                 rect.h = height;
28                 SDL_FillRect(dest, &rect, SDL_MapRGB(dest->format, 0xFF, 0x00, 0x00));
29                 return;
30         }
31         // top-left corner
32         SDL_Rect srcRect;
33         srcRect.x = offset.X();
34         srcRect.y = offset.Y();
35         srcRect.w = BorderWidth();
36         srcRect.h = BorderHeight();
37         SDL_Rect destRect;
38         destRect.x = position.X();
39         destRect.y = position.Y();
40         SDL_BlitSurface(surface, &srcRect, dest, &destRect);
41
42         // top border
43         srcRect.x += BorderWidth();
44         srcRect.w = RepeatWidth();
45         destRect.x += BorderWidth();
46         int fullRepeatWidth(width - (2 * BorderWidth()));
47         int repeatCursor(0);
48         while (repeatCursor < fullRepeatWidth) {
49                 SDL_BlitSurface(surface, &srcRect, dest, &destRect);
50                 destRect.x += RepeatWidth();
51                 repeatCursor += RepeatWidth();
52         }
53
54         // top-right corner
55         srcRect.x += RepeatWidth();
56         srcRect.w = BorderWidth();
57         SDL_BlitSurface(surface, &srcRect, dest, &destRect);
58
59         // middle
60         destRect.y += BorderHeight();
61         int fullRepeatHeight(height - (2 * BorderHeight()));
62         int hRepeatCursor(0);
63         while (hRepeatCursor < fullRepeatHeight) {
64
65                 // left border
66                 srcRect.x = offset.X();
67                 srcRect.y = offset.Y() + BorderHeight();
68                 srcRect.w = BorderWidth();
69                 srcRect.h = RepeatHeight();
70                 destRect.x = position.X();
71                 SDL_BlitSurface(surface, &srcRect, dest, &destRect);
72
73                 // fill
74                 repeatCursor = 0;
75                 srcRect.x += BorderWidth();
76                 srcRect.w = RepeatWidth();
77                 destRect.x += BorderWidth();
78                 while (repeatCursor < fullRepeatWidth) {
79                         SDL_BlitSurface(surface, &srcRect, dest, &destRect);
80                         destRect.x += RepeatWidth();
81                         repeatCursor += RepeatWidth();
82                 }
83
84                 // right border
85                 srcRect.x += RepeatWidth();
86                 srcRect.w = BorderWidth();
87                 SDL_BlitSurface(surface, &srcRect, dest, &destRect);
88
89                 destRect.y += RepeatHeight();
90                 hRepeatCursor += RepeatHeight();
91         }
92
93         // bottom-left corner
94         srcRect.x = offset.X();
95         srcRect.y = offset.Y() + BorderHeight() + RepeatHeight();
96         srcRect.w = BorderWidth();
97         srcRect.h = BorderHeight();
98         destRect.x = position.X();
99         SDL_BlitSurface(surface, &srcRect, dest, &destRect);
100
101         // bottom border
102         srcRect.x += BorderWidth();
103         srcRect.w = RepeatWidth();
104         destRect.x += BorderWidth();
105         repeatCursor = 0;
106         while (repeatCursor < fullRepeatWidth) {
107                 SDL_BlitSurface(surface, &srcRect, dest, &destRect);
108                 destRect.x += RepeatWidth();
109                 repeatCursor += RepeatWidth();
110         }
111         if (fullRepeatWidth < fullRepeatWidth) {
112                 srcRect.w = fullRepeatWidth - fullRepeatWidth;
113                 SDL_BlitSurface(surface, &srcRect, dest, &destRect);
114                 destRect.x += fullRepeatWidth - fullRepeatWidth;
115         }
116
117         // bottom-right corner
118         srcRect.x += RepeatWidth();
119         srcRect.w = BorderWidth();
120         SDL_BlitSurface(surface, &srcRect, dest, &destRect);
121 }
122
123
124 void Frame::CreateTypeDescription() {
125         Frame f;
126
127         TypeDescription &td(TypeDescription::Create(TYPE_ID, "Frame"));
128         td.SetDescription(
129                         "A frame is basically a border + a background texture.\n"
130                         "It splits an image into 3*3 parts where the edges are kept as is and the sides and the middle part are repeated as needed.");
131         td.SetConstructor(&Construct);
132         td.SetSize(sizeof(Frame));
133
134         td.AddField("image", FieldDescription(((char *)&f.surface) - ((char *)&f), Interpreter::IMAGE_ID).SetReferenced().SetDescription("the underlying graphic from which the frame parts are cut"));
135         td.AddField("border", FieldDescription(((char *)&f.borderSize) - ((char *)&f), Interpreter::VECTOR_ID).SetDescription("size of the border part, dimensions of top-left corner"));
136         td.AddField("repeat", FieldDescription(((char *)&f.repeatSize) - ((char *)&f), Interpreter::VECTOR_ID).SetDescription("size of the repeat part, dimensions of a single tile of the background texture"));
137         td.AddField("offset", FieldDescription(((char *)&f.offset) - ((char *)&f), Interpreter::VECTOR_ID).SetDescription("offset into the image where to start cutting, coordinates of the top-left corner on the image"));
138 }
139
140 void Frame::Construct(void *data) {
141         new (data) Frame;
142 }
143
144 }