/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "common/scummsys.h" #include "zvision/scripting/controls/paint_control.h" #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/cursors/cursor_manager.h" #include "zvision/graphics/render_manager.h" namespace ZVision { PaintControl::PaintControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream) : Control(engine, key, CONTROL_PAINT) { _cursor = CursorIndex_Active; _paint = NULL; _bkg = NULL; _brush = NULL; _colorKey = 0; _mouseDown = false; // Loop until we find the closing brace Common::String line = stream.readLine(); _engine->getScriptManager()->trimCommentsAndWhiteSpace(&line); Common::String param; Common::String values; getParams(line, param, values); while (!stream.eos() && !line.contains('}')) { if (param.matchString("rectangle", true)) { int x; int y; int width; int height; sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height); _rectangle = Common::Rect(x, y, width + x, height + y); } else if (param.matchString("cursor", true)) { _cursor = _engine->getCursorManager()->getCursorId(values); } else if (param.matchString("brush_file", true)) { _brush = _engine->getRenderManager()->loadImage(values, false); } else if (param.matchString("venus_id", true)) { _venusId = atoi(values.c_str()); } else if (param.matchString("paint_file", true)) { _paint = _engine->getRenderManager()->loadImage(values, false); } else if (param.matchString("eligible_objects", true)) { char buf[256]; memset(buf, 0, 256); strncpy(buf, values.c_str(), 255); char *curpos = buf; char *strend = buf + strlen(buf); while (true) { char *st = curpos; if (st >= strend) break; while (*curpos != ' ' && curpos < strend) curpos++; *curpos = 0; curpos++; int obj = atoi(st); _eligibleObjects.push_back(obj); } } line = stream.readLine(); _engine->getScriptManager()->trimCommentsAndWhiteSpace(&line); getParams(line, param, values); } if (_paint) { _colorKey = _paint->format.RGBToColor(255, 0, 255); _bkg = new Graphics::Surface; _bkg->create(_rectangle.width(), _rectangle.height(), _paint->format); _bkg->fillRect(Common::Rect(_rectangle.width(), _rectangle.height()), _colorKey); Graphics::Surface *tmp = new Graphics::Surface; tmp->create(_rectangle.width(), _rectangle.height(), _paint->format); _engine->getRenderManager()->blitSurfaceToSurface(*_paint, _rectangle, *tmp, 0, 0); _paint->free(); delete _paint; _paint = tmp; } } PaintControl::~PaintControl() { // Clear the state value back to 0 //_engine->getScriptManager()->setStateValue(_key, 0); if (_paint) { _paint->free(); delete _paint; } if (_brush) { _brush->free(); delete _brush; } if (_bkg) { _bkg->free(); delete _bkg; } } bool PaintControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; _mouseDown = false; return false; } bool PaintControl::onMouseDown(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; if (_rectangle.contains(backgroundImageSpacePos)) { int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem); if (eligeblity(mouseItem)) { setVenus(); _mouseDown = true; } } return false; } bool PaintControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) { if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED) return false; if (_rectangle.contains(backgroundImageSpacePos)) { int mouseItem = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem); if (eligeblity(mouseItem)) { _engine->getCursorManager()->changeCursor(_cursor); if (_mouseDown) { Common::Rect bkgRect = paint(backgroundImageSpacePos); if (!bkgRect.isEmpty()) { Common::Rect imgRect = bkgRect; imgRect.translate(-_rectangle.left, -_rectangle.top); Graphics::Surface imgUpdate = _bkg->getSubArea(imgRect); _engine->getRenderManager()->blitSurfaceToBkg(imgUpdate, bkgRect.left, bkgRect.top, _colorKey); } } return true; } } return false; } bool PaintControl::eligeblity(int itemId) { for (Common::List::iterator it = _eligibleObjects.begin(); it != _eligibleObjects.end(); it++) if (*it == itemId) return true; return false; } Common::Rect PaintControl::paint(const Common::Point &point) { Common::Rect paintRect = Common::Rect(_brush->w, _brush->h); paintRect.moveTo(point); paintRect.clip(_rectangle); if (!paintRect.isEmpty()) { Common::Rect brushRect = paintRect; brushRect.translate(-point.x, -point.y); Common::Rect bkgRect = paintRect; bkgRect.translate(-_rectangle.left, -_rectangle.top); for (int yy = 0; yy < brushRect.height(); yy++) { uint16 *mask = (uint16 *)_brush->getBasePtr(brushRect.left, brushRect.top + yy); uint16 *from = (uint16 *)_paint->getBasePtr(bkgRect.left, bkgRect.top + yy); uint16 *to = (uint16 *)_bkg->getBasePtr(bkgRect.left, bkgRect.top + yy); for (int xx = 0; xx < brushRect.width(); xx++) { if (*mask != 0) *(to + xx) = *(from + xx); mask++; } } } return paintRect; } } // End of namespace ZVision