1 /*
2  Copyright (C) 2010-2014 Kristian Duske
3 
4  This file is part of TrenchBroom.
5 
6  TrenchBroom is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  TrenchBroom is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "EntityColor.h"
21 
22 #include "Model/AttributableNode.h"
23 #include "Model/Entity.h"
24 #include "Model/NodeVisitor.h"
25 #include "Model/World.h"
26 
27 #include <cassert>
28 
29 namespace TrenchBroom {
30     namespace Model {
31         class DetectColorRangeVisitor : public ConstNodeVisitor {
32         private:
33             const AttributeName& m_name;
34             Assets::ColorRange::Type m_range;
35         public:
DetectColorRangeVisitor(const AttributeName & name)36             DetectColorRangeVisitor(const AttributeName& name) :
37             m_name(name),
38             m_range(Assets::ColorRange::Unset) {}
39 
result() const40             Assets::ColorRange::Type result() const { return m_range; }
41         private:
doVisit(const World * world)42             void doVisit(const World* world)   { visitAttributableNode(world); }
doVisit(const Layer * layer)43             void doVisit(const Layer* layer)   {}
doVisit(const Group * group)44             void doVisit(const Group* group)   {}
doVisit(const Entity * entity)45             void doVisit(const Entity* entity) { visitAttributableNode(entity); }
doVisit(const Brush * brush)46             void doVisit(const Brush* brush)   {}
47 
visitAttributableNode(const AttributableNode * attributable)48             void visitAttributableNode(const AttributableNode* attributable) {
49                 static const AttributeValue NullValue("");
50                 const AttributeValue& value = attributable->attribute(m_name, NullValue);
51                 if (value != NullValue) {
52                     const Assets::ColorRange::Type attrRange = Assets::detectColorRange(value);
53                     if (m_range == Assets::ColorRange::Unset)
54                         m_range = attrRange;
55                     else if (m_range != attrRange)
56                         m_range = Assets::ColorRange::Mixed;
57                 }
58             }
59         };
60 
detectColorRange(const AttributeName & name,const AttributableNodeList & attributables)61         Assets::ColorRange::Type detectColorRange(const AttributeName& name, const AttributableNodeList& attributables) {
62             DetectColorRangeVisitor visitor(name);
63             Node::accept(attributables.begin(), attributables.end(), visitor);
64             return visitor.result();
65         }
66 
convertEntityColor(const String & str,const Assets::ColorRange::Type colorRange)67         const String convertEntityColor(const String& str, const Assets::ColorRange::Type colorRange) {
68             const wxColor color = parseEntityColor(str);
69             return entityColorAsString(color, colorRange);
70         }
71 
parseEntityColor(const String & str)72         wxColor parseEntityColor(const String& str) {
73             const StringList components = StringUtils::splitAndTrim(str, " ");
74             const Assets::ColorRange::Type range = Assets::detectColorRange(components);
75             assert(range != Assets::ColorRange::Mixed);
76 
77             int r = 0, g = 0, b = 0;
78             if (range == Assets::ColorRange::Byte) {
79                 r = std::atoi(components[0].c_str());
80                 g = std::atoi(components[1].c_str());
81                 b = std::atoi(components[2].c_str());
82             } else if (range == Assets::ColorRange::Float) {
83                 r = static_cast<int>(std::atof(components[0].c_str()) * 255.0);
84                 g = static_cast<int>(std::atof(components[1].c_str()) * 255.0);
85                 b = static_cast<int>(std::atof(components[2].c_str()) * 255.0);
86             }
87 
88             return wxColor(r, g, b);
89         }
90 
entityColorAsString(const wxColor & color,const Assets::ColorRange::Type colorRange)91         String entityColorAsString(const wxColor& color, const Assets::ColorRange::Type colorRange) {
92             StringStream result;
93             if (colorRange == Assets::ColorRange::Byte) {
94                 result << int(color.Red()) << " " << int(color.Green()) << " " << int(color.Blue());
95             } else if (colorRange == Assets::ColorRange::Float) {
96                 result << float(color.Red()) / 255.0f << " " << float(color.Green()) / 255.0f << " "<< float(color.Blue()) / 255.0f;
97             }
98             return result.str();
99         }
100     }
101 }
102