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