aseprite/src/tools/tool_box.cpp
David Capello 1fd011c20b Move everything related to tools in "tools" namespace.
+ Splitted tools/tool.h|cpp in several files (ink.h, intertwine.h, etc.).
2011-04-02 10:47:03 -03:00

247 lines
8.9 KiB
C++

/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2011 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "base/exception.h"
#include "gui_xml.h"
#include "raster/algo.h"
#include "raster/image.h"
#include "raster/mask.h"
#include "raster/pen.h"
#include "tools/controller.h"
#include "tools/ink.h"
#include "tools/intertwine.h"
#include "tools/point_shape.h"
#include "tools/tool_box.h"
#include "tools/tool_group.h"
#include "tools/tool_loop.h"
#include <algorithm>
#include <allegro/file.h>
#include <allegro/fixed.h>
#include <allegro/fmaths.h>
using namespace gfx;
using namespace tools;
#include "tools/controllers.h"
#include "tools/inks.h"
#include "tools/intertwiners.h"
#include "tools/point_shapes.h"
//////////////////////////////////////////////////////////////////////
ToolBox::ToolBox()
{
PRINTF("Toolbox module: installing\n");
m_inks["selection"] = new SelectionInk();
m_inks["paint"] = new PaintInk(PaintInk::Normal);
m_inks["paint_fg"] = new PaintInk(PaintInk::WithFg);
m_inks["paint_bg"] = new PaintInk(PaintInk::WithBg);
m_inks["eraser"] = new EraserInk(EraserInk::Eraser);
m_inks["replace_fg_with_bg"] = new EraserInk(EraserInk::ReplaceFgWithBg);
m_inks["replace_bg_with_fg"] = new EraserInk(EraserInk::ReplaceBgWithFg);
m_inks["pick_fg"] = new PickInk(PickInk::Fg);
m_inks["pick_bg"] = new PickInk(PickInk::Bg);
m_inks["scroll"] = new ScrollInk();
m_inks["move"] = new MoveInk();
m_inks["blur"] = new BlurInk();
m_inks["jumble"] = new JumbleInk();
m_controllers["freehand"] = new FreehandController();
m_controllers["point_by_point"] = new PointByPointController();
m_controllers["one_point"] = new OnePointController();
m_controllers["two_points"] = new TwoPointsController();
m_controllers["four_points"] = new FourPointsController();
m_pointshapers["none"] = new NonePointShape();
m_pointshapers["pixel"] = new PixelPointShape();
m_pointshapers["pen"] = new PenPointShape();
m_pointshapers["floodfill"] = new FloodFillPointShape();
m_pointshapers["spray"] = new SprayPointShape();
m_intertwiners["none"] = new IntertwineNone();
m_intertwiners["as_lines"] = new IntertwineAsLines();
m_intertwiners["as_rectangles"] = new IntertwineAsRectangles();
m_intertwiners["as_ellipses"] = new IntertwineAsEllipses();
m_intertwiners["as_bezier"] = new IntertwineAsBezier();
loadTools();
PRINTF("Toolbox module: installed\n");
}
struct deleter {
template<typename T>
void operator()(T* p) { delete p; }
template<typename A, typename B>
void operator()(std::pair<A,B>& p) { delete p.second; }
};
ToolBox::~ToolBox()
{
PRINTF("Toolbox module: uninstalling\n");
std::for_each(m_tools.begin(), m_tools.end(), deleter());
std::for_each(m_groups.begin(), m_groups.end(), deleter());
std::for_each(m_intertwiners.begin(), m_intertwiners.end(), deleter());
std::for_each(m_pointshapers.begin(), m_pointshapers.end(), deleter());
std::for_each(m_controllers.begin(), m_controllers.end(), deleter());
std::for_each(m_inks.begin(), m_inks.end(), deleter());
PRINTF("Toolbox module: uninstalled\n");
}
Tool* ToolBox::getToolById(const std::string& id)
{
for (ToolIterator it = begin(); it != end(); ++it) {
Tool* tool = *it;
if (tool->getId() == id)
return tool;
}
// PRINTF("Error get_tool_by_name() with '%s'\n", name.c_str());
// ASSERT(false);
return NULL;
}
void ToolBox::loadTools()
{
PRINTF("Loading ASE tools\n");
TiXmlDocument& doc(GuiXml::instance()->doc());
TiXmlHandle handle(&doc);
// For each group
TiXmlElement* xmlGroup = handle.FirstChild("gui").FirstChild("tools").FirstChild("group").ToElement();
while (xmlGroup) {
const char* group_id = xmlGroup->Attribute("id");
const char* group_text = xmlGroup->Attribute("text");
PRINTF(" - New group '%s'\n", group_id);
if (!group_id || !group_text)
throw base::Exception("The configuration file has a <group> without 'id' or 'text' attributes.");
ToolGroup* tool_group = new ToolGroup(group_id, group_text);
// For each tool
TiXmlNode* xmlToolNode = xmlGroup->FirstChild("tool");
TiXmlElement* xmlTool = xmlToolNode ? xmlToolNode->ToElement(): NULL;
while (xmlTool) {
const char* tool_id = xmlTool->Attribute("id");
const char* tool_text = xmlTool->Attribute("text");
const char* tool_tips = xmlTool->FirstChild("tooltip") ? ((TiXmlElement*)xmlTool->FirstChild("tooltip"))->GetText(): "";
const char* default_pen_size = xmlTool->Attribute("default_pen_size");
Tool* tool = new Tool(tool_group, tool_id, tool_text, tool_tips,
default_pen_size ? strtol(default_pen_size, NULL, 10): 1);
PRINTF(" - New tool '%s' in group '%s' found\n", tool_id, group_id);
loadToolProperties(xmlTool, tool, 0, "left");
loadToolProperties(xmlTool, tool, 1, "right");
m_tools.push_back(tool);
xmlTool = xmlTool->NextSiblingElement();
}
m_groups.push_back(tool_group);
xmlGroup = xmlGroup->NextSiblingElement();
}
}
void ToolBox::loadToolProperties(TiXmlElement* xmlTool, Tool* tool, int button, const std::string& suffix)
{
const char* tool_id = tool->getId().c_str();
const char* fill = xmlTool->Attribute(("fill_"+suffix).c_str());
const char* ink = xmlTool->Attribute(("ink_"+suffix).c_str());
const char* controller = xmlTool->Attribute(("controller_"+suffix).c_str());
const char* pointshape = xmlTool->Attribute(("pointshape_"+suffix).c_str());
const char* intertwine = xmlTool->Attribute(("intertwine_"+suffix).c_str());
const char* tracepolicy = xmlTool->Attribute(("tracepolicy_"+suffix).c_str());
if (!fill) fill = xmlTool->Attribute("fill");
if (!ink) ink = xmlTool->Attribute("ink");
if (!controller) controller = xmlTool->Attribute("controller");
if (!pointshape) pointshape = xmlTool->Attribute("pointshape");
if (!intertwine) intertwine = xmlTool->Attribute("intertwine");
if (!tracepolicy) tracepolicy = xmlTool->Attribute("tracepolicy");
// Fill
Fill fill_value = FillNone;
if (fill) {
if (strcmp(fill, "none") == 0)
fill_value = FillNone;
else if (strcmp(fill, "always") == 0)
fill_value = FillAlways;
else if (strcmp(fill, "optional") == 0)
fill_value = FillOptional;
else
throw base::Exception("Invalid fill '%s' specified in '%s' tool.\n", fill, tool_id);
}
// Find the ink
std::map<std::string, Ink*>::iterator it_ink
= m_inks.find(ink ? ink: "");
if (it_ink == m_inks.end())
throw base::Exception("Invalid ink '%s' specified in '%s' tool.\n", ink, tool_id);
// Find the controller
std::map<std::string, Controller*>::iterator it_controller
= m_controllers.find(controller ? controller: "none");
if (it_controller == m_controllers.end())
throw base::Exception("Invalid controller '%s' specified in '%s' tool.\n", controller, tool_id);
// Find the point_shape
std::map<std::string, PointShape*>::iterator it_pointshaper
= m_pointshapers.find(pointshape ? pointshape: "none");
if (it_pointshaper == m_pointshapers.end())
throw base::Exception("Invalid point-shape '%s' specified in '%s' tool.\n", pointshape, tool_id);
// Find the intertwiner
std::map<std::string, Intertwine*>::iterator it_intertwiner
= m_intertwiners.find(intertwine ? intertwine: "none");
if (it_intertwiner == m_intertwiners.end())
throw base::Exception("Invalid intertwiner '%s' specified in '%s' tool.\n", intertwine, tool_id);
// Trace policy
TracePolicy tracepolicy_value = TracePolicyLast;
if (tracepolicy) {
if (strcmp(tracepolicy, "accumulative") == 0)
tracepolicy_value = TracePolicyAccumulate;
else if (strcmp(tracepolicy, "last") == 0)
tracepolicy_value = TracePolicyLast;
else if (strcmp(tracepolicy, "overlap") == 0)
tracepolicy_value = TracePolicyOverlap;
else
throw base::Exception("Invalid trace-policy '%s' specified in '%s' tool.\n", tracepolicy, tool_id);
}
// Setup the tool properties
tool->setFill(button, fill_value);
tool->setInk(button, it_ink->second);
tool->setController(button, it_controller->second);
tool->setPointShape(button, it_pointshaper->second);
tool->setIntertwine(button, it_intertwiner->second);
tool->setTracePolicy(button, tracepolicy_value);
}