Merging in master
commit
1ce759af06
@ -0,0 +1,123 @@
|
||||
Bitstream Vera Fonts Copyright
|
||||
|
||||
The fonts have a generous copyright, allowing derivative works (as
|
||||
long as "Bitstream" or "Vera" are not in the names), and full
|
||||
redistribution (so long as they are not *sold* by themselves). They
|
||||
can be be bundled, redistributed and sold with any software.
|
||||
|
||||
The fonts are distributed under the following copyright:
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
|
||||
Vera is a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the fonts accompanying this license ("Fonts") and associated
|
||||
documentation files (the "Font Software"), to reproduce and distribute
|
||||
the Font Software, including without limitation the rights to use,
|
||||
copy, merge, publish, distribute, and/or sell copies of the Font
|
||||
Software, and to permit persons to whom the Font Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice
|
||||
shall be included in all copies of one or more of the Font Software
|
||||
typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in
|
||||
particular the designs of glyphs or characters in the Fonts may be
|
||||
modified and additional glyphs or characters may be added to the
|
||||
Fonts, only if the fonts are renamed to names not containing either
|
||||
the words "Bitstream" or the word "Vera".
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts
|
||||
or Font Software that has been modified and is distributed under the
|
||||
"Bitstream Vera" names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but
|
||||
no copy of one or more of the Font Software typefaces may be sold by
|
||||
itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||
BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
|
||||
OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
|
||||
SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome
|
||||
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||
otherwise to promote the sale, use or other dealings in this Font
|
||||
Software without prior written authorization from the Gnome Foundation
|
||||
or Bitstream Inc., respectively. For further information, contact:
|
||||
fonts at gnome dot org.
|
||||
|
||||
Copyright FAQ
|
||||
=============
|
||||
|
||||
1. I don't understand the resale restriction... What gives?
|
||||
|
||||
Bitstream is giving away these fonts, but wishes to ensure its
|
||||
competitors can't just drop the fonts as is into a font sale system
|
||||
and sell them as is. It seems fair that if Bitstream can't make money
|
||||
from the Bitstream Vera fonts, their competitors should not be able to
|
||||
do so either. You can sell the fonts as part of any software package,
|
||||
however.
|
||||
|
||||
2. I want to package these fonts separately for distribution and
|
||||
sale as part of a larger software package or system. Can I do so?
|
||||
|
||||
Yes. A RPM or Debian package is a "larger software package" to begin
|
||||
with, and you aren't selling them independently by themselves.
|
||||
See 1. above.
|
||||
|
||||
3. Are derivative works allowed?
|
||||
Yes!
|
||||
|
||||
4. Can I change or add to the font(s)?
|
||||
Yes, but you must change the name(s) of the font(s).
|
||||
|
||||
5. Under what terms are derivative works allowed?
|
||||
|
||||
You must change the name(s) of the fonts. This is to ensure the
|
||||
quality of the fonts, both to protect Bitstream and Gnome. We want to
|
||||
ensure that if an application has opened a font specifically of these
|
||||
names, it gets what it expects (though of course, using fontconfig,
|
||||
substitutions could still could have occurred during font
|
||||
opening). You must include the Bitstream copyright. Additional
|
||||
copyrights can be added, as per copyright law. Happy Font Hacking!
|
||||
|
||||
6. If I have improvements for Bitstream Vera, is it possible they might get
|
||||
adopted in future versions?
|
||||
|
||||
Yes. The contract between the Gnome Foundation and Bitstream has
|
||||
provisions for working with Bitstream to ensure quality additions to
|
||||
the Bitstream Vera font family. Please contact us if you have such
|
||||
additions. Note, that in general, we will want such additions for the
|
||||
entire family, not just a single font, and that you'll have to keep
|
||||
both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add
|
||||
glyphs to the font, they must be stylistically in keeping with Vera's
|
||||
design. Vera cannot become a "ransom note" font. Jim Lyles will be
|
||||
providing a document describing the design elements used in Vera, as a
|
||||
guide and aid for people interested in contributing to Vera.
|
||||
|
||||
7. I want to sell a software package that uses these fonts: Can I do so?
|
||||
|
||||
Sure. Bundle the fonts with your software and sell your software
|
||||
with the fonts. That is the intent of the copyright.
|
||||
|
||||
8. If applications have built the names "Bitstream Vera" into them,
|
||||
can I override this somehow to use fonts of my choosing?
|
||||
|
||||
This depends on exact details of the software. Most open source
|
||||
systems and software (e.g., Gnome, KDE, etc.) are now converting to
|
||||
use fontconfig (see www.fontconfig.org) to handle font configuration,
|
||||
selection and substitution; it has provisions for overriding font
|
||||
names and subsituting alternatives. An example is provided by the
|
||||
supplied local.conf file, which chooses the family Bitstream Vera for
|
||||
"sans", "serif" and "monospace". Other software (e.g., the XFree86
|
||||
core server) has other mechanisms for font substitution.
|
@ -0,0 +1,93 @@
|
||||
Copyright (c) 2010, 2011 Georg Duffner (http://www.georgduffner.at)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
Binary file not shown.
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 50 KiB |
@ -0,0 +1,20 @@
|
||||
set(MWINIIMPORT
|
||||
main.cpp
|
||||
importer.cpp
|
||||
)
|
||||
|
||||
set(MWINIIMPORT_HEADER
|
||||
importer.hpp
|
||||
)
|
||||
|
||||
source_group(launcher FILES ${MWINIIMPORT} ${MWINIIMPORT_HEADER})
|
||||
|
||||
add_executable(mwiniimport
|
||||
${MWINIIMPORT}
|
||||
)
|
||||
|
||||
target_link_libraries(mwiniimport
|
||||
${Boost_LIBRARIES}
|
||||
components
|
||||
)
|
||||
|
@ -0,0 +1,216 @@
|
||||
#include "importer.hpp"
|
||||
#include <boost/iostreams/device/file.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
MwIniImporter::MwIniImporter() {
|
||||
const char *map[][2] =
|
||||
{
|
||||
{ "fps", "General:Show FPS" },
|
||||
{ "nosound", "General:Disable Audio" },
|
||||
{ 0, 0 }
|
||||
};
|
||||
const char *fallback[] = {
|
||||
"Weather:Sunrise Time",
|
||||
"Weather:Sunset Time",
|
||||
0
|
||||
};
|
||||
|
||||
for(int i=0; map[i][0]; i++) {
|
||||
mMergeMap.insert(std::make_pair<std::string, std::string>(map[i][0], map[i][1]));
|
||||
}
|
||||
|
||||
for(int i=0; fallback[i]; i++) {
|
||||
mMergeFallback.push_back(fallback[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void MwIniImporter::setVerbose(bool verbose) {
|
||||
mVerbose = verbose;
|
||||
}
|
||||
|
||||
std::string MwIniImporter::numberToString(int n) {
|
||||
std::stringstream str;
|
||||
str << n;
|
||||
return str.str();
|
||||
}
|
||||
|
||||
MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) {
|
||||
std::cout << "load ini file: " << filename << std::endl;
|
||||
|
||||
std::string section("");
|
||||
MwIniImporter::multistrmap map;
|
||||
boost::iostreams::stream<boost::iostreams::file_source>file(filename.c_str());
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
|
||||
if(line[0] == '[') {
|
||||
if(line.length() > 2) {
|
||||
section = line.substr(1, line.length()-3);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int comment_pos = line.find(";");
|
||||
if(comment_pos > 0) {
|
||||
line = line.substr(0,comment_pos);
|
||||
}
|
||||
|
||||
if(line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int pos = line.find("=");
|
||||
if(pos < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string key(section + ":" + line.substr(0,pos));
|
||||
std::string value(line.substr(pos+1));
|
||||
|
||||
multistrmap::iterator it;
|
||||
if((it = map.find(key)) == map.end()) {
|
||||
map.insert( std::make_pair<std::string, std::vector<std::string> > (key, std::vector<std::string>() ) );
|
||||
}
|
||||
map[key].push_back(value);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) {
|
||||
std::cout << "load cfg file: " << filename << std::endl;
|
||||
|
||||
MwIniImporter::multistrmap map;
|
||||
boost::iostreams::stream<boost::iostreams::file_source>file(filename.c_str());
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
|
||||
// we cant say comment by only looking at first char anymore
|
||||
int comment_pos = line.find("#");
|
||||
if(comment_pos > 0) {
|
||||
line = line.substr(0,comment_pos);
|
||||
}
|
||||
|
||||
if(line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int pos = line.find("=");
|
||||
if(pos < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string key(line.substr(0,pos));
|
||||
std::string value(line.substr(pos+1));
|
||||
|
||||
multistrmap::iterator it;
|
||||
if((it = map.find(key)) == map.end()) {
|
||||
map.insert( std::make_pair<std::string, std::vector<std::string> > (key, std::vector<std::string>() ) );
|
||||
}
|
||||
map[key].push_back(value);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) {
|
||||
multistrmap::iterator cfgIt;
|
||||
multistrmap::iterator iniIt;
|
||||
for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) {
|
||||
if((iniIt = ini.find(it->second)) != ini.end()) {
|
||||
for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) {
|
||||
cfg.erase(it->first);
|
||||
insertMultistrmap(cfg, it->first, *vc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) {
|
||||
cfg.erase("fallback");
|
||||
|
||||
multistrmap::iterator cfgIt;
|
||||
multistrmap::iterator iniIt;
|
||||
for(std::vector<std::string>::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); it++) {
|
||||
if((iniIt = ini.find(*it)) != ini.end()) {
|
||||
for(std::vector<std::string>::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) {
|
||||
std::string value(*it);
|
||||
std::replace( value.begin(), value.end(), ' ', '_' );
|
||||
std::replace( value.begin(), value.end(), ':', '_' );
|
||||
value.append(",").append(vc->substr(0,vc->length()-1));
|
||||
insertMultistrmap(cfg, "fallback", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void MwIniImporter::insertMultistrmap(multistrmap &cfg, std::string key, std::string value) {
|
||||
multistrmap::iterator it = cfg.find(key);
|
||||
if(it == cfg.end()) {
|
||||
cfg.insert(std::make_pair<std::string, std::vector<std::string> >(key, std::vector<std::string>() ));
|
||||
}
|
||||
cfg[key].push_back(value);
|
||||
}
|
||||
|
||||
void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) {
|
||||
std::vector<std::string> esmFiles;
|
||||
std::vector<std::string> espFiles;
|
||||
std::string baseGameFile("Game Files:GameFile");
|
||||
std::string gameFile("");
|
||||
|
||||
multistrmap::iterator it = ini.begin();
|
||||
for(int i=0; it != ini.end(); i++) {
|
||||
gameFile = baseGameFile;
|
||||
gameFile.append(this->numberToString(i));
|
||||
|
||||
it = ini.find(gameFile);
|
||||
if(it == ini.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::iterator entry = it->second.begin(); entry!=it->second.end(); entry++) {
|
||||
std::string filetype(entry->substr(entry->length()-4, 3));
|
||||
std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower);
|
||||
|
||||
if(filetype.compare("esm") == 0) {
|
||||
esmFiles.push_back(*entry);
|
||||
}
|
||||
else if(filetype.compare("esp") == 0) {
|
||||
espFiles.push_back(*entry);
|
||||
}
|
||||
}
|
||||
|
||||
gameFile = "";
|
||||
}
|
||||
|
||||
cfg.erase("master");
|
||||
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("master", std::vector<std::string>() ) );
|
||||
|
||||
for(std::vector<std::string>::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) {
|
||||
cfg["master"].push_back(*it);
|
||||
}
|
||||
|
||||
cfg.erase("plugin");
|
||||
cfg.insert( std::make_pair<std::string, std::vector<std::string> > ("plugin", std::vector<std::string>() ) );
|
||||
|
||||
for(std::vector<std::string>::iterator it=espFiles.begin(); it!=espFiles.end(); it++) {
|
||||
cfg["plugin"].push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void MwIniImporter::writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, multistrmap &cfg) {
|
||||
|
||||
for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); it++) {
|
||||
for(std::vector<std::string>::iterator entry=it->second.begin(); entry != it->second.end(); entry++) {
|
||||
out << (it->first) << "=" << (*entry) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#ifndef MWINIIMPORTER_IMPORTER
|
||||
#define MWINIIMPORTER_IMPORTER 1
|
||||
|
||||
#include <boost/iostreams/device/file.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
|
||||
class MwIniImporter {
|
||||
public:
|
||||
typedef std::map<std::string, std::string> strmap;
|
||||
typedef std::map<std::string, std::vector<std::string> > multistrmap;
|
||||
|
||||
MwIniImporter();
|
||||
void setVerbose(bool verbose);
|
||||
multistrmap loadIniFile(std::string filename);
|
||||
multistrmap loadCfgFile(std::string filename);
|
||||
void merge(multistrmap &cfg, multistrmap &ini);
|
||||
void mergeFallback(multistrmap &cfg, multistrmap &ini);
|
||||
void importGameFiles(multistrmap &cfg, multistrmap &ini);
|
||||
void writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, multistrmap &cfg);
|
||||
|
||||
private:
|
||||
void insertMultistrmap(multistrmap &cfg, std::string key, std::string value);
|
||||
std::string numberToString(int n);
|
||||
bool mVerbose;
|
||||
strmap mMergeMap;
|
||||
std::vector<std::string> mMergeFallback;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,75 @@
|
||||
#include "importer.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
bpo::options_description desc("Syntax: mwiniimporter <options> inifile configfile\nAllowed options");
|
||||
bpo::positional_options_description p_desc;
|
||||
desc.add_options()
|
||||
("help,h", "produce help message")
|
||||
("verbose,v", "verbose output")
|
||||
("ini,i", bpo::value<std::string>(), "morrowind.ini file")
|
||||
("cfg,c", bpo::value<std::string>(), "openmw.cfg file")
|
||||
("output,o", bpo::value<std::string>()->default_value(""), "openmw.cfg file")
|
||||
("game-files,g", "import esm and esp files")
|
||||
;
|
||||
p_desc.add("ini", 1).add("cfg", 1);
|
||||
|
||||
bpo::variables_map vm;
|
||||
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv)
|
||||
.options(desc)
|
||||
.positional(p_desc)
|
||||
.run();
|
||||
|
||||
bpo::store(parsed, vm);
|
||||
|
||||
if(vm.count("help") || !vm.count("ini") || !vm.count("cfg")) {
|
||||
std::cout << desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bpo::notify(vm);
|
||||
|
||||
std::string iniFile = vm["ini"].as<std::string>();
|
||||
std::string cfgFile = vm["cfg"].as<std::string>();
|
||||
|
||||
// if no output is given, write back to cfg file
|
||||
std::string outputFile(vm["output"].as<std::string>());
|
||||
if(vm["output"].defaulted()) {
|
||||
outputFile = vm["cfg"].as<std::string>();
|
||||
}
|
||||
|
||||
if(!boost::filesystem::exists(iniFile)) {
|
||||
std::cerr << "ini file does not exist" << std::endl;
|
||||
return -3;
|
||||
}
|
||||
if(!boost::filesystem::exists(cfgFile)) {
|
||||
std::cerr << "cfg file does not exist" << std::endl;
|
||||
return -4;
|
||||
}
|
||||
|
||||
MwIniImporter importer;
|
||||
importer.setVerbose(vm.count("verbose"));
|
||||
|
||||
MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile);
|
||||
MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile);
|
||||
|
||||
importer.merge(cfg, ini);
|
||||
importer.mergeFallback(cfg, ini);
|
||||
|
||||
if(vm.count("game-files")) {
|
||||
importer.importGameFiles(cfg, ini);
|
||||
}
|
||||
|
||||
std::cout << "write to: " << outputFile << std::endl;
|
||||
boost::iostreams::stream<boost::iostreams::file_sink> file(outputFile);
|
||||
importer.writeToFile(file, cfg);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#include "cursorreplace.hpp"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <openengine/ogre/imagerotate.hpp>
|
||||
|
||||
#include <OgreResourceGroupManager.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
CursorReplace::CursorReplace()
|
||||
{
|
||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_vresize.png", 90);
|
||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize1.png", -45);
|
||||
OEngine::Render::ImageRotate::rotate("textures\\tx_cursormove.dds", "mwpointer_dresize2.png", 45);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#ifndef GAME_CURSORREPLACE_H
|
||||
#define GAME_CURSORREPLACE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
/// \brief MyGUI does not support rotating cursors, so we have to do it manually
|
||||
class CursorReplace
|
||||
{
|
||||
public:
|
||||
CursorReplace();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,106 @@
|
||||
#include "map_window.hpp"
|
||||
#include "window_manager.hpp"
|
||||
/*
|
||||
#include "../mwmechanics/mechanicsmanager.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
*/
|
||||
using namespace MWGui;
|
||||
|
||||
MapWindow::MapWindow(WindowManager& parWindowManager) :
|
||||
MWGui::WindowPinnableBase("openmw_map_window_layout.xml", parWindowManager),
|
||||
mGlobal(false)
|
||||
{
|
||||
setCoord(500,0,320,300);
|
||||
setText("WorldButton", "World");
|
||||
setImage("Compass", "textures\\compass.dds");
|
||||
|
||||
// Obviously you should override this later on
|
||||
setCellName("No Cell Loaded");
|
||||
|
||||
getWidget(mLocalMap, "LocalMap");
|
||||
getWidget(mGlobalMap, "GlobalMap");
|
||||
getWidget(mPlayerArrow, "Compass");
|
||||
|
||||
getWidget(mButton, "WorldButton");
|
||||
mButton->eventMouseButtonClick += MyGUI::newDelegate(this, &MapWindow::onWorldButtonClicked);
|
||||
|
||||
MyGUI::Button* eventbox;
|
||||
getWidget(eventbox, "EventBox");
|
||||
eventbox->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
|
||||
eventbox->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
|
||||
|
||||
LocalMapBase::init(mLocalMap, this);
|
||||
}
|
||||
|
||||
void MapWindow::setCellName(const std::string& cellName)
|
||||
{
|
||||
static_cast<MyGUI::Window*>(mMainWidget)->setCaption(cellName);
|
||||
adjustWindowCaption();
|
||||
}
|
||||
|
||||
void MapWindow::setPlayerPos(const float x, const float y)
|
||||
{
|
||||
if (mGlobal || !mVisible || (x == mLastPositionX && y == mLastPositionY)) return;
|
||||
MyGUI::IntSize size = mLocalMap->getCanvasSize();
|
||||
MyGUI::IntPoint middle = MyGUI::IntPoint((1/3.f + x/3.f)*size.width,(1/3.f + y/3.f)*size.height);
|
||||
MyGUI::IntCoord viewsize = mLocalMap->getCoord();
|
||||
MyGUI::IntPoint pos(0.5*viewsize.width - middle.left, 0.5*viewsize.height - middle.top);
|
||||
mLocalMap->setViewOffset(pos);
|
||||
|
||||
mPlayerArrow->setPosition(MyGUI::IntPoint(x*512-16, y*512-16));
|
||||
mLastPositionX = x;
|
||||
mLastPositionY = y;
|
||||
}
|
||||
|
||||
void MapWindow::setPlayerDir(const float x, const float y)
|
||||
{
|
||||
if (!mVisible || (x == mLastDirectionX && y == mLastDirectionY)) return;
|
||||
MyGUI::ISubWidget* main = mPlayerArrow->getSubWidgetMain();
|
||||
MyGUI::RotatingSkin* rotatingSubskin = main->castType<MyGUI::RotatingSkin>();
|
||||
rotatingSubskin->setCenter(MyGUI::IntPoint(16,16));
|
||||
float angle = std::atan2(x,y);
|
||||
rotatingSubskin->setAngle(angle);
|
||||
|
||||
mLastDirectionX = x;
|
||||
mLastDirectionY = y;
|
||||
}
|
||||
|
||||
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||
{
|
||||
if (_id!=MyGUI::MouseButton::Left) return;
|
||||
if (!mGlobal)
|
||||
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
||||
}
|
||||
|
||||
void MapWindow::onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||
{
|
||||
if (_id!=MyGUI::MouseButton::Left) return;
|
||||
|
||||
if (!mGlobal)
|
||||
{
|
||||
MyGUI::IntPoint diff = MyGUI::IntPoint(_left, _top) - mLastDragPos;
|
||||
mLocalMap->setViewOffset( mLocalMap->getViewOffset() + diff );
|
||||
|
||||
mLastDragPos = MyGUI::IntPoint(_left, _top);
|
||||
}
|
||||
}
|
||||
|
||||
void MapWindow::onWorldButtonClicked(MyGUI::Widget* _sender)
|
||||
{
|
||||
mGlobal = !mGlobal;
|
||||
mGlobalMap->setVisible(mGlobal);
|
||||
mLocalMap->setVisible(!mGlobal);
|
||||
|
||||
mButton->setCaption( mGlobal ? "Local" : "World" );
|
||||
}
|
||||
|
||||
void MapWindow::onPinToggled()
|
||||
{
|
||||
mWindowManager.setMinimapVisibility(!mPinned);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#ifndef MWGUI_MAPWINDOW_H
|
||||
#define MWGUI_MAPWINDOW_H
|
||||
|
||||
#include "layouts.hpp"
|
||||
#include "window_pinnable_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase
|
||||
{
|
||||
public:
|
||||
MapWindow(WindowManager& parWindowManager);
|
||||
virtual ~MapWindow(){}
|
||||
|
||||
void setPlayerPos(const float x, const float y);
|
||||
void setPlayerDir(const float x, const float y);
|
||||
void setCellName(const std::string& cellName);
|
||||
|
||||
private:
|
||||
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
void onWorldButtonClicked(MyGUI::Widget* _sender);
|
||||
|
||||
MyGUI::ScrollView* mGlobalMap;
|
||||
MyGUI::ImageBox* mPlayerArrow;
|
||||
MyGUI::Button* mButton;
|
||||
MyGUI::IntPoint mLastDragPos;
|
||||
bool mGlobal;
|
||||
|
||||
protected:
|
||||
virtual void onPinToggled();
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,33 @@
|
||||
#include "window_pinnable_base.hpp"
|
||||
#include "window_manager.hpp"
|
||||
|
||||
using namespace MWGui;
|
||||
|
||||
WindowPinnableBase::WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager)
|
||||
: WindowBase(parLayout, parWindowManager), mPinned(false), mVisible(false)
|
||||
{
|
||||
MyGUI::WindowPtr t = static_cast<MyGUI::WindowPtr>(mMainWidget);
|
||||
t->eventWindowButtonPressed += MyGUI::newDelegate(this, &WindowPinnableBase::onWindowButtonPressed);
|
||||
}
|
||||
|
||||
void WindowPinnableBase::setVisible(bool b)
|
||||
{
|
||||
// Pinned windows can not be hidden
|
||||
if (mPinned && !b)
|
||||
return;
|
||||
|
||||
WindowBase::setVisible(b);
|
||||
mVisible = b;
|
||||
}
|
||||
|
||||
void WindowPinnableBase::onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName)
|
||||
{
|
||||
if ("PinToggle" == eventName)
|
||||
{
|
||||
mPinned = !mPinned;
|
||||
onPinToggled();
|
||||
}
|
||||
|
||||
eventDone(this);
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
#ifndef MWGUI_WINDOW_PINNABLE_BASE_H
|
||||
#define MWGUI_WINDOW_PINNABLE_BASE_H
|
||||
|
||||
#include "window_base.hpp"
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
class WindowManager;
|
||||
|
||||
class WindowPinnableBase: public WindowBase
|
||||
{
|
||||
public:
|
||||
WindowPinnableBase(const std::string& parLayout, WindowManager& parWindowManager);
|
||||
void setVisible(bool b);
|
||||
|
||||
private:
|
||||
void onWindowButtonPressed(MyGUI::Window* sender, const std::string& eventName);
|
||||
|
||||
protected:
|
||||
virtual void onPinToggled() = 0;
|
||||
|
||||
bool mPinned;
|
||||
bool mVisible;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -0,0 +1,77 @@
|
||||
|
||||
#include "actors.hpp"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Actors::updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused)
|
||||
{
|
||||
if (!paused && ptr.getRefData().getHandle()!="player")
|
||||
MWWorld::Class::get (ptr).getInventoryStore (ptr).autoEquip (
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr), mEnvironment);
|
||||
}
|
||||
|
||||
Actors::Actors (MWWorld::Environment& environment) : mEnvironment (environment), mDuration (0) {}
|
||||
|
||||
void Actors::addActor (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
mActors.insert (ptr);
|
||||
}
|
||||
|
||||
void Actors::removeActor (const MWWorld::Ptr& ptr)
|
||||
{
|
||||
mActors.erase (ptr);
|
||||
}
|
||||
|
||||
void Actors::dropActors (const MWWorld::Ptr::CellStore *cellStore)
|
||||
{
|
||||
std::set<MWWorld::Ptr>::iterator iter = mActors.begin();
|
||||
|
||||
while (iter!=mActors.end())
|
||||
if (iter->getCell()==cellStore)
|
||||
{
|
||||
mActors.erase (iter++);
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
|
||||
void Actors::update (std::vector<std::pair<std::string, Ogre::Vector3> >& movement, float duration,
|
||||
bool paused)
|
||||
{
|
||||
mDuration += duration;
|
||||
|
||||
if (mDuration>=0.25)
|
||||
{
|
||||
for (std::set<MWWorld::Ptr>::iterator iter (mActors.begin()); iter!=mActors.end(); ++iter)
|
||||
{
|
||||
updateActor (*iter, mDuration);
|
||||
|
||||
if (iter->getTypeName()==typeid (ESM::NPC).name())
|
||||
updateNpc (*iter, mDuration, paused);
|
||||
}
|
||||
|
||||
mDuration = 0;
|
||||
}
|
||||
|
||||
for (std::set<MWWorld::Ptr>::iterator iter (mActors.begin()); iter!=mActors.end();
|
||||
++iter)
|
||||
{
|
||||
Ogre::Vector3 vector = MWWorld::Class::get (*iter).getMovementVector (*iter);
|
||||
|
||||
if (vector!=Ogre::Vector3::ZERO)
|
||||
movement.push_back (std::make_pair (iter->getRefData().getHandle(), vector));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
#ifndef GAME_MWMECHANICS_ACTORS_H
|
||||
#define GAME_MWMECHANICS_ACTORS_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector3;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class Actors
|
||||
{
|
||||
MWWorld::Environment& mEnvironment;
|
||||
std::set<MWWorld::Ptr> mActors;
|
||||
float mDuration;
|
||||
|
||||
void updateActor (const MWWorld::Ptr& ptr, float duration);
|
||||
|
||||
void updateNpc (const MWWorld::Ptr& ptr, float duration, bool paused);
|
||||
|
||||
public:
|
||||
|
||||
Actors (MWWorld::Environment& environment);
|
||||
|
||||
void addActor (const MWWorld::Ptr& ptr);
|
||||
///< Register an actor for stats management
|
||||
|
||||
void removeActor (const MWWorld::Ptr& ptr);
|
||||
///< Deregister an actor for stats management
|
||||
|
||||
void dropActors (const MWWorld::Ptr::CellStore *cellStore);
|
||||
///< Deregister all actors in the given cell.
|
||||
|
||||
void update (std::vector<std::pair<std::string, Ogre::Vector3> >& movement,
|
||||
float duration, bool paused);
|
||||
///< Update actor stats and store desired velocity vectors in \a movement
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,13 @@
|
||||
#ifndef GAME_MWMECHANICS_DRAWSTATE_H
|
||||
#define GAME_MWMECHANICS_DRAWSTATE_H
|
||||
|
||||
#undef DrawState
|
||||
|
||||
enum DrawState
|
||||
{
|
||||
DrawState_Weapon = 0,
|
||||
DrawState_Spell = 1,
|
||||
DrawState_Nothing = 2,
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,81 @@
|
||||
|
||||
#include "spells.hpp"
|
||||
|
||||
#include <components/esm/loadspel.hpp>
|
||||
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
void Spells::addSpell (const ESM::Spell *spell, MagicEffects& effects) const
|
||||
{
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter = spell->effects.list.begin();
|
||||
iter!=spell->effects.list.end(); ++iter)
|
||||
{
|
||||
EffectParam param;
|
||||
param.mMagnitude = iter->magnMax; /// \todo calculate magnitude
|
||||
effects.add (EffectKey (*iter), param);
|
||||
}
|
||||
}
|
||||
|
||||
Spells::TIterator Spells::begin() const
|
||||
{
|
||||
return mSpells.begin();
|
||||
}
|
||||
|
||||
Spells::TIterator Spells::end() const
|
||||
{
|
||||
return mSpells.end();
|
||||
}
|
||||
|
||||
void Spells::add (const std::string& spellId)
|
||||
{
|
||||
if (std::find (mSpells.begin(), mSpells.end(), spellId)!=mSpells.end())
|
||||
mSpells.push_back (spellId);
|
||||
}
|
||||
|
||||
void Spells::remove (const std::string& spellId)
|
||||
{
|
||||
TContainer::iterator iter = std::find (mSpells.begin(), mSpells.end(), spellId);
|
||||
|
||||
if (iter!=mSpells.end())
|
||||
mSpells.erase (iter);
|
||||
|
||||
if (spellId==mSelectedSpell)
|
||||
mSelectedSpell.clear();
|
||||
}
|
||||
|
||||
MagicEffects Spells::getMagicEffects (const MWWorld::Environment& environment) const
|
||||
{
|
||||
MagicEffects effects;
|
||||
|
||||
for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter)
|
||||
{
|
||||
const ESM::Spell *spell = environment.mWorld->getStore().spells.find (*iter);
|
||||
|
||||
if (spell->data.type==ESM::Spell::ST_Ability || spell->data.type==ESM::Spell::ST_Blight ||
|
||||
spell->data.type==ESM::Spell::ST_Disease || spell->data.type==ESM::Spell::ST_Curse)
|
||||
addSpell (spell, effects);
|
||||
}
|
||||
|
||||
return effects;
|
||||
}
|
||||
|
||||
void Spells::clear()
|
||||
{
|
||||
mSpells.clear();
|
||||
}
|
||||
|
||||
void Spells::setSelectedSpell (const std::string& spellId)
|
||||
{
|
||||
mSelectedSpell = spellId;
|
||||
}
|
||||
|
||||
const std::string Spells::getSelectedSpell() const
|
||||
{
|
||||
return mSelectedSpell;
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
#ifndef GAME_MWMECHANICS_SPELLS_H
|
||||
#define GAME_MWMECHANICS_SPELLS_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Spell;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
struct Environment;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class MagicEffects;
|
||||
|
||||
/// \brief Spell list
|
||||
///
|
||||
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
||||
/// diseaes.
|
||||
class Spells
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::vector<std::string> TContainer;
|
||||
typedef TContainer::const_iterator TIterator;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::string> mSpells;
|
||||
std::string mSelectedSpell;
|
||||
|
||||
void addSpell (const ESM::Spell *, MagicEffects& effects) const;
|
||||
|
||||
public:
|
||||
|
||||
TIterator begin() const;
|
||||
|
||||
TIterator end() const;
|
||||
|
||||
void add (const std::string& spell);
|
||||
///< Adding a spell that is already listed in *this is a no-op.
|
||||
|
||||
void remove (const std::string& spell);
|
||||
///< If the spell to be removed is the selected spell, the selected spell will be changed to
|
||||
/// no spell (empty string).
|
||||
|
||||
MagicEffects getMagicEffects (const MWWorld::Environment& environment) const;
|
||||
///< Return sum of magic effects resulting from abilities, blights, deseases and curses.
|
||||
|
||||
void clear();
|
||||
///< Remove all spells of al types.
|
||||
|
||||
void setSelectedSpell (const std::string& spellId);
|
||||
///< This function does not verify, if the spell is available.
|
||||
|
||||
const std::string getSelectedSpell() const;
|
||||
///< May return an empty string.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,357 @@
|
||||
#include "localmap.hpp"
|
||||
#include "renderingmanager.hpp"
|
||||
|
||||
#include "../mwworld/environment.hpp"
|
||||
#include "../mwworld/world.hpp"
|
||||
#include "../mwgui/window_manager.hpp"
|
||||
#include "renderconst.hpp"
|
||||
|
||||
#include <OgreOverlayManager.h>
|
||||
#include <OgreMaterialManager.h>
|
||||
|
||||
using namespace MWRender;
|
||||
using namespace Ogre;
|
||||
|
||||
LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering, MWWorld::Environment* env) :
|
||||
mInterior(false), mCellX(0), mCellY(0)
|
||||
{
|
||||
mRendering = rend;
|
||||
mRenderingManager = rendering;
|
||||
mEnvironment = env;
|
||||
|
||||
mCameraPosNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode();
|
||||
mCameraRotNode = mCameraPosNode->createChildSceneNode();
|
||||
mCameraNode = mCameraRotNode->createChildSceneNode();
|
||||
|
||||
mCellCamera = mRendering->getScene()->createCamera("CellCamera");
|
||||
mCellCamera->setProjectionType(PT_ORTHOGRAPHIC);
|
||||
// look down -y
|
||||
const float sqrt0pt5 = 0.707106781;
|
||||
mCellCamera->setOrientation(Quaternion(sqrt0pt5, -sqrt0pt5, 0, 0));
|
||||
|
||||
mCameraNode->attachObject(mCellCamera);
|
||||
}
|
||||
|
||||
LocalMap::~LocalMap()
|
||||
{
|
||||
deleteBuffers();
|
||||
}
|
||||
|
||||
const Ogre::Vector2 LocalMap::rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle)
|
||||
{
|
||||
return Vector2( Math::Cos(angle) * (p.x - c.x) - Math::Sin(angle) * (p.y - c.y) + c.x,
|
||||
Math::Sin(angle) * (p.x - c.x) + Math::Cos(angle) * (p.y - c.y) + c.y);
|
||||
}
|
||||
|
||||
void LocalMap::deleteBuffers()
|
||||
{
|
||||
mBuffers.clear();
|
||||
}
|
||||
|
||||
void LocalMap::saveTexture(const std::string& texname, const std::string& filename)
|
||||
{
|
||||
TexturePtr tex = TextureManager::getSingleton().getByName(texname);
|
||||
if (tex.isNull()) return;
|
||||
HardwarePixelBufferSharedPtr readbuffer = tex->getBuffer();
|
||||
readbuffer->lock(HardwareBuffer::HBL_NORMAL );
|
||||
const PixelBox &readrefpb = readbuffer->getCurrentLock();
|
||||
uchar *readrefdata = static_cast<uchar*>(readrefpb.data);
|
||||
|
||||
Image img;
|
||||
img = img.loadDynamicImage (readrefdata, tex->getWidth(),
|
||||
tex->getHeight(), tex->getFormat());
|
||||
img.save("./" + filename);
|
||||
|
||||
readbuffer->unlock();
|
||||
}
|
||||
|
||||
std::string LocalMap::coordStr(const int x, const int y)
|
||||
{
|
||||
return StringConverter::toString(x) + "_" + StringConverter::toString(y);
|
||||
}
|
||||
|
||||
void LocalMap::saveFogOfWar(MWWorld::Ptr::CellStore* cell)
|
||||
{
|
||||
if (!mInterior)
|
||||
{
|
||||
/*saveTexture("Cell_"+coordStr(mCellX, mCellY)+"_fog",
|
||||
"Cell_"+coordStr(mCellX, mCellY)+"_fog.png");*/
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z);
|
||||
Vector2 length = max-min;
|
||||
|
||||
// divide into segments
|
||||
const int segsX = std::ceil( length.x / sSize );
|
||||
const int segsY = std::ceil( length.y / sSize );
|
||||
|
||||
for (int x=0; x<segsX; ++x)
|
||||
{
|
||||
for (int y=0; y<segsY; ++y)
|
||||
{
|
||||
/*saveTexture(
|
||||
mInteriorName + "_" + coordStr(x,y) + "_fog",
|
||||
mInteriorName + "_" + coordStr(x,y) + "_fog.png");*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell)
|
||||
{
|
||||
mInterior = false;
|
||||
|
||||
mCameraRotNode->setOrientation(Quaternion::IDENTITY);
|
||||
|
||||
std::string name = "Cell_"+coordStr(cell->cell->data.gridX, cell->cell->data.gridY);
|
||||
|
||||
int x = cell->cell->data.gridX;
|
||||
int y = cell->cell->data.gridY;
|
||||
|
||||
mCameraPosNode->setPosition(Vector3(0,0,0));
|
||||
|
||||
render((x+0.5)*sSize, (-y-0.5)*sSize, -10000, 10000, sSize, sSize, name);
|
||||
}
|
||||
|
||||
void LocalMap::requestMap(MWWorld::Ptr::CellStore* cell,
|
||||
AxisAlignedBox bounds)
|
||||
{
|
||||
mInterior = true;
|
||||
mBounds = bounds;
|
||||
|
||||
Vector2 z(mBounds.getMaximum().y, mBounds.getMinimum().y);
|
||||
|
||||
const Vector2& north = mEnvironment->mWorld->getNorthVector(cell);
|
||||
Radian angle(std::atan2(-north.x, -north.y));
|
||||
mAngle = angle.valueRadians();
|
||||
mCameraRotNode->setOrientation(Quaternion(Math::Cos(angle/2.f), 0, Math::Sin(angle/2.f), 0));
|
||||
|
||||
// rotate the cell and merge the rotated corners to the bounding box
|
||||
Vector2 _center(bounds.getCenter().x, bounds.getCenter().z);
|
||||
Vector3 _c1 = bounds.getCorner(AxisAlignedBox::NEAR_LEFT_BOTTOM);
|
||||
Vector3 _c2 = bounds.getCorner(AxisAlignedBox::FAR_LEFT_BOTTOM);
|
||||
Vector3 _c3 = bounds.getCorner(AxisAlignedBox::NEAR_RIGHT_BOTTOM);
|
||||
Vector3 _c4 = bounds.getCorner(AxisAlignedBox::FAR_RIGHT_BOTTOM);
|
||||
Vector2 c1(_c1.x, _c1.z);
|
||||
Vector2 c2(_c2.x, _c2.z);
|
||||
Vector2 c3(_c3.x, _c3.z);
|
||||
Vector2 c4(_c4.x, _c4.z);
|
||||
c1 = rotatePoint(c1, _center, mAngle);
|
||||
c2 = rotatePoint(c2, _center, mAngle);
|
||||
c3 = rotatePoint(c3, _center, mAngle);
|
||||
c4 = rotatePoint(c4, _center, mAngle);
|
||||
mBounds.merge(Vector3(c1.x, 0, c1.y));
|
||||
mBounds.merge(Vector3(c2.x, 0, c2.y));
|
||||
mBounds.merge(Vector3(c3.x, 0, c3.y));
|
||||
mBounds.merge(Vector3(c4.x, 0, c4.y));
|
||||
|
||||
Vector2 center(mBounds.getCenter().x, mBounds.getCenter().z);
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||
Vector2 max(mBounds.getMaximum().x, mBounds.getMaximum().z);
|
||||
|
||||
Vector2 length = max-min;
|
||||
|
||||
mCameraPosNode->setPosition(Vector3(center.x, 0, center.y));
|
||||
|
||||
// divide into segments
|
||||
const int segsX = std::ceil( length.x / sSize );
|
||||
const int segsY = std::ceil( length.y / sSize );
|
||||
|
||||
mInteriorName = cell->cell->name;
|
||||
|
||||
for (int x=0; x<segsX; ++x)
|
||||
{
|
||||
for (int y=0; y<segsY; ++y)
|
||||
{
|
||||
Vector2 start = min + Vector2(sSize*x,sSize*y);
|
||||
Vector2 newcenter = start + 4096;
|
||||
|
||||
render(newcenter.x - center.x, newcenter.y - center.y, z.y, z.x, sSize, sSize,
|
||||
cell->cell->name + "_" + coordStr(x,y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalMap::render(const float x, const float y,
|
||||
const float zlow, const float zhigh,
|
||||
const float xw, const float yw, const std::string& texture)
|
||||
{
|
||||
// disable fog
|
||||
// changing FOG_MODE is not a solution when using shaders, thus we have to push linear start/end
|
||||
const float fStart = mRendering->getScene()->getFogStart();
|
||||
const float fEnd = mRendering->getScene()->getFogEnd();
|
||||
const ColourValue& clr = mRendering->getScene()->getFogColour();
|
||||
mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, 1000000, 10000000);
|
||||
|
||||
// make everything visible
|
||||
mRendering->getScene()->setAmbientLight(ColourValue(1,1,1));
|
||||
mRenderingManager->disableLights();
|
||||
|
||||
mCameraNode->setPosition(Vector3(x, zhigh+100000, y));
|
||||
//mCellCamera->setFarClipDistance( (zhigh-zlow) * 1.1 );
|
||||
mCellCamera->setFarClipDistance(0); // infinite
|
||||
|
||||
mCellCamera->setOrthoWindow(xw, yw);
|
||||
|
||||
TexturePtr tex;
|
||||
// try loading from memory
|
||||
tex = TextureManager::getSingleton().getByName(texture);
|
||||
if (tex.isNull())
|
||||
{
|
||||
// try loading from disk
|
||||
//if (boost::filesystem::exists(texture+".jpg"))
|
||||
//{
|
||||
/// \todo
|
||||
//}
|
||||
//else
|
||||
{
|
||||
// render
|
||||
tex = TextureManager::getSingleton().createManual(
|
||||
texture,
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
xw*sMapResolution/sSize, yw*sMapResolution/sSize,
|
||||
0,
|
||||
PF_R8G8B8,
|
||||
TU_RENDERTARGET);
|
||||
|
||||
RenderTarget* rtt = tex->getBuffer()->getRenderTarget();
|
||||
rtt->setAutoUpdated(false);
|
||||
Viewport* vp = rtt->addViewport(mCellCamera);
|
||||
vp->setOverlaysEnabled(false);
|
||||
vp->setShadowsEnabled(false);
|
||||
vp->setBackgroundColour(ColourValue(0, 0, 0));
|
||||
vp->setVisibilityMask(RV_Map);
|
||||
|
||||
// use fallback techniques without shadows and without mrt
|
||||
vp->setMaterialScheme("Fallback");
|
||||
|
||||
rtt->update();
|
||||
|
||||
// create "fog of war" texture
|
||||
TexturePtr tex2 = TextureManager::getSingleton().createManual(
|
||||
texture + "_fog",
|
||||
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
TEX_TYPE_2D,
|
||||
xw*sFogOfWarResolution/sSize, yw*sFogOfWarResolution/sSize,
|
||||
0,
|
||||
PF_A8R8G8B8,
|
||||
TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
|
||||
|
||||
// create a buffer to use for dynamic operations
|
||||
std::vector<uint32> buffer;
|
||||
buffer.resize(sFogOfWarResolution*sFogOfWarResolution);
|
||||
|
||||
// initialize to (0, 0, 0, 1)
|
||||
for (int p=0; p<sFogOfWarResolution*sFogOfWarResolution; ++p)
|
||||
{
|
||||
buffer[p] = (255 << 24);
|
||||
}
|
||||
|
||||
memcpy(tex2->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &buffer[0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||
tex2->getBuffer()->unlock();
|
||||
|
||||
mBuffers[texture] = buffer;
|
||||
|
||||
// save to cache for next time
|
||||
//rtt->writeContentsToFile("./" + texture + ".jpg");
|
||||
}
|
||||
}
|
||||
|
||||
mRenderingManager->enableLights();
|
||||
|
||||
// re-enable fog
|
||||
mRendering->getScene()->setFog(FOG_LINEAR, clr, 0, fStart, fEnd);
|
||||
}
|
||||
|
||||
void LocalMap::updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation)
|
||||
{
|
||||
if (sFogOfWarSkip != 0)
|
||||
{
|
||||
static int count=0;
|
||||
if (++count % sFogOfWarSkip != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// retrieve the x,y grid coordinates the player is in
|
||||
int x,y;
|
||||
Vector3 _pos(position.x, 0, position.z);
|
||||
Vector2 pos(_pos.x, _pos.z);
|
||||
|
||||
if (mInterior)
|
||||
{
|
||||
pos = rotatePoint(pos, Vector2(mBounds.getCenter().x, mBounds.getCenter().z), mAngle);
|
||||
}
|
||||
|
||||
|
||||
Vector3 playerdirection = -mCameraRotNode->convertWorldToLocalOrientation(orientation).zAxis();
|
||||
|
||||
Vector2 min(mBounds.getMinimum().x, mBounds.getMinimum().z);
|
||||
|
||||
if (!mInterior)
|
||||
{
|
||||
x = std::ceil(pos.x / sSize)-1;
|
||||
y = std::ceil(-pos.y / sSize)-1;
|
||||
mCellX = x;
|
||||
mCellY = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = std::ceil((pos.x - min.x)/sSize)-1;
|
||||
y = std::ceil((pos.y - min.y)/sSize)-1;
|
||||
|
||||
mEnvironment->mWindowManager->setInteriorMapTexture(x,y);
|
||||
}
|
||||
|
||||
// convert from world coordinates to texture UV coordinates
|
||||
float u,v;
|
||||
std::string texName;
|
||||
if (!mInterior)
|
||||
{
|
||||
u = std::abs((pos.x - (sSize*x))/sSize);
|
||||
v = 1-std::abs((pos.y + (sSize*y))/sSize);
|
||||
texName = "Cell_"+coordStr(x,y);
|
||||
}
|
||||
else
|
||||
{
|
||||
u = (pos.x - min.x - sSize*x)/sSize;
|
||||
v = (pos.y - min.y - sSize*y)/sSize;
|
||||
|
||||
texName = mInteriorName + "_" + coordStr(x,y);
|
||||
}
|
||||
|
||||
mEnvironment->mWindowManager->setPlayerPos(u, v);
|
||||
mEnvironment->mWindowManager->setPlayerDir(playerdirection.x, -playerdirection.z);
|
||||
|
||||
// explore radius (squared)
|
||||
const float sqrExploreRadius = 0.01 * sFogOfWarResolution*sFogOfWarResolution;
|
||||
|
||||
// get the appropriate fog of war texture
|
||||
TexturePtr tex = TextureManager::getSingleton().getByName(texName+"_fog");
|
||||
if (!tex.isNull())
|
||||
{
|
||||
// get its buffer
|
||||
if (mBuffers.find(texName) == mBuffers.end()) return;
|
||||
int i=0;
|
||||
for (int texV = 0; texV<sFogOfWarResolution; ++texV)
|
||||
{
|
||||
for (int texU = 0; texU<sFogOfWarResolution; ++texU)
|
||||
{
|
||||
float sqrDist = Math::Sqr(texU - u*sFogOfWarResolution) + Math::Sqr(texV - v*sFogOfWarResolution);
|
||||
uint32 clr = mBuffers[texName][i];
|
||||
uint8 alpha = (clr >> 24);
|
||||
alpha = std::min( alpha, (uint8) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
|
||||
mBuffers[texName][i] = (uint32) (alpha << 24);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// copy to the texture
|
||||
memcpy(tex->getBuffer()->lock(HardwareBuffer::HBL_DISCARD), &mBuffers[texName][0], sFogOfWarResolution*sFogOfWarResolution*4);
|
||||
tex->getBuffer()->unlock();
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
#ifndef _GAME_RENDER_LOCALMAP_H
|
||||
#define _GAME_RENDER_LOCALMAP_H
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class RenderingManager;
|
||||
|
||||
///
|
||||
/// \brief Local map rendering
|
||||
///
|
||||
class LocalMap
|
||||
{
|
||||
public:
|
||||
LocalMap(OEngine::Render::OgreRenderer*, MWRender::RenderingManager* rendering, MWWorld::Environment* env);
|
||||
~LocalMap();
|
||||
|
||||
/**
|
||||
* Request the local map for an exterior cell.
|
||||
* @remarks It will either be loaded from a disk cache,
|
||||
* or rendered if it is not already cached.
|
||||
* @param exterior cell
|
||||
*/
|
||||
void requestMap (MWWorld::Ptr::CellStore* cell);
|
||||
|
||||
/**
|
||||
* Request the local map for an interior cell.
|
||||
* @remarks It will either be loaded from a disk cache,
|
||||
* or rendered if it is not already cached.
|
||||
* @param interior cell
|
||||
* @param bounding box of the cell
|
||||
*/
|
||||
void requestMap (MWWorld::Ptr::CellStore* cell,
|
||||
Ogre::AxisAlignedBox bounds);
|
||||
|
||||
/**
|
||||
* Set the position & direction of the player.
|
||||
* @remarks This is used to draw a "fog of war" effect
|
||||
* to hide areas on the map the player has not discovered yet.
|
||||
* @param position (OGRE coordinates)
|
||||
* @param camera orientation (OGRE coordinates)
|
||||
*/
|
||||
void updatePlayer (const Ogre::Vector3& position, const Ogre::Quaternion& orientation);
|
||||
|
||||
/**
|
||||
* Save the fog of war for the current cell to disk.
|
||||
* @remarks This should be called before loading a
|
||||
* new cell, as well as when the game is quit.
|
||||
* @param current cell
|
||||
*/
|
||||
void saveFogOfWar(MWWorld::Ptr::CellStore* cell);
|
||||
|
||||
private:
|
||||
OEngine::Render::OgreRenderer* mRendering;
|
||||
MWRender::RenderingManager* mRenderingManager;
|
||||
MWWorld::Environment* mEnvironment;
|
||||
|
||||
// 1024*1024 pixels for a cell
|
||||
static const int sMapResolution = 1024;
|
||||
|
||||
// the dynamic texture is a bottleneck, so don't set this too high
|
||||
static const int sFogOfWarResolution = 32;
|
||||
|
||||
// frames to skip before rendering fog of war
|
||||
static const int sFogOfWarSkip = 2;
|
||||
|
||||
// size of a map segment (for exteriors, 1 cell)
|
||||
static const int sSize = 8192;
|
||||
|
||||
Ogre::Camera* mCellCamera;
|
||||
Ogre::SceneNode* mCameraNode;
|
||||
Ogre::SceneNode* mCameraPosNode;
|
||||
Ogre::SceneNode* mCameraRotNode;
|
||||
|
||||
float mAngle;
|
||||
const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle);
|
||||
|
||||
void render(const float x, const float y,
|
||||
const float zlow, const float zhigh,
|
||||
const float xw, const float yw,
|
||||
const std::string& texture);
|
||||
|
||||
void saveTexture(const std::string& texname, const std::string& filename);
|
||||
|
||||
std::string coordStr(const int x, const int y);
|
||||
|
||||
// a buffer for the "fog of war" texture of the current cell.
|
||||
// interior cells could be divided into multiple textures,
|
||||
// so we store in a map.
|
||||
std::map <std::string, std::vector<Ogre::uint32> > mBuffers;
|
||||
|
||||
void deleteBuffers();
|
||||
|
||||
bool mInterior;
|
||||
int mCellX, mCellY;
|
||||
Ogre::AxisAlignedBox mBounds;
|
||||
std::string mInteriorName;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue