#include "GGraph.h" #include "utils/ByteBuffer.h" #include "utils/ToolSet.h" NS_FGUI_BEGIN USING_NS_AX; static void drawVertRect(ax::DrawNode* shape, float x, float y, float width, float height, const ax::Color4F& color) { float mx = x + width; float my = y + height; shape->drawTriangle(Vec2(x, y), Vec2(mx, y), Vec2(x, my), color); shape->drawTriangle(Vec2(mx, y), Vec2(mx, my), Vec2(x, my), color); } GGraph::GGraph() : _shape(nullptr), _type(0), _lineSize(1), _lineColor(Color4F::BLACK), _fillColor(Color4F::WHITE), _cornerRadius(nullptr), _polygonPoints(nullptr), _distances(nullptr) { _touchDisabled = true; } GGraph::~GGraph() { AX_SAFE_DELETE(_cornerRadius); AX_SAFE_DELETE(_polygonPoints); AX_SAFE_DELETE(_distances); } void GGraph::handleInit() { _shape = DrawNode::create(); _shape->retain(); _displayObject = _shape; } void GGraph::drawRect(float aWidth, float aHeight, int lineSize, const ax::Color4F& lineColor, const ax::Color4F& fillColor) { _type = 0; //avoid updateshape call in handleSizeChange setSize(aWidth, aHeight); _type = 1; _lineSize = lineSize; _lineColor = lineColor; _fillColor = fillColor; updateShape(); } void GGraph::drawEllipse(float aWidth, float aHeight, int lineSize, const ax::Color4F& lineColor, const ax::Color4F& fillColor) { _type = 0; //avoid updateshape call in handleSizeChange setSize(aWidth, aHeight); _type = 2; _lineSize = lineSize; _lineColor = lineColor; _fillColor = fillColor; updateShape(); } void GGraph::drawPolygon(int lineSize, const ax::Color4F& lineColor, const ax::Color4F& fillColor, const ax::Vec2* points, int count) { _type = 3; _lineSize = lineSize; _lineColor = lineColor; _fillColor = fillColor; if (_polygonPoints == nullptr) _polygonPoints = new std::vector(); else _polygonPoints->clear(); float h = getHeight(); _polygonPointOffset = h; for (int i = 0; i < count; i++) { Vec2 pt = *(points + i); pt.y = h - pt.y; _polygonPoints->push_back(*(points + i)); } updateShape(); } void GGraph::drawRegularPolygon(int lineSize, const ax::Color4F& lineColor, const ax::Color4F& fillColor, int sides, float startAngle, const float* distances, int count) { _type = 4; _lineSize = lineSize; _lineColor = lineColor; _fillColor = fillColor; _sides = sides; _startAngle = startAngle; if (distances != nullptr) { if (_distances == nullptr) _distances = new std::vector(); else _distances->clear(); for (int i = 0; i < count; i++) _distances->push_back(*(distances + i)); } else if (_distances != nullptr) _distances->clear(); } void GGraph::updateShape() { _shape->clear(); if (_type == 0) { _touchDisabled = false; return; } switch (_type) { case 1: { if (_lineSize > 0) { float wl = _size.width - _lineSize; float hl = _size.height - _lineSize; drawVertRect(_shape, 0, 0, wl, _lineSize, _lineColor); drawVertRect(_shape, wl, 0, _lineSize, hl, _lineColor); drawVertRect(_shape, _lineSize, hl, wl, _lineSize, _lineColor); drawVertRect(_shape, 0, _lineSize, _lineSize, hl, _lineColor); drawVertRect(_shape, _lineSize, _lineSize, _size.width - _lineSize * 2, _size.height - _lineSize * 2, _fillColor); } else drawVertRect(_shape, 0, 0, _size.width, _size.height, _fillColor); break; } case 2: { if (_lineSize > 0) { _shape->setLineWidth(_lineSize); _shape->drawCircle(Vec2(_size.width / 2, _size.height / 2), _size.width / 2, 0, 360, false, 1, _size.height / _size.width, _lineColor); } _shape->drawSolidCircle(Vec2(_size.width / 2, _size.height / 2), _size.width / 2, 0, 360, 1, _size.height / _size.width, _fillColor); break; } case 3: { _shape->drawPolygon(_polygonPoints->data(), (int)_polygonPoints->size(), _fillColor, _lineSize * 0.5f, _lineColor); break; } case 4: { float h = getHeight(); _polygonPointOffset = h; if (_polygonPoints == nullptr) _polygonPoints = new std::vector(); else _polygonPoints->clear(); float radius = MIN(getWidth(), getHeight()) * 0.5f; float angle = MATH_DEG_TO_RAD(_startAngle); float deltaAngle = 2 * M_PI / _sides; float dist; for (int i = 0; i < _sides; i++) { if (_distances != nullptr && i < (int)_distances->size()) dist = (*_distances)[i]; else dist = 1; float xv = radius + radius * dist * cos(angle); float yv = h - (radius + radius * dist * sin(angle)); _polygonPoints->push_back(Vec2(xv, yv)); angle += deltaAngle; } _shape->drawPolygon(_polygonPoints->data(), (int)_polygonPoints->size(), _fillColor, _lineSize * 0.5f, _lineColor); break; } } } ax::Color3B GGraph::getColor() const { return (Color3B)_fillColor; } void GGraph::setColor(const ax::Color3B& value) { _fillColor = Color4F(value, _fillColor.a); updateShape(); } ax::Value GGraph::getProp(ObjectPropID propId) { switch (propId) { case ObjectPropID::Color: return Value(ToolSet::colorToInt(getColor())); default: return GObject::getProp(propId); } } void GGraph::setProp(ObjectPropID propId, const ax::Value& value) { switch (propId) { case ObjectPropID::Color: setColor(ToolSet::intToColor(value.asUnsignedInt())); break; default: GObject::setProp(propId, value); break; } } void GGraph::handleSizeChanged() { GObject::handleSizeChanged(); if (_type == 3 || _type == 4) { float h = getHeight(); int count = (int)_polygonPoints->size(); for (int i = 0; i < count; i++) { Vec2 pt = (*_polygonPoints)[i]; pt.y = h - (_polygonPointOffset - pt.y); (*_polygonPoints)[i] = pt; } _polygonPointOffset = h; } updateShape(); } void GGraph::setup_beforeAdd(ByteBuffer* buffer, int beginPos) { GObject::setup_beforeAdd(buffer, beginPos); buffer->seek(beginPos, 5); _type = buffer->readByte(); if (_type != 0) { _lineSize = buffer->readInt(); _lineColor = (Color4F)buffer->readColor(); _fillColor = (Color4F)buffer->readColor(); if (buffer->readBool()) { _cornerRadius = new float[4]; for (int i = 0; i < 4; i++) _cornerRadius[i] = buffer->readFloat(); } if (_type == 3) { int cnt = buffer->readShort() / 2; _polygonPoints = new std::vector(cnt); float h = getHeight(); _polygonPointOffset = h; for (int i = 0; i < cnt; i++) { float f1 = buffer->readFloat(); float f2 = h - buffer->readFloat(); (*_polygonPoints)[i] = Vec2(f1, f2); } } else if (_type == 4) { _sides = buffer->readShort(); _startAngle = buffer->readFloat(); int cnt = buffer->readShort(); if (cnt > 0) { _distances = new std::vector(cnt); for (int i = 0; i < cnt; i++) (*_distances)[i] = buffer->readFloat(); } } updateShape(); } } NS_FGUI_END