3
*************************************************************************
5
ArmageTron -- Just another Tron Lightcycle Game in 3D.
6
Copyright (C) 2000 Manuel Moos (manuel@moosnet.de)
8
**************************************************************************
10
This program is free software; you can redistribute it and/or
11
modify it under the terms of the GNU General Public License
12
as published by the Free Software Foundation; either version 2
13
of the License, or (at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
***************************************************************************
29
#include "eRectangle.h"
35
#include "tDirectories.h"
36
#include "gSvgOutput.h"
38
static REAL clamp(REAL c) {
44
std::ostream &operator<<(std::ostream &s, gSvgColor const &c) {
46
return s << '#' << std::hex
47
<< std::setw(2) << (int)(clamp(c.r)*255)
48
<< std::setw(2) << (int)(clamp(c.g)*255)
49
<< std::setw(2) << (int)(clamp(c.b)*255);
52
std::ofstream SvgOutput::svgFile;
53
long SvgOutput::afterRimWallsPos;
54
float SvgOutput::lx, SvgOutput::ly, SvgOutput::hx, SvgOutput::hy;
55
float SvgOutput::w, SvgOutput::h, SvgOutput::cx, SvgOutput::cy;
56
static bool sg_svgTransparentBackground=false;
57
static tSettingItem< bool > sg_svgTransparentBackgroundConf( "SVG_TRANSPARENT_BACKGROUND", sg_svgTransparentBackground);
59
void SvgOutput::WriteSvgHeader() {
60
// Assume the file is already open
61
svgFile << "<?xml version=\"1.0\" standalone=\"no\"?>\n"
62
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
63
"<svg xmlns:xlink='http://www.w3.org/1999/xlink' width=\"100%\" height=\"100%\" version=\"1.1\" viewBox=\""
64
<< lx << " " << -hy << " "
65
<< hx-lx << " " << hy-ly
66
<< "\" xmlns=\"http://www.w3.org/2000/svg\">\n";
67
if ( !sg_svgTransparentBackground ) {
68
svgFile << "<rect x=\"" << lx << "\" y=\"" << -hy << "\" width=\"" << hx-lx << "\" height=\"" << hy-ly
69
<< "\" stroke=\"none\" fill=\"#222\" />\n\n";
72
"\t<polygon id='cycle' stroke='none' points='4,0 0,2 0,-2' />\n"
73
"\t<filter x=\"" << lx << "\" y=\"" << -hy << "\" width=\"" << hx-lx << "\" height=\"" << hy-ly << "\" id='wallsFilter' filterUnits='userSpaceOnUse'>\n"
74
"\t\t<feGaussianBlur in='SourceAlpha' stdDeviation='1' />\n"
75
"\t\t<feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1' />\n"
77
"\t\t\t<feMergeNode />\n"
78
"\t\t\t<feMergeNode in='SourceGraphic' />\n"
84
void SvgOutput::WriteSvgFooter() {
85
// Assume the file is already open
86
svgFile << "\n</svg>\n";
89
void SvgOutput::DrawRimWalls( std::vector<ePolyLine> &list ) {
91
for (int i=0; i < list.size(); ++i)
93
ePolyLine P = list[i];
98
svgFile << P.op << P.pt.x << ',' << -P.pt.y << " ";
102
void SvgOutput::DrawWalls(tList<gNetPlayerWall> &list) {
103
unsigned i, len=list.Len();
104
double currentTime = se_GameTime();
105
bool limitedLength = gCycle::WallsLength() > 0;
106
double wallsStayUpDelay = gCycle::WallsStayUpDelay();
107
for(i=0; i<len; i++) {
108
gNetPlayerWall *wall = list[i];
109
gCycle *cycle = wall->Cycle();
112
if(!cycle->Alive() && wallsStayUpDelay >= 0) {
113
alpha -= 2 * (currentTime - cycle->DeathTime() - wallsStayUpDelay);
114
if(alpha <= 0) continue;
116
double wallsLength = cycle->ThisWallsLength();
117
double cycleDist = cycle->GetDistance();
118
double minDist = limitedLength && cycleDist > wallsLength ? cycleDist - wallsLength : 0;
119
const eCoord &begPos = wall->EndPoint(0), &endPos = wall->EndPoint(1);
120
tArray<gPlayerWallCoord> &coords = wall->Coords();
121
double begDist = wall->BegPos();
122
double lenDist = wall->EndPos() - begDist;
123
unsigned j, numcoords = coords.Len();
124
if(numcoords < 2) continue;
125
bool prevDangerous = coords[0].IsDangerous;
126
double prevDist = coords[0].Pos;
127
if(prevDist < minDist) prevDist = minDist;
128
prevDist = (prevDist - begDist) / lenDist;
129
for(j=1; j<numcoords; j++) {
130
bool curDangerous = coords[j].IsDangerous;
131
double curDist = coords[j].Pos;
132
if(curDist < minDist) curDist = minDist;
133
curDist = (curDist - begDist) / lenDist;
135
eCoord v = endPos - begPos, begin = begPos + v * prevDist, end = begPos + v * curDist;
136
svgFile << "\t<path d='M" << begin.x << ',' << -begin.y
137
<< ' ' << end.x << ',' << -end.y << "' stroke='" << gSvgColor(cycle->color_) << '\'';
139
svgFile << " opacity='" << alpha << '\'';
143
prevDangerous = curDangerous;
149
void SvgOutput::DrawObjects() {
150
tList<eGameObject> const &gameObjects = eGrid::CurrentGrid()->GameObjects();
151
size_t len = gameObjects.Len();
152
for(size_t i = 0; i < len; ++i) {
153
eGameObject *obj = gameObjects(i);
155
obj->DrawSvg(svgFile);
159
extern std::vector<ePolyLine> se_unsplittedRimWalls;
161
static bool sg_cycleWallsGlow = true;
162
static tSettingItem<bool> sg_cycleWallsGlowConf("SVG_CYCLE_WALLS_GLOW", sg_cycleWallsGlow);
164
static eLadderLogWriter sg_svgOutputWriter("SVG_CREATED", true);
166
void SvgOutput::Create() {
167
// open file as a new one
169
if ( !tDirectories::Var().Open(svgFile, "map.svg", std::ios::trunc) ) return;
171
const eRectangle &bounds = eWallRim::GetBounds();
172
lx = round(bounds.GetLow().x) - 5;
173
ly = round(bounds.GetLow().y) - 5;
174
hx = round(bounds.GetHigh().x) + 5;
175
hy = round(bounds.GetHigh().y) + 5;
181
// add header, rim wall
183
svgFile << "<!-- Rim Walls -->\n<path fill = 'none' stroke='#fff' stroke-width='1' stroke-linecap='round'\n\td='";
184
DrawRimWalls(se_unsplittedRimWalls);
185
svgFile << "'/>\n<!-- End of Rim Walls -->\n\n";
186
// keep the current file offset
187
afterRimWallsPos = svgFile.tellp();
188
// add player walls and other game objects
189
if(sg_cycleWallsGlow) {
190
svgFile << "<g filter='url(#wallsFilter)'>\n";
192
svgFile << "<!-- Cycle's Walls -->\n<g stroke-width='1' stroke-linecap='round'";
194
DrawWalls(sg_netPlayerWallsGridded);
195
DrawWalls(sg_netPlayerWalls);
196
svgFile << "\n</g>\n<!-- Game objects -->\n";
198
if(sg_cycleWallsGlow) {
201
// add the footer and close the filepp
204
sg_svgOutputWriter.write();
205
//con << "Svg file created\n";
208
SvgOutput::SvgOutput() {
211
SvgOutput::~SvgOutput() {