Add a --drawalpha mode that keeps water (etc.) transparent to great depths
This new mode averages the colors of all transparent blocks, instead of making the colors progressively darker and more opaque. This 'average' mode is now the default when using --drawalpha. It can be explicitly selected using --drawalpha=average. The old modes can be selected using --drawalpha=cumulative[-darken]. It is recommended to change the colors of water as well. These are in a separate patch.
This commit is contained in:
parent
e27d181d9f
commit
b99111e038
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
PixelAttribute::AlphaMixingMode PixelAttribute::m_mixMode = PixelAttribute::AlphaMixCumulative;
|
||||||
|
|
||||||
PixelAttributes::PixelAttributes():
|
PixelAttributes::PixelAttributes():
|
||||||
m_pixelAttributes(0)
|
m_pixelAttributes(0)
|
||||||
{
|
{
|
||||||
@ -113,7 +115,11 @@ void PixelAttributes::renderShading(bool drawAlpha)
|
|||||||
x += 15;
|
x += 15;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!m_pixelAttributes[y][x].isNormalized())
|
||||||
|
m_pixelAttributes[y][x].normalize();
|
||||||
if (!m_pixelAttributes[y][x].is_valid() || !m_pixelAttributes[y - 1][x].is_valid()) {
|
if (!m_pixelAttributes[y][x].is_valid() || !m_pixelAttributes[y - 1][x].is_valid()) {
|
||||||
|
if (x + 1 < m_width && !m_pixelAttributes[y][x + 1].isNormalized())
|
||||||
|
m_pixelAttributes[y][x + 1].normalize();
|
||||||
x++;
|
x++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -142,7 +148,90 @@ void PixelAttributes::renderShading(bool drawAlpha)
|
|||||||
m_firstUnshadedY = y - yCoord2Line(0);
|
m_firstUnshadedY = y - yCoord2Line(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PixelAttribute::mixUnder(const PixelAttribute &p, bool darkenHighAlpha)
|
// Meaning and usage of parameter 'n'.
|
||||||
|
//
|
||||||
|
// When n==0, all other values should be interpreted as
|
||||||
|
// plain color / height / etc.
|
||||||
|
//
|
||||||
|
// When n is positive, some kind of pixel average is being
|
||||||
|
// computed, and the other values represent a sum, with
|
||||||
|
// n being the number of items summed.
|
||||||
|
//
|
||||||
|
// There is a twist when summing colors: Transparent colors
|
||||||
|
// should not contribute the same amount to the final average
|
||||||
|
// color as opaque colors do.
|
||||||
|
// For that reason, the color values (r, g, b) are not simply
|
||||||
|
// summed, but they are multiplied by their alpha values
|
||||||
|
// first.
|
||||||
|
//
|
||||||
|
// Conversion from pixelattributes with n>0 to pixelattributes
|
||||||
|
// with n==0 is performed as follows:
|
||||||
|
// <color-value> = <sum-of-weighed-color-values> / <sum-of-alpha-values>
|
||||||
|
// <alpha-value> = <sum-of-alpha-values> / n
|
||||||
|
// <height> = <sum-of-heights> / n
|
||||||
|
// <thick> = <sum-of-thick-values> / n
|
||||||
|
// n = 0
|
||||||
|
// The converse is (n would normally be set to 1):
|
||||||
|
// <weighed-color-value> = <color-value> * <alpha-value>
|
||||||
|
// n = 1
|
||||||
|
// Color values with n>0 can be summed.
|
||||||
|
|
||||||
|
// normalize() converts from n>0 to n==0 representation
|
||||||
|
void PixelAttribute::normalize(double count, Color defColor)
|
||||||
|
{
|
||||||
|
if (!m_n) {
|
||||||
|
// Already normalized
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_n < count) {
|
||||||
|
m_r += (defColor.r / 255.0) * (defColor.a / 255.0) * (count - m_n);
|
||||||
|
m_g += (defColor.g / 255.0) * (defColor.a / 255.0) * (count - m_n);
|
||||||
|
m_b += (defColor.b / 255.0) * (defColor.a / 255.0) * (count - m_n);
|
||||||
|
m_a += (defColor.a / 255.0) * (count - m_n);
|
||||||
|
m_h *= double(count) / m_n;
|
||||||
|
m_t *= double(count) / m_n;
|
||||||
|
m_n = count;
|
||||||
|
}
|
||||||
|
if (m_n != 1) {
|
||||||
|
m_r /= m_a;
|
||||||
|
m_g /= m_a;
|
||||||
|
m_b /= m_a;
|
||||||
|
m_a /= m_n;
|
||||||
|
m_t /= m_n;
|
||||||
|
m_h /= m_n;
|
||||||
|
}
|
||||||
|
m_n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixelAttribute::add(const PixelAttribute &p)
|
||||||
|
{
|
||||||
|
if (!m_n) {
|
||||||
|
m_r *= m_a;
|
||||||
|
m_g *= m_a;
|
||||||
|
m_b *= m_a;
|
||||||
|
m_n = 1;
|
||||||
|
}
|
||||||
|
if (!p.m_n) {
|
||||||
|
m_r += p.m_r * p.m_a;
|
||||||
|
m_g += p.m_g * p.m_a;
|
||||||
|
m_b += p.m_b * p.m_a;
|
||||||
|
m_a += p.m_a;
|
||||||
|
m_t += p.m_t;
|
||||||
|
m_h += p.m_h;
|
||||||
|
m_n++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_r += p.m_r;
|
||||||
|
m_g += p.m_g;
|
||||||
|
m_b += p.m_b;
|
||||||
|
m_a += p.m_a;
|
||||||
|
m_t += p.m_t;
|
||||||
|
m_h += p.m_h;
|
||||||
|
m_n += p.m_n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixelAttribute::mixUnder(const PixelAttribute &p)
|
||||||
{
|
{
|
||||||
if (!is_valid() || m_a == 0) {
|
if (!is_valid() || m_a == 0) {
|
||||||
if (!is_valid() || p.m_a != 0) {
|
if (!is_valid() || p.m_a != 0) {
|
||||||
@ -155,26 +244,57 @@ void PixelAttribute::mixUnder(const PixelAttribute &p, bool darkenHighAlpha)
|
|||||||
}
|
}
|
||||||
m_h = p.m_h;
|
m_h = p.m_h;
|
||||||
}
|
}
|
||||||
else {
|
else if ((m_mixMode & AlphaMixCumulative) == AlphaMixCumulative || (m_mixMode == AlphaMixAverage && p.m_a == 1)) {
|
||||||
|
PixelAttribute pp(p);
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(pp.isNormalized());
|
||||||
|
#else
|
||||||
|
if (!pp.isNormalized())
|
||||||
|
pp.normalize();
|
||||||
|
#endif
|
||||||
|
if (!isNormalized())
|
||||||
|
normalize();
|
||||||
int prev_alpha = alpha();
|
int prev_alpha = alpha();
|
||||||
m_r = (m_a * m_r + p.m_a * (1 - m_a) * p.m_r);
|
m_r = (m_a * m_r + pp.m_a * (1 - m_a) * pp.m_r);
|
||||||
m_g = (m_a * m_g + p.m_a * (1 - m_a) * p.m_g);
|
m_g = (m_a * m_g + pp.m_a * (1 - m_a) * pp.m_g);
|
||||||
m_b = (m_a * m_b + p.m_a * (1 - m_a) * p.m_b);
|
m_b = (m_a * m_b + pp.m_a * (1 - m_a) * pp.m_b);
|
||||||
m_a = (m_a + (1 - m_a) * p.m_a);
|
m_a = (m_a + (1 - m_a) * pp.m_a);
|
||||||
if (p.m_a != 1)
|
if (pp.m_a != 1)
|
||||||
m_t = (m_t + p.m_t) / 2;
|
m_t = (m_t + pp.m_t) / 2;
|
||||||
m_h = p.m_h;
|
m_h = pp.m_h;
|
||||||
if (prev_alpha >= 254 && p.alpha() < 255 && darkenHighAlpha) {
|
if ((m_mixMode & AlphaMixDarkenBit) && prev_alpha >= 254 && pp.alpha() < 255) {
|
||||||
// Darken
|
// Darken
|
||||||
// Parameters make deep water look good :-)
|
// Parameters make deep water look good :-)
|
||||||
// (maybe this setting should be per-node-type, and obtained from the colors file ?)
|
// (maybe this setting should be per-node-type, and obtained from the colors file ?)
|
||||||
m_r = m_r * 0.95;
|
m_r = m_r * 0.95;
|
||||||
m_g = m_g * 0.95;
|
m_g = m_g * 0.95;
|
||||||
m_b = m_b * 0.95;
|
m_b = m_b * 0.95;
|
||||||
if (p.m_a != 1)
|
if (pp.m_a != 1)
|
||||||
m_t = (m_t + p.m_t) / 2;
|
m_t = (m_t + pp.m_t) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else if (m_mixMode == AlphaMixAverage && p.m_a != 1) {
|
||||||
|
#else
|
||||||
|
else {
|
||||||
|
#endif
|
||||||
|
if (p.m_a == 1)
|
||||||
|
normalize();
|
||||||
|
double h = p.m_h;
|
||||||
|
double t = m_t;
|
||||||
|
add(p);
|
||||||
|
if (p.m_a == 1) {
|
||||||
|
normalize();
|
||||||
|
m_t = t;
|
||||||
|
m_a = 1;
|
||||||
|
}
|
||||||
|
m_h = m_n * h;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else {
|
||||||
|
// Internal error
|
||||||
|
assert(1 && m_mixMode);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,15 @@
|
|||||||
|
|
||||||
class PixelAttribute {
|
class PixelAttribute {
|
||||||
public:
|
public:
|
||||||
|
enum AlphaMixingMode {
|
||||||
|
AlphaMixDarkenBit = 0x01,
|
||||||
|
AlphaMixCumulative = 0x02,
|
||||||
|
AlphaMixCumulativeDarken = 0x03,
|
||||||
|
AlphaMixAverage = 0x04,
|
||||||
|
};
|
||||||
|
static void setMixMode(AlphaMixingMode mode);
|
||||||
PixelAttribute(): next16Empty(true), m_n(0), m_h(NAN), m_t(0), m_a(0), m_r(0), m_g(0), m_b(0) {};
|
PixelAttribute(): next16Empty(true), m_n(0), m_h(NAN), m_t(0), m_a(0), m_r(0), m_g(0), m_b(0) {};
|
||||||
|
// PixelAttribute(const PixelAttribute &p);
|
||||||
PixelAttribute(const Color &color, double height);
|
PixelAttribute(const Color &color, double height);
|
||||||
PixelAttribute(const ColorEntry &entry, double height);
|
PixelAttribute(const ColorEntry &entry, double height);
|
||||||
bool next16Empty;
|
bool next16Empty;
|
||||||
@ -36,12 +44,16 @@ public:
|
|||||||
uint8_t alpha(void) const { return int(a() * 255 + 0.5); }
|
uint8_t alpha(void) const { return int(a() * 255 + 0.5); }
|
||||||
uint8_t thicken(void) const { return int(t() * 255 + 0.5); }
|
uint8_t thicken(void) const { return int(t() * 255 + 0.5); }
|
||||||
unsigned height(void) const { return unsigned(h() + 0.5); }
|
unsigned height(void) const { return unsigned(h() + 0.5); }
|
||||||
|
bool isNormalized(void) const { return !m_n; }
|
||||||
Color color(void) const { return Color(red(), green(), blue(), alpha()); }
|
Color color(void) const { return Color(red(), green(), blue(), alpha()); }
|
||||||
|
|
||||||
inline bool is_valid() const { return !isnan(m_h); }
|
inline bool is_valid() const { return !isnan(m_h); }
|
||||||
PixelAttribute &operator=(const PixelAttribute &p);
|
PixelAttribute &operator=(const PixelAttribute &p);
|
||||||
void mixUnder(const PixelAttribute &p, bool darkenHighAlpha);
|
void normalize(double count = 0, Color defaultColor = Color(127, 127, 127));
|
||||||
|
void add(const PixelAttribute &p);
|
||||||
|
void mixUnder(const PixelAttribute &p);
|
||||||
private:
|
private:
|
||||||
|
static AlphaMixingMode m_mixMode;
|
||||||
double m_n;
|
double m_n;
|
||||||
double m_h;
|
double m_h;
|
||||||
double m_t;
|
double m_t;
|
||||||
@ -94,6 +106,13 @@ inline void PixelAttributes::setLastY(int y)
|
|||||||
m_lastY = y;
|
m_lastY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void PixelAttribute::setMixMode(AlphaMixingMode mode)
|
||||||
|
{
|
||||||
|
if (mode == AlphaMixDarkenBit)
|
||||||
|
mode = AlphaMixCumulativeDarken;
|
||||||
|
m_mixMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
inline PixelAttribute &PixelAttributes::attribute(int y, int x)
|
inline PixelAttribute &PixelAttributes::attribute(int y, int x)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -106,6 +125,11 @@ inline PixelAttribute &PixelAttributes::attribute(int y, int x)
|
|||||||
return m_pixelAttributes[yCoord2Line(y)][x + 1];
|
return m_pixelAttributes[yCoord2Line(y)][x + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//inline PixelAttribute::PixelAttribute(const PixelAttribute &p) :
|
||||||
|
//{
|
||||||
|
// operator=(p);
|
||||||
|
//}
|
||||||
|
|
||||||
inline PixelAttribute::PixelAttribute(const Color &color, double height) :
|
inline PixelAttribute::PixelAttribute(const Color &color, double height) :
|
||||||
next16Empty(false), m_n(0), m_h(height), m_t(0), m_a(color.a/255.0),
|
next16Empty(false), m_n(0), m_h(height), m_t(0), m_a(color.a/255.0),
|
||||||
m_r(color.r/255.0), m_g(color.g/255.0), m_b(color.b/255.0)
|
m_r(color.r/255.0), m_g(color.g/255.0), m_b(color.b/255.0)
|
||||||
|
44
README.rst
44
README.rst
@ -176,22 +176,42 @@ drawplayers:
|
|||||||
draworigin:
|
draworigin:
|
||||||
Draw origin indicator, `--draworigin`
|
Draw origin indicator, `--draworigin`
|
||||||
|
|
||||||
drawalpha[=darken|nodarken]:
|
drawalpha[=cumulative|cumulative-darken|average|none]:
|
||||||
Allow blocks to be drawn with transparency, `--drawalpha=darken`
|
Allow blocks to be drawn with transparency, `--drawalpha=average`
|
||||||
|
|
||||||
Even with drawalpha, transparency decreases with depth. After a certain
|
In cumulative mode, transparency decreases with depth, and darkness of
|
||||||
number of transparent blocks (e.g. water depth), the color will become opaque,
|
the color increases. After a certain number of transparent blocks
|
||||||
and the underlying colors will no longer shine through. The height differences
|
(e.g. water depth), the color will become opaque, and the underlying
|
||||||
*will* still be visible though.
|
colors will no longer shine through. The height differences *will*
|
||||||
|
still be visible though.
|
||||||
|
|
||||||
With 'darken', after the color becomes opaque, it will gradually be darkened
|
In cumulative-darken mode, after the color becomes opaque, it will gradually
|
||||||
to visually simulate the bigger thickness of transparent blocks. The downside
|
be darkened to visually simulate the bigger thickness of transparent blocks.
|
||||||
is that eventually, the color becomes black.
|
The downside is that eventually, the color becomes black.
|
||||||
|
|
||||||
Darken mode makes deeper, but not too deep water look much better. Very deep water
|
Cumulative-darken mode makes deeper, but not too deep water look much better.
|
||||||
will become black though.
|
Very deep water will become black though.
|
||||||
|
|
||||||
With nodarken (default), after it becomes opaque, the color will not be darkened.
|
In average mode, all transparent colors are averaged. The blocks remain transparent
|
||||||
|
infinitely. If no parameter is given to --drawalpha, 'average' is the default.
|
||||||
|
|
||||||
|
'None' disables alpha drawing. This is the same as not using --drawalpha at all.
|
||||||
|
|
||||||
|
For backward compatibility, 'nodarken' is still recognised as alias for 'cumulative';
|
||||||
|
'darken' is still recognised as alias for 'cumulative-darken'. Please don't use
|
||||||
|
them, they may disappear in the future.
|
||||||
|
|
||||||
|
Note that each of the different modes has a different color definition
|
||||||
|
for transparent blocks that looks best. For instance, for water, the following
|
||||||
|
are suggested:
|
||||||
|
|
||||||
|
(disabled): 39 66 106 [192 224 - optional: alpha configuration will be ignored]
|
||||||
|
|
||||||
|
cumulative: 78 132 255 64 224
|
||||||
|
|
||||||
|
cumulative-darken: 78 132 255 64 224
|
||||||
|
|
||||||
|
average: 49 82 132 192 224 (look also good with alpha disabled)
|
||||||
|
|
||||||
drawair:
|
drawair:
|
||||||
Draw air blocks. `--drawair`
|
Draw air blocks. `--drawair`
|
||||||
|
@ -134,7 +134,6 @@ TileGenerator::TileGenerator():
|
|||||||
m_drawPlayers(false),
|
m_drawPlayers(false),
|
||||||
m_drawScale(false),
|
m_drawScale(false),
|
||||||
m_drawAlpha(false),
|
m_drawAlpha(false),
|
||||||
m_darkenHighAlpha(false),
|
|
||||||
m_drawAir(false),
|
m_drawAir(false),
|
||||||
m_shading(true),
|
m_shading(true),
|
||||||
m_border(0),
|
m_border(0),
|
||||||
@ -268,10 +267,9 @@ void TileGenerator::setDrawScale(bool drawScale)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileGenerator::setDrawAlpha(bool drawAlpha, bool darkenHighAlpha)
|
void TileGenerator::setDrawAlpha(bool drawAlpha)
|
||||||
{
|
{
|
||||||
m_drawAlpha = drawAlpha;
|
m_drawAlpha = drawAlpha;
|
||||||
m_darkenHighAlpha = darkenHighAlpha;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileGenerator::setDrawAir(bool drawAir)
|
void TileGenerator::setDrawAir(bool drawAir)
|
||||||
@ -1237,7 +1235,7 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
|
|||||||
rowIsEmpty = false;
|
rowIsEmpty = false;
|
||||||
#define nodeColor (*m_nodeIDColor[content])
|
#define nodeColor (*m_nodeIDColor[content])
|
||||||
//const ColorEntry &nodeColor = *m_nodeIDColor[content];
|
//const ColorEntry &nodeColor = *m_nodeIDColor[content];
|
||||||
pixel.mixUnder(PixelAttribute(nodeColor, pos.y * 16 + y), m_darkenHighAlpha);
|
pixel.mixUnder(PixelAttribute(nodeColor, pos.y * 16 + y));
|
||||||
if ((m_drawAlpha && nodeColor.a == 0xff) || (!m_drawAlpha && nodeColor.a != 0)) {
|
if ((m_drawAlpha && nodeColor.a == 0xff) || (!m_drawAlpha && nodeColor.a != 0)) {
|
||||||
m_readedPixels[z] |= (1 << x);
|
m_readedPixels[z] |= (1 << x);
|
||||||
break;
|
break;
|
||||||
|
@ -91,7 +91,7 @@ public:
|
|||||||
void setDrawOrigin(bool drawOrigin);
|
void setDrawOrigin(bool drawOrigin);
|
||||||
void setDrawPlayers(bool drawPlayers);
|
void setDrawPlayers(bool drawPlayers);
|
||||||
void setDrawScale(bool drawScale);
|
void setDrawScale(bool drawScale);
|
||||||
void setDrawAlpha(bool drawAlpha, bool darkenHighAlpha = false);
|
void setDrawAlpha(bool drawAlpha);
|
||||||
void setDrawAir(bool drawAir);
|
void setDrawAir(bool drawAir);
|
||||||
void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); }
|
void drawObject(const DrawObject &object) { m_drawObjects.push_back(object); }
|
||||||
void setShading(bool shading);
|
void setShading(bool shading);
|
||||||
@ -169,7 +169,6 @@ private:
|
|||||||
bool m_drawPlayers;
|
bool m_drawPlayers;
|
||||||
bool m_drawScale;
|
bool m_drawScale;
|
||||||
bool m_drawAlpha;
|
bool m_drawAlpha;
|
||||||
bool m_darkenHighAlpha;
|
|
||||||
bool m_drawAir;
|
bool m_drawAir;
|
||||||
bool m_shading;
|
bool m_shading;
|
||||||
int m_border;
|
int m_border;
|
||||||
|
22
mapper.cpp
22
mapper.cpp
@ -19,6 +19,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include "TileGenerator.h"
|
#include "TileGenerator.h"
|
||||||
|
#include "PixelAttributes.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ void usage()
|
|||||||
" --drawscale\n"
|
" --drawscale\n"
|
||||||
" --drawplayers\n"
|
" --drawplayers\n"
|
||||||
" --draworigin\n"
|
" --draworigin\n"
|
||||||
" --drawalpha[=[no]darken]\n"
|
" --drawalpha[=cumulative|cumulative-darken|average|none]\n"
|
||||||
" --drawair\n"
|
" --drawair\n"
|
||||||
" --draw[map]point \"<x>,<y> color\"\n"
|
" --draw[map]point \"<x>,<y> color\"\n"
|
||||||
" --draw[map]line \"<geometry> color\"\n"
|
" --draw[map]line \"<geometry> color\"\n"
|
||||||
@ -648,12 +649,19 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
if (optarg && string(optarg) == "darken")
|
generator.setDrawAlpha(true);
|
||||||
generator.setDrawAlpha(true, true);
|
if (!optarg || !*optarg)
|
||||||
else if (optarg && string(optarg) == "nodarken")
|
PixelAttribute::setMixMode(PixelAttribute::AlphaMixAverage);
|
||||||
generator.setDrawAlpha(true, false);
|
else if (string(optarg) == "cumulative" || string(optarg) == "nodarken")
|
||||||
else if (!optarg)
|
// "nodarken" is supported for backwards compatibility
|
||||||
generator.setDrawAlpha(true);
|
PixelAttribute::setMixMode(PixelAttribute::AlphaMixCumulative);
|
||||||
|
else if (string(optarg) == "darken" || string(optarg) == "cumulative-darken")
|
||||||
|
// "darken" is supported for backwards compatibility
|
||||||
|
PixelAttribute::setMixMode(PixelAttribute::AlphaMixCumulativeDarken);
|
||||||
|
else if (string(optarg) == "average")
|
||||||
|
PixelAttribute::setMixMode(PixelAttribute::AlphaMixAverage);
|
||||||
|
else if (string(optarg) == "none")
|
||||||
|
generator.setDrawAlpha(false);
|
||||||
else {
|
else {
|
||||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
||||||
usage();
|
usage();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user