From 61f5ceabde9e78067ef1687d1ce13087df091430 Mon Sep 17 00:00:00 2001 From: George ElKoura Date: Tue, 2 Apr 2019 18:29:00 -0700 Subject: [PATCH] Factored viewer args parsing for into common place Started refactoring how we parse arguments for sample viewer applications into a common place. This will make it easier to keep args consistent between applications. --- examples/common/CMakeLists.txt | 5 ++ examples/common/argOptions.cpp | 97 +++++++++++++++++++++ examples/common/argOptions.h | 95 ++++++++++++++++++++ examples/common/shapeDesc.h | 44 ++++++++++ examples/common/viewerArgsUtils.cpp | 115 +++++++++++++++++++++++++ examples/common/viewerArgsUtils.h | 61 +++++++++++++ examples/glFVarViewer/glFVarViewer.cpp | 56 +++--------- examples/glFVarViewer/init_shapes.h | 11 +-- examples/glViewer/glViewer.cpp | 76 +++++----------- examples/glViewer/init_shapes.h | 12 +-- 10 files changed, 453 insertions(+), 119 deletions(-) create mode 100644 examples/common/argOptions.cpp create mode 100644 examples/common/argOptions.h create mode 100644 examples/common/shapeDesc.h create mode 100644 examples/common/viewerArgsUtils.cpp create mode 100644 examples/common/viewerArgsUtils.h diff --git a/examples/common/CMakeLists.txt b/examples/common/CMakeLists.txt index 7bbb6ce1..50d6618d 100644 --- a/examples/common/CMakeLists.txt +++ b/examples/common/CMakeLists.txt @@ -29,23 +29,28 @@ set(EXAMPLES_COMMON_SHADER_FILES ) set(EXAMPLES_COMMON_SOURCE_FILES + argOptions.cpp font_image.cpp hdr_reader.cpp hud.cpp objAnim.cpp patchColors.cpp + viewerArgsUtils.cpp ) set(EXAMPLES_COMMON_HEADER_FILES + argOptions.h font_image.h hdr_reader.h hud.h objAnim.h patchColors.h shaderCache.h + shapeDesc.h simple_math.h stb_image_write.h stopwatch.h + viewerArgsUtils.h ) if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND)) diff --git a/examples/common/argOptions.cpp b/examples/common/argOptions.cpp new file mode 100644 index 00000000..b7a5fd4a --- /dev/null +++ b/examples/common/argOptions.cpp @@ -0,0 +1,97 @@ +// +// Copyright 2019 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "../common/argOptions.h" + +static int +parseIntArg(const char* argString, int dfltValue = 0) { + char *argEndptr; + int argValue = strtol(argString, &argEndptr, 10); + if (*argEndptr != 0) { + printf("Warning: non-integer option parameter '%s' ignored\n", + argString); + argValue = dfltValue; + } + return argValue; +} + + +ArgOptions::ArgOptions() + : _adaptive(false) + , _fullscreen(false) + , _level(2) + , _objsAreAnim(false) + , _axis(true) + , _repeatCount(0) + , _defaultScheme(kCatmark) +{ +} + +void +ArgOptions::Parse(int argc, char **argv) +{ + for (int i = 1; i < argc; ++i) { + + if (strstr(argv[i], ".obj")) { + _objFiles.push_back(argv[i]); + } else if (!strcmp(argv[i], "-a")) { + _adaptive = true; + } else if (!strcmp(argv[i], "-u")) { + _adaptive = false; + } else if (!strcmp(argv[i], "-l")) { + if (++i < argc) _level = parseIntArg(argv[i], 2); + } else if (!strcmp(argv[i], "-c")) { + if (++i < argc) _repeatCount = parseIntArg(argv[i], 0); + } else if (!strcmp(argv[i], "-f")) { + _fullscreen = true; + } else if (!strcmp(argv[i], "-axis")) { + _axis = false; + } else if (!strcmp(argv[i], "-anim")) { + _objsAreAnim = true; + } else if (!strcmp(argv[i], "-bilinear")) { + _defaultScheme = kBilinear; + } else if (!strcmp(argv[i], "-catmark")) { + _defaultScheme = kCatmark; + } else if (!strcmp(argv[i], "-loop")) { + _defaultScheme = kLoop; + } else { + _remainingArgs.push_back(argv[i]); + } + + } +} + +void +ArgOptions::PrintUnrecognizedArgWarning(const char *arg) const +{ + printf("Warning: unrecognized argument '%s' ignored\n", arg); +} + +void +ArgOptions::PrintUnrecognizedArgsWarnings() const +{ + for(size_t i = 0; i < _remainingArgs.size(); ++i) { + PrintUnrecognizedArgWarning(_remainingArgs[i]); + } +} diff --git a/examples/common/argOptions.h b/examples/common/argOptions.h new file mode 100644 index 00000000..daac98f1 --- /dev/null +++ b/examples/common/argOptions.h @@ -0,0 +1,95 @@ +// +// Copyright 2019 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef COMMON_ARGS_H +#define COMMON_ARGS_H + +#include "../../regression/common/shape_utils.h" + +#include + +class ArgOptions +{ +public: + + ArgOptions(); + + // Uses argc and argv to initialize the members of this object. + void Parse(int argc, char **argv); + + // Prints out unrecognized argument warnings for each argument left in + // remainingArgs + void PrintUnrecognizedArgsWarnings() const; + + // Print unrecognized warning for arg + void PrintUnrecognizedArgWarning(const char *arg) const; + + + // Accessors to parsed arguments + // + + bool GetAdaptive() const { return _adaptive; } + + bool GetFullScreen() const { return _fullscreen; } + + int GetLevel() const { return _level; } + + bool GetObjsAreAnim() const { return _objsAreAnim; } + + bool GetAxis() const { return _axis; } + + int GetRepeatCount() const { return _repeatCount; } + + Scheme GetDefaultScheme() const { return _defaultScheme; } + + const std::vector GetObjFiles() const { return _objFiles; } + + const std::vector GetRemainingArgs() const { + return _remainingArgs; } + +private: + + bool _adaptive; + + bool _fullscreen; + + int _level; + + bool _objsAreAnim; + + bool _axis; + + int _repeatCount; + + Scheme _defaultScheme; + + // .obj files that we've parsed + std::vector _objFiles; + + // Remaining args that we have not parsed, in order that they've appeared + std::vector _remainingArgs; + +}; + +#endif // COMMON_ARGS_H diff --git a/examples/common/shapeDesc.h b/examples/common/shapeDesc.h new file mode 100644 index 00000000..e8af0c2c --- /dev/null +++ b/examples/common/shapeDesc.h @@ -0,0 +1,44 @@ +// +// Copyright 2019 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef SHAPE_DESC_H +#define SHAPE_DESC_H + + +#include + +struct ShapeDesc +{ + ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme, + bool iIsLeftHanded = false) : + name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) + { } + + std::string name; + std::string data; + Scheme scheme; + bool isLeftHanded; +}; + +#endif // SHAPE_DESC_H diff --git a/examples/common/viewerArgsUtils.cpp b/examples/common/viewerArgsUtils.cpp new file mode 100644 index 00000000..97099de8 --- /dev/null +++ b/examples/common/viewerArgsUtils.cpp @@ -0,0 +1,115 @@ +// +// Copyright 2019 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#include "../common/viewerArgsUtils.h" + +#include "../common/objAnim.h" +#include "../common/shapeDesc.h" + +#include +#include + +namespace ViewerArgsUtils { + +const ObjAnim * +PopulateAnimShapes(const ArgOptions &args, + std::vector *defaultShapes) +{ + if (!defaultShapes) + return NULL; + + if (args.GetObjFiles().empty()) + return NULL; + + + const ObjAnim *objAnim = ObjAnim::Create(args.GetObjFiles(), args.GetAxis(), + args.GetDefaultScheme()); + + if (objAnim) { + defaultShapes->push_back(ShapeDesc(args.GetObjFiles()[0], "", + args.GetDefaultScheme())); + } + + return objAnim; + +} + +void +PopulateShapes(const ArgOptions &args, + std::vector *defaultShapes) +{ + if (!defaultShapes) + return; + + if (args.GetObjFiles().empty()) + return; + + for (size_t i = 0; i < args.GetObjFiles().size(); ++i) { + std::ifstream ifs(args.GetObjFiles()[i]); + if (ifs) { + std::stringstream ss; + ss << ifs.rdbuf(); + ifs.close(); + std::string str = ss.str(); + defaultShapes->push_back(ShapeDesc( + args.GetObjFiles()[i], str.c_str(), + args.GetDefaultScheme())); + } else { + printf("Warning: cannot open shape file '%s'\n", + args.GetObjFiles()[i]); + } + } + +} + +void +PopulateShapesOrAnimShapes( + const ArgOptions &args, + std::vector *defaultShapes, + const ObjAnim **objAnim) +{ + if (!defaultShapes) + return; + + if (args.GetObjFiles().empty()) + return; + + if (args.GetObjsAreAnim()) { + + if (!objAnim) { + printf("Warning: animations of objs are unsupported in this " + "viewer.\n"); + return; + } + + *objAnim = PopulateAnimShapes(args, defaultShapes); + + } else { + + PopulateShapes(args, defaultShapes); + + } +} + +} diff --git a/examples/common/viewerArgsUtils.h b/examples/common/viewerArgsUtils.h new file mode 100644 index 00000000..6c4e16f2 --- /dev/null +++ b/examples/common/viewerArgsUtils.h @@ -0,0 +1,61 @@ +// +// Copyright 2019 Pixar +// +// Licensed under the Apache License, Version 2.0 (the "Apache License") +// with the following modification; you may not use this file except in +// compliance with the Apache License and the following modification to it: +// Section 6. Trademarks. is deleted and replaced with: +// +// 6. Trademarks. This License does not grant permission to use the trade +// names, trademarks, service marks, or product names of the Licensor +// and its affiliates, except as required to comply with Section 4(c) of +// the License and to reproduce the content of the NOTICE file. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the Apache License with the above modification is +// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the Apache License for the specific +// language governing permissions and limitations under the Apache License. +// + +#ifndef VIEWER_ARGS_UTILS_H +#define VIEWER_ARGS_UTILS_H + +#include "../../regression/common/shape_utils.h" + +#include "../common/argOptions.h" +#include "../common/shapeDesc.h" + +class ObjAnim; + +#include + +namespace ViewerArgsUtils { + +// From the list of obj files in args, populates the +// defaultShapes vector, treating the objs as an animated series, returning +// an ObjAnim object. +const ObjAnim *PopulateAnimShapes(const ArgOptions &args, + std::vector *defaultShapes); + +// From the list of obj files in args, populates the +// defaultShapes vector. +void PopulateShapes(const ArgOptions &args, + std::vector *defaultShapes); + +// From the list of obj files in args, populates the +// defaultShapes vector and the objAnim object if animated objs have +// been specified in args. +void PopulateShapesOrAnimShapes( + const ArgOptions &args, + std::vector *defaultShapes, + const ObjAnim **objAnim); + + +} // namespace ViewerArgsUtils + +#endif // VIEWER_ARGS_UTILS_H diff --git a/examples/glFVarViewer/glFVarViewer.cpp b/examples/glFVarViewer/glFVarViewer.cpp index 0d51c148..69ecb408 100644 --- a/examples/glFVarViewer/glFVarViewer.cpp +++ b/examples/glFVarViewer/glFVarViewer.cpp @@ -36,11 +36,13 @@ GLFWmonitor* g_primary = 0; OpenSubdiv::Osd::GLMeshInterface *g_mesh = NULL; #include "../../regression/common/far_utils.h" +#include "../common/argOptions.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" #include "../common/glControlMeshDisplay.h" #include "../common/glHud.h" #include "../common/glShaderCache.h" +#include "../common/viewerArgsUtils.h" #include static const char *shaderSource = @@ -76,8 +78,7 @@ OpenSubdiv::Sdc::Options::FVarLinearInterpolation g_fvarBoundary = OpenSubdiv::Sdc::Options::FVAR_LINEAR_ALL; // GUI variables -int g_fullscreen = 0, - g_freeze = 0, +int g_freeze = 0, g_displayStyle = kWireShaded, g_adaptive = 1, g_smoothCornerPatch = 0, @@ -1262,45 +1263,16 @@ parseIntArg(const char* argString, int dfltValue = 0) { //------------------------------------------------------------------------------ int main(int argc, char ** argv) { - bool fullscreen = false; - Scheme defaultScheme = kCatmark; - std::vector objfiles; + ArgOptions args; + + args.Parse(argc, argv); + args.PrintUnrecognizedArgsWarnings(); - for (int i = 1; i < argc; ++i) { - if (strstr(argv[i], ".obj")) { - objfiles.push_back(argv[i]); - } else if (!strcmp(argv[i], "-a")) { - g_adaptive = true; - } else if (!strcmp(argv[i], "-u")) { - g_adaptive = false; - } else if (!strcmp(argv[i], "-l")) { - if (++i < argc) g_level = parseIntArg(argv[i], g_level); - } else if (!strcmp(argv[i], "-c")) { - if (++i < argc) g_repeatCount = parseIntArg(argv[i], g_repeatCount); - } else if (!strcmp(argv[i], "-f")) { - fullscreen = true; - } else if (!strcmp(argv[i], "-bilinear")) { - defaultScheme = kBilinear; - } else if (!strcmp(argv[i], "-catmark")) { - defaultScheme = kCatmark; - } else if (!strcmp(argv[i], "-loop")) { - defaultScheme = kLoop; - } else { - printf("Warning: unrecognized argument '%s' ignored\n", argv[i]); - } - } - for (int i = 0; i < (int)objfiles.size(); ++i) { - std::ifstream ifs(objfiles[i]); - if (ifs) { - std::stringstream ss; - ss << ifs.rdbuf(); - ifs.close(); - std::string str = ss.str(); - g_defaultShapes.push_back(ShapeDesc(objfiles[i], str.c_str(), defaultScheme)); - } else { - printf("Warning: cannot open shape file '%s'\n", objfiles[i]); - } - } + g_adaptive = args.GetAdaptive(); + g_level = args.GetLevel(); + g_repeatCount = args.GetRepeatCount(); + + ViewerArgsUtils::PopulateShapes(args, &g_defaultShapes); initShapes(); @@ -1316,7 +1288,7 @@ int main(int argc, char ** argv) { GLUtils::SetMinimumGLVersion(); - if (fullscreen) { + if (args.GetFullScreen()) { g_primary = glfwGetPrimaryMonitor(); // apparently glfwGetPrimaryMonitor fails under linux : if no primary, @@ -1337,7 +1309,7 @@ int main(int argc, char ** argv) { } if (! (g_window=glfwCreateWindow(g_width, g_height, windowTitle, - fullscreen && g_primary ? g_primary : NULL, NULL))) { + args.GetFullScreen() && g_primary ? g_primary : NULL, NULL))) { std::cerr << "Failed to create OpenGL context.\n"; glfwTerminate(); return 1; diff --git a/examples/glFVarViewer/init_shapes.h b/examples/glFVarViewer/init_shapes.h index bc42b29e..bc6de15c 100644 --- a/examples/glFVarViewer/init_shapes.h +++ b/examples/glFVarViewer/init_shapes.h @@ -24,16 +24,7 @@ #include "../../regression/common/shape_utils.h" #include "../../regression/shapes/all.h" - -struct ShapeDesc { - - ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme) : - name(iname), data(idata), scheme(ischeme) { } - - std::string name, - data; - Scheme scheme; -}; +#include "../common/shapeDesc.h" static std::vector g_defaultShapes; diff --git a/examples/glViewer/glViewer.cpp b/examples/glViewer/glViewer.cpp index 92fc7127..6fd8ba7e 100644 --- a/examples/glViewer/glViewer.cpp +++ b/examples/glViewer/glViewer.cpp @@ -74,6 +74,7 @@ OpenSubdiv::Osd::GLLegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL; bool g_legacyGregoryEnabled = false; #include "../../regression/common/far_utils.h" +#include "../common/argOptions.h" #include "../common/glHud.h" #include "../common/glUtils.h" #include "../common/glControlMeshDisplay.h" @@ -81,6 +82,7 @@ bool g_legacyGregoryEnabled = false; #include "../common/objAnim.h" #include "../common/simple_math.h" #include "../common/stopwatch.h" +#include "../common/viewerArgsUtils.h" #include @@ -172,15 +174,12 @@ int g_currentShape = 0; ObjAnim const * g_objAnim = 0; -bool g_axis=true; - int g_frame = 0, g_repeatCount = 0; float g_animTime = 0; // GUI variables -int g_fullscreen = 0, - g_freeze = 0, +int g_freeze = 0, g_shadingMode = kShadingPatchType, g_displayStyle = kDisplayStyleWireOnShaded, g_adaptive = 1, @@ -1651,62 +1650,27 @@ callbackErrorGLFW(int error, const char* description) { int main(int argc, char ** argv) { - bool fullscreen = false; - Scheme defaultScheme = kCatmark; - std::vector objfiles; - bool objAnimFlag = false; + ArgOptions args; + + args.Parse(argc, argv); - for (int i = 1; i < argc; ++i) { - if (strstr(argv[i], ".obj")) { - objfiles.push_back(argv[i]); - } else if (!strcmp(argv[i], "-a")) { - g_adaptive = true; - } else if (!strcmp(argv[i], "-u")) { - g_adaptive = false; - } else if (!strcmp(argv[i], "-l")) { - if (++i < argc) g_level = atoi(argv[i]); - } else if (!strcmp(argv[i], "-axis")) { - g_axis = false; - } else if (!strcmp(argv[i], "-c")) { - if (++i < argc) g_repeatCount = atoi(argv[i]); - } else if (!strcmp(argv[i], "-f")) { - fullscreen = true; - } else if (!strcmp(argv[i], "-anim")) { - objAnimFlag = true; - } else if (!strcmp(argv[i], "-bilinear")) { - defaultScheme = kBilinear; - } else if (!strcmp(argv[i], "-catmark")) { - defaultScheme = kCatmark; - } else if (!strcmp(argv[i], "-loop")) { - defaultScheme = kLoop; - } else if (!strcmp(argv[i], "-lg")) { + g_adaptive = args.GetAdaptive(); + g_level = args.GetLevel(); + g_repeatCount = args.GetRepeatCount(); + + // Parse remaining args + const std::vector &rargs = args.GetRemainingArgs(); + for (size_t i = 0; i < rargs.size(); ++i) { + + if (!strcmp(rargs[i], "-lg")) { g_legacyGregoryEnabled = true; } else { - printf("Warning: unrecognized argument '%s' ignored\n", argv[i]); + args.PrintUnrecognizedArgWarning(rargs[i]); } } - if (! objfiles.empty()) { - if (objAnimFlag) { - g_objAnim = ObjAnim::Create(objfiles, g_axis, defaultScheme); - if (g_objAnim) { - g_defaultShapes.push_back(ShapeDesc(objfiles[0], "", defaultScheme)); - } - } else { - for (int i = 0; i < (int)objfiles.size(); ++i) { - std::ifstream ifs(objfiles[i]); - if (ifs) { - std::stringstream ss; - ss << ifs.rdbuf(); - ifs.close(); - std::string str = ss.str(); - g_defaultShapes.push_back(ShapeDesc(objfiles[i], str.c_str(), defaultScheme)); - } else { - printf("Warning: cannot open shape file '%s'\n", objfiles[i]); - } - } - } - } + ViewerArgsUtils::PopulateShapesOrAnimShapes( + args, &g_defaultShapes, &g_objAnim); initShapes(); @@ -1724,7 +1688,7 @@ int main(int argc, char ** argv) { GLUtils::SetMinimumGLVersion(argc, argv); - if (fullscreen) { + if (args.GetFullScreen()) { g_primary = glfwGetPrimaryMonitor(); @@ -1746,7 +1710,7 @@ int main(int argc, char ** argv) { } g_window = glfwCreateWindow(g_width, g_height, windowTitle, - fullscreen && g_primary ? g_primary : NULL, NULL); + args.GetFullScreen() && g_primary ? g_primary : NULL, NULL); if (! g_window) { std::cerr << "Failed to create OpenGL context.\n"; diff --git a/examples/glViewer/init_shapes.h b/examples/glViewer/init_shapes.h index c4cfc83c..f85657ee 100644 --- a/examples/glViewer/init_shapes.h +++ b/examples/glViewer/init_shapes.h @@ -25,17 +25,7 @@ #include "../../regression/common/shape_utils.h" #include "../../regression/shapes/all.h" -struct ShapeDesc { - - ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme, - bool iIsLeftHanded = false) : - name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) { } - - std::string name; - std::string data; - Scheme scheme; - bool isLeftHanded; -}; +#include "../common/shapeDesc.h" static std::vector g_defaultShapes;