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
);
80 frect
= aa
.texCoords(arc
);
84 private void createLists () {
85 listBase
= glGenLists(4);
86 foreach (immutable my
; 0..2) {
87 foreach (immutable mx
; 0..2) {
88 GLuint ln
= listBase
+(my
*2)+mx
;
89 glNewList(ln
, GL_COMPILE
);
90 int x0
= -(mirrored ? vga
.width
-1-vga
.sx
: vga
.sx
);
92 int x1
= x0
+vga
.width
;
93 int y1
= y0
+vga
.height
;
94 if (mx
) { int tmp
= x0
; x0
= x1
; x1
= tmp
; }
95 if (my
) { int tmp
= y0
; y0
= y1
; y1
= tmp
; }
97 glTexCoord2f(frect
.x0
, frect
.y0
); glVertex2i(x0
, y0
); // top-left
98 glTexCoord2f(frect
.x1
, frect
.y0
); glVertex2i(x1
, y0
); // top-right
99 glTexCoord2f(frect
.x1
, frect
.y1
); glVertex2i(x1
, y1
); // bottom-right
100 glTexCoord2f(frect
.x0
, frect
.y1
); glVertex2i(x0
, y1
); // bottom-left
107 void drawAtXY (int x
, int y
, bool mirrorX
=false, bool mirrorY
=false) {
108 if (atlas
is null ||
!atlas
.hasTexture
) return;
109 //if (listBase == 0) createLists();
110 if (mirrored
) mirrorX
= !mirrorX
;
111 ubyte lnum
= (mirrorX ?
0x01 : 0x00)|
(mirrorY ?
0x02 : 0x00);
112 bindTexture(atlas
.tex
.tid
);
114 scope(exit
) glPopMatrix();
115 glTranslatef(x
, y
, 0);
116 glCallList(listBase
+lnum
);
121 public final class ImgSpriteMirrored
: ImgSprite
{
122 private this (ImgSprite aspr
) {
128 assert(atlas
!is null);
129 //listBase = aspr.listBase;
136 // ////////////////////////////////////////////////////////////////////////// //
137 ImgSprite
loadSpriteIntr (string spfilename
, bool checkMirror
, bool updateAtlas
) {
138 if (spfilename
.length
== 0) return null;
140 if (auto imm
= spfilename
in sprImages
) {
142 //conwriteln("cached sprite '", spfilename, "'");
146 import std
.algorithm
: endsWith
;
147 string spnameReal
= spfilename
;
148 if (checkMirror
&& spnameReal
.endsWith("_mirrored.vga")) {
149 // for mirrored, load normal sprite and create mirrored one
150 spnameReal
= spnameReal
[0..$-13]~".vga";
151 if (auto imm
= spnameReal
in sprImages
) {
154 im
= loadSpriteIntr(spnameReal
, false, updateAtlas
);
155 if (im
!is null && updateAtlas
) realiseSpriteAtlases();
157 if (im
is null) return null;
158 im
= new ImgSpriteMirrored(im
);
161 //conwriteln("mirroired sprite '", spfilename, "' [", spnameReal, "]");
163 im
= new ImgSprite();
164 //conwriteln("loading sprite '", spfilename, "'");
165 im
.vga
= new D2DImage(spfilename
);
167 if (updateAtlas
) realiseSpriteAtlases();
169 sprImages
[spfilename
] = im
;
175 public ImgSprite
loadSprite (string spfilename
, bool updateAtlas
=false) { return loadSpriteIntr(spfilename
, true, updateAtlas
); }