add wraparound support to C2 physics
[openc2e.git] / imageManager.cpp
blob1d69cda6cc0b5dcd100da110cba06317d103bab6
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 "bmpImage.h"
25 #include "openc2e.h"
26 #include "World.h"
27 #include "Engine.h"
28 #include "fileSwapper.h"
30 #include "PathResolver.h"
32 #include <iostream>
33 #include <fstream>
35 #include <boost/filesystem/path.hpp>
36 #include <boost/filesystem/operations.hpp>
37 #include <boost/filesystem/convenience.hpp>
39 using namespace boost::filesystem;
41 enum filetype { blk, s16, c16, spr, bmp };
43 bool tryOpen(mmapifstream *in, shared_ptr<creaturesImage> &img, std::string fname, filetype ft, bool is_background = false) {
44 path cachefile, realfile;
45 std::string cachename;
46 if (fname.size() < 5) return false; // not enough chars for an extension and filename..
47 std::string basename = fname; basename.erase(basename.end() - 4, basename.end());
49 if (is_background) {
50 realfile = path(world.findFile(std::string("/Backgrounds/") + fname), native);
51 } else {
52 realfile = path(world.findFile(std::string("/Images/") + fname), native);
55 // if it doesn't exist, too bad, give up.
56 if (!exists(realfile)) return false;
58 // work out where the cached file should be
59 cachename = engine.storageDirectory().native_directory_string() + "/" + fname;
60 if (ft == c16) { // TODO: we should really stop the caller from appending .s16/.c16
61 cachename.erase(cachename.end() - 4, cachename.end());
62 cachename.append(".s16");
65 #if OC2E_BIG_ENDIAN
66 if (ft != spr)
67 cachename = cachename + ".big";
68 #endif
69 cachefile = path(cachename, native);
71 if (resolveFile(cachefile)) {
72 // TODO: check for up-to-date-ness
73 in->clear();
74 in->mmapopen(cachefile.native_file_string());
75 if (ft == c16) ft = s16;
76 goto done;
78 //std::cout << "couldn't find cached version: " << cachefile.native_file_string() << std::endl;
80 in->clear();
81 in->mmapopen(realfile.native_file_string());
82 #if OC2E_BIG_ENDIAN
83 if (in->is_open() && (ft != spr)) {
84 fileSwapper f;
85 switch (ft) {
86 case blk:
87 f.convertblk(realfile.native_file_string(), cachefile.native_file_string());
88 break;
89 case s16:
90 f.converts16(realfile.native_file_string(), cachefile.native_file_string());
91 break;
92 case c16:
93 //cachefile = change_extension(cachefile, "");
94 //cachefile = change_extension(cachefile, ".s16.big");
95 f.convertc16(realfile.native_file_string(), cachefile.native_file_string());
96 ft = s16;
97 break;
98 default:
99 return true; // TODO: exception?
101 in->close(); // TODO: close the mmap too! how?
102 if (!exists(cachefile)) return false; // TODO: exception?
103 in->mmapopen(cachefile.native_file_string());
105 #endif
106 done:
107 if (in->is_open()) {
108 switch (ft) {
109 case blk: img = shared_ptr<creaturesImage>(new blkImage(in, basename)); break;
110 case c16: img = shared_ptr<creaturesImage>(new c16Image(in, basename)); break; // this should never happen, actually, once we're done
111 case s16: img = shared_ptr<creaturesImage>(new s16Image(in, basename)); break;
112 case spr: img = shared_ptr<creaturesImage>(new sprImage(in, basename)); break;
113 case bmp: img = shared_ptr<creaturesImage>(new bmpImage(in, basename)); break; // TODO: don't commit this ;p
116 return in->is_open();
120 * Retrieve an image for rendering use. To retrieve a sprite, pass the name without
121 * extension. To retrieve a background, pass the full filename (ie, with .blk).
123 shared_ptr<creaturesImage> imageManager::getImage(std::string name, bool is_background) {
124 if (name.empty()) return shared_ptr<creaturesImage>(); // empty sprites definitely don't exist
126 // step one: see if the image is already in the gallery
127 std::map<std::string, boost::weak_ptr<creaturesImage> >::iterator i = images.find(name);
128 if (i != images.end() && i->second.lock()) {
129 if (!is_background) return i->second.lock(); // TODO: handle backgrounds
132 // step two: try opening it in .c16 form first, then try .s16 form
133 mmapifstream *in = new mmapifstream();
134 shared_ptr<creaturesImage> img;
136 bool successful = true;
137 if (engine.bmprenderer) {
138 successful = tryOpen(in, img, name + ".bmp", bmp, is_background);
139 } else {
140 if (is_background) {
141 successful = tryOpen(in, img, name + ".blk", blk, true);
142 } else {
143 if (!tryOpen(in, img, name + ".s16", s16)) {
144 if (!tryOpen(in, img, name + ".c16", c16)) {
145 if (!tryOpen(in, img, name + ".spr", spr)) {
146 successful = false;
153 if (successful) {
154 if (!is_background) // TODO: handle backgrounds
155 images[name] = img;
156 } else {
157 std::cerr << "imageGallery couldn't find the sprite '" << name << "'" << std::endl;
158 return shared_ptr<creaturesImage>();
161 in->close(); // doesn't close the mmap, which we still need :)
163 return img;
166 /* vim: set noet: */