* move imageManager code into new imageManager.h/imageManager.cpp
[openc2e.git] / imageManager.cpp
blob274ab88092c9bcbc3d1ab456d685ddb55aa68ecb
1 /*
2 * imageManager.cpp
3 * openc2e
5 * Created by Alyssa Milburn on Sun Jun 06 2004.
6 * Copyright (c) 2004-2008 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "imageManager.h"
21 #include "c16Image.h"
22 #include "sprImage.h"
23 #include "blkImage.h"
24 #include "openc2e.h"
25 #include "World.h"
26 #include "Engine.h"
27 #include "fileSwapper.h"
29 #include "PathResolver.h"
31 #include <iostream>
32 #include <fstream>
34 #include <boost/filesystem/path.hpp>
35 #include <boost/filesystem/operations.hpp>
36 #include <boost/filesystem/convenience.hpp>
38 using namespace boost::filesystem;
40 enum filetype { blk, s16, c16, spr };
42 bool tryOpen(mmapifstream *in, shared_ptr<creaturesImage> &img, std::string fname, filetype ft) {
43 path cachefile, realfile;
44 std::string cachename;
45 if (fname.size() < 5) return false; // not enough chars for an extension and filename..
46 std::string basename = fname; basename.erase(basename.end() - 4, basename.end());
48 // work out where the real file should be
49 switch (ft) {
50 case blk:
51 realfile = path(world.findFile(std::string("/Backgrounds/") + fname), native); break;
53 case spr:
54 case c16:
55 case s16:
56 realfile = path(world.findFile(std::string("/Images/") + fname), native); break;
59 // if it doesn't exist, too bad, give up.
60 if (!exists(realfile)) return false;
62 // work out where the cached file should be
63 cachename = engine.storageDirectory().native_directory_string() + "/" + fname;
64 if (ft == c16) { // TODO: we should really stop the caller from appending .s16/.c16
65 cachename.erase(cachename.end() - 4, cachename.end());
66 cachename.append(".s16");
69 #ifdef __C2E_BIGENDIAN
70 if (ft != spr)
71 cachename = cachename + ".big";
72 #endif
73 cachefile = path(cachename, native);
75 if (resolveFile(cachefile)) {
76 // TODO: check for up-to-date-ness
77 in->clear();
78 in->mmapopen(cachefile.native_file_string());
79 if (ft == c16) ft = s16;
80 goto done;
82 //std::cout << "couldn't find cached version: " << cachefile.native_file_string() << std::endl;
84 in->clear();
85 in->mmapopen(realfile.native_file_string());
86 #ifdef __C2E_BIGENDIAN
87 if (in->is_open() && (ft != spr)) {
88 fileSwapper f;
89 switch (ft) {
90 case blk:
91 f.convertblk(realfile.native_file_string(), cachefile.native_file_string());
92 break;
93 case s16:
94 f.converts16(realfile.native_file_string(), cachefile.native_file_string());
95 break;
96 case c16:
97 //cachefile = change_extension(cachefile, "");
98 //cachefile = change_extension(cachefile, ".s16.big");
99 f.convertc16(realfile.native_file_string(), cachefile.native_file_string());
100 ft = s16;
101 break;
102 default:
103 return true; // TODO: exception?
105 in->close(); // TODO: close the mmap too! how?
106 if (!exists(cachefile)) return false; // TODO: exception?
107 in->mmapopen(cachefile.native_file_string());
109 #endif
110 done:
111 if (in->is_open()) {
112 switch (ft) {
113 case blk: img = shared_ptr<creaturesImage>(new blkImage(in)); break;
114 case c16: img = shared_ptr<creaturesImage>(new c16Image(in)); break; // this should never happen, actually, once we're done
115 case s16: img = shared_ptr<creaturesImage>(new s16Image(in)); break;
116 case spr: img = shared_ptr<creaturesImage>(new sprImage(in)); break;
118 img->name = basename;
120 return in->is_open();
124 * Retrieve an image for rendering use. To retrieve a sprite, pass the name without
125 * extension. To retrieve a background, pass the full filename (ie, with .blk).
127 shared_ptr<creaturesImage> imageManager::getImage(std::string name) {
128 if (name.empty()) return shared_ptr<creaturesImage>(); // empty sprites definitely don't exist
130 // step one: see if the image is already in the gallery
131 std::map<std::string, boost::weak_ptr<creaturesImage> >::iterator i = images.find(name);
132 if (i != images.end() && i->second.lock()) {
133 return i->second.lock();
136 // step two: try opening it in .c16 form first, then try .s16 form
137 mmapifstream *in = new mmapifstream();
138 shared_ptr<creaturesImage> img;
140 if (!tryOpen(in, img, name + ".s16", s16)) {
141 if (!tryOpen(in, img, name + ".c16", c16)) {
142 if (!tryOpen(in, img, name + ".spr", spr)) {
143 bool lasttry = tryOpen(in, img, name, blk);
144 if (!lasttry) {
145 std::cerr << "imageGallery couldn't find the sprite '" << name << "'" << std::endl;
146 return shared_ptr<creaturesImage>();
148 images[name] = img;
149 } else {
150 images[name] = img;
152 } else {
153 images[name] = img;
155 } else {
156 images[name] = img;
159 in->close(); // doesn't close the mmap, which we still need :)
161 return img;
164 /* vim: set noet: */