source: trunk/src/tileset.cpp @ 2610

Last change on this file since 2610 was 2610, checked in by sam, 8 years ago

base: a few minor style tweaks.

  • Property svn:keywords set to Id
File size: 6.6 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdlib>
16#include <cstdio>
17#include <cstring>
18
19#if defined WIN32 && !defined _XBOX
20#   define WIN32_LEAN_AND_MEAN
21#   include <windows.h>
22#   if defined USE_D3D9
23#       define FAR
24#       define NEAR
25#       include <d3d9.h>
26#   endif
27#endif
28
29#include "core.h"
30#include "lolgl.h"
31
32using namespace std;
33
34#if defined USE_D3D9
35extern IDirect3DDevice9 *g_d3ddevice;
36#elif defined _XBOX
37extern D3DDevice *g_d3ddevice;
38#endif
39
40namespace lol
41{
42
43/*
44 * TileSet implementation class
45 */
46
47class TileSetData
48{
49    friend class TileSet;
50
51private:
52    String m_name;
53
54    /* Pixels, then texture coordinates */
55    Array<ibox2, box2> m_tiles;
56    ivec2 m_tile_size, m_image_size, m_texture_size;
57
58    Image *m_image;
59    Texture *m_texture;
60};
61
62/*
63 * Public TileSet class
64 */
65
66TileSet::TileSet(char const *path)
67  : m_data(new TileSetData())
68{
69    Init(path);
70}
71
72TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
73  : m_data(new TileSetData())
74{
75    Init(path);
76
77    /* If count is valid, fix size; otherwise, fix count. */
78    if (count.x > 0 && count.y > 0)
79    {
80        size = m_data->m_image_size / count;
81    }
82    else
83    {
84        if (size.x <= 0 || size.y <= 0)
85            size = ivec2(32, 32);
86        count = max(ivec2(1, 1), m_data->m_image_size / size);
87    }
88
89    for (int j = 0; j < count.y; ++j)
90    for (int i = 0; i < count.x; ++i)
91    {
92        AddTile(ibox2(size * ivec2(i, j),
93                      size * ivec2(i + 1, j + 1)));
94    }
95}
96
97void TileSet::Init(char const *path)
98{
99    m_data->m_name = String("<tileset> ") + path;
100
101    m_data->m_texture = 0;
102    m_data->m_image = Image::Create(path);
103    m_data->m_image_size = m_data->m_image->GetSize();
104    m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x),
105                                   PotUp(m_data->m_image_size.y));
106
107    m_drawgroup = DRAWGROUP_BEFORE;
108}
109
110int TileSet::AddTile(ibox2 rect)
111{
112    m_data->m_tiles.Push(rect,
113                         box2((vec2)rect.A / (vec2)m_data->m_texture_size,
114                              (vec2)rect.B / (vec2)m_data->m_texture_size));
115    return m_data->m_tiles.Count() - 1;
116}
117
118TileSet::~TileSet()
119{
120    delete m_data;
121}
122
123void TileSet::TickDraw(float seconds)
124{
125    Entity::TickDraw(seconds);
126
127    if (IsDestroying())
128    {
129        if (m_data->m_image)
130        {
131            Image::Destroy(m_data->m_image);
132            m_data->m_image = nullptr;
133        }
134        else
135        {
136            delete m_data->m_texture;
137            m_data->m_texture = nullptr;
138        }
139    }
140    else if (m_data->m_image)
141    {
142        int planes;
143        PixelFormat format = m_data->m_image->GetFormat();
144
145        switch (format)
146        {
147        case PixelFormat::RGB_8:
148            planes = 3;
149            break;
150        case PixelFormat::RGBA_8:
151        case PixelFormat::ARGB_8:
152        case PixelFormat::ABGR_8:
153        default:
154            planes = 4;
155            break;
156        }
157
158        int w = m_data->m_texture_size.x;
159        int h = m_data->m_texture_size.y;
160
161        uint8_t *pixels = m_data->m_image->GetData();
162        if (w != m_data->m_image_size.x || h != m_data->m_image_size.y)
163        {
164            uint8_t *tmp = new uint8_t[planes * w * h];
165            for (int line = 0; line < m_data->m_image_size.y; line++)
166                memcpy(tmp + planes * w * line,
167                       pixels + planes * m_data->m_image_size.x * line,
168                       planes * m_data->m_image_size.x);
169            pixels = tmp;
170        }
171
172        m_data->m_texture = new Texture(ivec2(w, h), format);
173        m_data->m_texture->SetData(pixels);
174
175        if (pixels != m_data->m_image->GetData())
176            delete[] pixels;
177        Image::Destroy(m_data->m_image);
178        m_data->m_image = nullptr;
179    }
180}
181
182char const *TileSet::GetName()
183{
184    return m_data->m_name.C();
185}
186
187int TileSet::GetTileCount() const
188{
189    return m_data->m_tiles.Count();
190}
191
192ivec2 TileSet::GetTileSize(int tileid) const
193{
194    ibox2 const &box = m_data->m_tiles[tileid].m1;
195    return box.B - box.A;
196}
197
198ivec2 TileSet::GetTextureSize() const
199{
200    return m_data->m_texture_size;
201}
202
203ShaderTexture TileSet::GetTexture() const
204{
205    return m_data->m_texture->GetTexture();
206}
207
208void TileSet::Bind()
209{
210    if (!m_data->m_image && m_data->m_texture)
211        m_data->m_texture->Bind();
212}
213
214void TileSet::Unbind()
215{
216    ;
217}
218
219void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale,
220                       float *vertex, float *texture)
221{
222    ibox2 pixels = m_data->m_tiles[id].m1;
223    box2 texels = m_data->m_tiles[id].m2;
224    float dtx = texels.B.x - texels.A.x;
225    float dty = texels.B.y - texels.A.y;
226    float tx = texels.A.x;
227    float ty = texels.A.y;
228
229    int dx = (pixels.B.x - pixels.A.x) * scale.x;
230    int dy = o ? 0 : (pixels.B.y - pixels.A.y) * scale.y;
231    int dz = o ? (pixels.B.y - pixels.A.y) * scale.y : 0;
232
233    /* If scaling is negative, switch triangle winding */
234    if (scale.x * scale.y < 0.0f)
235    {
236        pos.x += dx;
237        dx = -dx;
238
239        tx += dtx;
240        dtx = -dtx;
241    }
242
243#if 1
244    /* HACK: tweak UV values */
245    tx += (1.f / 128.f) * dtx;
246    ty += (1.f / 128.f) * dty;
247    dtx *= 126.f / 128.f;
248    dty *= 126.f / 128.f;
249#endif
250
251    if (!m_data->m_image && m_data->m_texture)
252    {
253        float tmp[10];
254
255        *vertex++ = pos.x + dx;
256        *vertex++ = pos.y + dy;
257        *vertex++ = pos.z + dz;
258        *texture++ = tx + dtx;
259        *texture++ = ty;
260
261        *vertex++ = tmp[0] = pos.x;
262        *vertex++ = tmp[1] = pos.y + dy;
263        *vertex++ = tmp[2] = pos.z + dz;
264        *texture++ = tmp[3] = tx;
265        *texture++ = tmp[4] = ty;
266
267        *vertex++ = tmp[5] = pos.x + dx;
268        *vertex++ = tmp[6] = pos.y;
269        *vertex++ = tmp[7] = pos.z;
270        *texture++ = tmp[8] = tx + dtx;
271        *texture++ = tmp[9] = ty + dty;
272
273        *vertex++ = tmp[5];
274        *vertex++ = tmp[6];
275        *vertex++ = tmp[7];
276        *texture++ = tmp[8];
277        *texture++ = tmp[9];
278
279        *vertex++ = tmp[0];
280        *vertex++ = tmp[1];
281        *vertex++ = tmp[2];
282        *texture++ = tmp[3];
283        *texture++ = tmp[4];
284
285        *vertex++ = pos.x;
286        *vertex++ = pos.y;
287        *vertex++ = pos.z;
288        *texture++ = tx;
289        *texture++ = ty + dty;
290    }
291    else
292    {
293        memset(vertex, 0, 3 * sizeof(float));
294        memset(texture, 0, 2 * sizeof(float));
295    }
296}
297
298} /* namespace lol */
299
Note: See TracBrowser for help on using the repository browser.