1 /* DooM2D: Midnight on the Firing Line
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module d2dsprite
is aliced
;
28 //version = tatlas_dump;
31 // ////////////////////////////////////////////////////////////////////////// //
33 __gshared TexAtlas
[] atlases
;
34 __gshared ImgSprite
[string
] sprImages
;
37 // ////////////////////////////////////////////////////////////////////////// //
38 public void realiseSpriteAtlases () {
39 foreach (immutable idx
, TexAtlas a
; atlases
) {
41 import std
.string
: format
;
43 version(tatlas_dump
) writePng("_za%02s.png".format(idx
), a
.img
);
48 // ////////////////////////////////////////////////////////////////////////// //
49 public class ImgSprite
{
55 GLuint listBase
; // gl lists (4)
59 ~this () { if (/*!mirrored &&*/ listBase
) glDeleteLists(listBase
, 4); listBase
= 0; }
63 if (atlas
!is null) return;
66 foreach (TexAtlas a
; atlases
) {
67 auto rc
= a
.insert(vga
);
68 if (rc
.valid
) { arc
= rc
; aa
= a
; break; }
71 int w
= (vga
.width
< 1024 ?
1024 : vga
.width
);
72 int h
= (vga
.height
< 1024 ?
1024 : vga
.height
);
73 aa
= new TexAtlas(w
, h
);
81 frect
= aa
.texCoords(arc
);
85 private void createLists () {
86 listBase
= glGenLists(4);
87 foreach (immutable my
; 0..2) {
88 foreach (immutable mx
; 0..2) {
89 GLuint ln
= listBase
+(my
*2)+mx
;
90 glNewList(ln
, GL_COMPILE
);
91 int x0
= -(mirrored ? vga
.width
-1-vga
.sx
: vga
.sx
);
93 int x1
= x0
+vga
.width
;
94 int y1
= y0
+vga
.height
;
95 if (mx
) { int tmp
= x0
; x0
= x1
; x1
= tmp
; }
96 if (my
) { int tmp
= y0
; y0
= y1
; y1
= tmp
; }
98 glTexCoord2f(frect
.x0
, frect
.y0
); glVertex2i(x0
, y0
); // top-left
99 glTexCoord2f(frect
.x1
, frect
.y0
); glVertex2i(x1
, y0
); // top-right
100 glTexCoord2f(frect
.x1
, frect
.y1
); glVertex2i(x1
, y1
); // bottom-right
101 glTexCoord2f(frect
.x0
, frect
.y1
); glVertex2i(x0
, y1
); // bottom-left
108 void drawAtXY (int x
, int y
, bool mirrorX
=false, bool mirrorY
=false) {
109 if (atlas
is null ||
!atlas
.hasTexture
) return;
110 //if (listBase == 0) createLists();
111 if (mirrored
) mirrorX
= !mirrorX
;
112 ubyte lnum
= (mirrorX ?
0x01 : 0x00)|
(mirrorY ?
0x02 : 0x00);
113 bindTexture(atlas
.tex
.tid
);
115 scope(exit
) glPopMatrix();
116 glTranslatef(x
, y
, 0);
117 glCallList(listBase
+lnum
);
122 public final class ImgSpriteMirrored
: ImgSprite
{
123 private this (ImgSprite aspr
) {
129 assert(atlas
!is null);
130 //listBase = aspr.listBase;
137 // ////////////////////////////////////////////////////////////////////////// //
138 ImgSprite
loadSpriteIntr (string spfilename
, bool checkMirror
, bool updateAtlas
) {
139 if (spfilename
.length
== 0) return null;
141 if (auto imm
= spfilename
in sprImages
) {
143 //conwriteln("cached sprite '", spfilename, "'");
147 import std
.algorithm
: endsWith
;
148 string spnameReal
= spfilename
;
149 if (checkMirror
&& spnameReal
.endsWith("_mirrored.vga")) {
150 // for mirrored, load normal sprite and create mirrored one
151 spnameReal
= spnameReal
[0..$-13]~".vga";
152 if (auto imm
= spnameReal
in sprImages
) {
155 im
= loadSpriteIntr(spnameReal
, false, updateAtlas
);
156 if (im
!is null && updateAtlas
) realiseSpriteAtlases();
158 if (im
is null) return null;
159 im
= new ImgSpriteMirrored(im
);
162 //conwriteln("mirroired sprite '", spfilename, "' [", spnameReal, "]");
164 im
= new ImgSprite();
165 //conwriteln("loading sprite '", spfilename, "'");
166 im
.vga
= new D2DImage(spfilename
);
168 if (updateAtlas
) realiseSpriteAtlases();
170 sprImages
[spfilename
] = im
;
176 public ImgSprite
loadSprite (string spfilename
, bool updateAtlas
=false) { return loadSpriteIntr(spfilename
, true, updateAtlas
); }