void GraphicsContinuousControlItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    if (minValue != maxValue) {
        GraphicsLabelItem::mousePressEvent(event);
        if (event->isAccepted()) {
            valueEditingStarted();
            positionBeforeEdit = pos();
            rectBeforeEdit = rect();
            waitingForMouseReleaseEvent = true;
            valueBeforeEdit = currentValue;
            // create label items marking the minimum and maximum value:
            setZValue(zValue() + 2);
            double absolutePositionBeforeEdit = (orientation == HORIZONTAL ? positionBeforeEdit.x() : -positionBeforeEdit.y());
            double relativePositionBeforeEdit = size * (valueBeforeEdit - minValue) / (maxValue - minValue);
            double minPos = absolutePositionBeforeEdit - relativePositionBeforeEdit;
            double maxPos = minPos + size;
            backgroundRect->setVisible(true);
            minLabel->setVisible(true);
            maxLabel->setVisible(true);
            if (orientation == HORIZONTAL) {
                minLabel->setPos(QPointF(minPos, positionBeforeEdit.y()));
                maxLabel->setPos(QPointF(maxPos, positionBeforeEdit.y()));
            } else {
                minLabel->setPos(QPointF(alignX(minLabel->rect(), rectBeforeEdit.translated(positionBeforeEdit)), -minPos));
                maxLabel->setPos(QPointF(alignX(maxLabel->rect(), rectBeforeEdit.translated(positionBeforeEdit)), -maxPos));
            }
            backgroundRect->setRect((minLabel->rect().translated(minLabel->pos()) | maxLabel->rect().translated(maxLabel->pos())));//.adjusted(-1, -1, 1, 1));
            setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
        }
    }
}
QVariant GraphicsContinuousControlItem::itemChange(GraphicsItemChange change, const QVariant & value)
{
    if (change == QGraphicsItem::ItemPositionChange) {
        if (minValue == maxValue) {
            return pos();
        }
        QPointF newPos = value.toPointF();
        double absolutePositionBeforeEdit = (orientation == HORIZONTAL ? positionBeforeEdit.x() : -positionBeforeEdit.y());
        double relativePositionBeforeEdit = size * (valueBeforeEdit - minValue) / (maxValue - minValue);
        // make sure the element is not moved beyond its limits:
        double minPos = absolutePositionBeforeEdit - relativePositionBeforeEdit;
        double maxPos = minPos + size;
        double currentRelativePosition;
        if (orientation == HORIZONTAL) {
            // y coordinate has to remain constant:
            newPos.setY(positionBeforeEdit.y());
            newPos.setX(qBound(minPos, newPos.x(), maxPos));
            // update the relative position:
            currentRelativePosition = newPos.x() - minPos;
        } else {
            newPos.setY(-qBound(minPos, -newPos.y(), maxPos));
            // update the relative position:
            currentRelativePosition = -newPos.y() - minPos;
        }
        // change the current value according to the position change:
        double nextValue = currentRelativePosition * (maxValue - minValue) / size;
        // if given resolution is non-zero, change value such that
        // nextValue is a multiple of the resolution:
        if (resolution) {
            nextValue = (double)qRound(nextValue / resolution) * resolution;
            currentRelativePosition = nextValue * size / (maxValue - minValue);
            if (orientation == HORIZONTAL) {
                newPos.setX(currentRelativePosition + minPos);
            } else {
                newPos.setY(-currentRelativePosition - minPos);
            }
        }
        nextValue += minValue;
        if (nextValue != currentValue) {
            currentValue = nextValue;
            // change the text accordingly:
            setLabelText(this, currentValue);
            valueChanged(currentValue);
        }
        if (orientation == VERTICAL) {
            // align the new position:
            newPos.setX(alignX(rect(), rectBeforeEdit.translated(positionBeforeEdit)));
        }
        return newPos;
    } else {
        return GraphicsLabelItem::itemChange(change, value);
    }
}
void GMap::draw(Rect drawRect_, bool generate_)
{
    // Draw

    // Generate
    if(generate_)
        generate(drawRect_.getWidth(), drawRect_.getHeight());

    // Draw

    // Map
    for(int mX = 0; mX < alignX(drawRect_.getWidth()); mX++)
    {
        // X
        int x = cameraX(alignX(drawRect_.getWidth())) + mX;

        for(int mY = 0; mY < alignY(drawRect_.getHeight()); mY++)
        {
            // Y
            int y = cameraY(alignY(drawRect_.getHeight())) + mY;

            // Draw
            move(alignY(drawRect_.coord.getY()) + mY, alignX(drawRect_.coord.getY()) + mX);
            if(slot[x][y]->getDynamicType() == ' ')
            {
                addch(slot[x][y]->getStaticType());
            }
            else
            {
                addch(slot[x][y]->getDynamicType());
            }
        }
    }

    // Player
    move(toScrY(playerY, alignY(drawRect_.getHeight()), alignY(drawRect_.coord.getY())),
         toScrX(playerX, alignX(drawRect_.getWidth()), alignX(drawRect_.coord.getX())));
    printw("T");
}
void GMap::generate(int dW, int dH)
{
    // Generate slots

    for(int mX = 0; mX < alignX(dW); mX++)
    {
        // X
        int gX = cameraX(alignX(dW)) + mX;

        for(int mY = 0; mY < alignY(dH); mY++)
        {
            // Y
            int gY = cameraY(alignY(dH)) + mY;

            // Generate
            if( slot.find(gX) == slot.end() ||
                    slot[gX].find(gY) == slot[gX].end() )
            {
                slot[gX][gY] = generateSlot();
            }
        }
    }
}
bool Label::draw(int scrW, int scrH)
{
    // Draw label

    // Center coords
    int lCX = alignX(x + width/2, scrW);
    int lCY = alignY(y + height/2, scrH);

    // Try Big size
    if(!drawText(lCX - textWidth(text, "big", font) / 2,
                 lCY - textHeight(text, "big", font) / 2,
                 animationText(), "big", font,
                 alignX(x, scrW), alignY(y, scrH),
                 alignX(width, scrW), alignY(height, scrH), indent))
    {
        // Try Normal size
        if(!drawText(lCX - textWidth(text, "normal", font) / 2,
                     lCY - textHeight(text, "normal", font) / 2,
                     animationText(), "normal", font,
                     alignX(x, scrW), alignY(y, scrH),
                     alignX(width, scrW), alignY(height, scrH), indent))
        {
            // Try Small size
            if(!drawText(lCX - textWidth(text, "small", font) / 2,
                         lCY - textHeight(text, "small", font) / 2,
                         animationText(), "small", font,
                         alignX(x, scrW), alignY(y, scrH),
                         alignX(width, scrW), alignY(height, scrH), indent))
            {
                // Try Natural size
                return drawText(lCX - textWidth(text, "natural", font) / 2,
                                lCY - textHeight(text, "natural", font) / 2,
                                animationText(), "natural", font,
                                alignX(x, scrW), alignY(y, scrH),
                                alignX(width, scrW), alignY(height, scrH), indent);
            }
        }
    }

    return true;
}
void GraphicsContinuousControlItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
    GraphicsLabelItem::mouseReleaseEvent(event);
    if (waitingForMouseReleaseEvent) {
        waitingForMouseReleaseEvent = false;
        setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
        setSelected(false);
        // remove the minimum/maximum labels:
        setZValue(zValue() - 2);
        backgroundRect->setVisible(false);
        minLabel->setVisible(false);
        maxLabel->setVisible(false);
        // change our position back to the original position:
        setPos(alignX(rect(), rectBeforeEdit.translated(positionBeforeEdit)), positionBeforeEdit.y());
        valueEditingStopped(currentValue);
    }
}
void GraphicsContinuousControlItem::setValue(double value, bool emitSignal)
{
    if (resolution) {
        value = qBound(minValue, (double)qRound(value / resolution) * resolution, maxValue);
    }
    if (value != currentValue) {
        QRectF previousRect = rect().translated(pos());
        currentValue = value;
        // change the text accordingly:
        setLabelText(this, currentValue);
        if (emitSignal) {
            valueChanged(currentValue);
        }
        // align the new position:
        setPos(alignX(rect(), previousRect), pos().y());
    }
}
void GMapHome::generate(int dW, int dH)
{
    // Generate home

    // Set

    // Width
    int hWidth = 10 + randi(10);

    // Height
    int hHeight = hWidth/2;

    // Create clear slots
    for(int mX = -hWidth; mX < alignX(dW) + hWidth*2; mX++)
    {
        // X
        int x = cameraX(alignX(dW)) + mX;

        for(int mY = -hHeight; mY < alignY(dH) + hHeight*2; mY++)
        {
            // Y
            int y = cameraY(alignY(dH)) + mY;

            // Create

            slot[x][y] = new GMapSlot();
        }
    }

    // Home coords
    const int homeX = -hWidth/2;
    const int homeY = -hHeight/2;

    // Generate

    // Home
    for(int mX = -hWidth/2; mX < hWidth/2; mX++)
    {
        for(int mY = -hHeight/2; mY < hHeight/2; mY++)
        {
            slot[mX][mY] = generateSlot();
        }
    }

    // Walls

    // Up / Down
    for(int mX = -hWidth/2; mX <= hWidth/2; mX++)
    {
        // Wall

        slot[mX][-hHeight/2] = &gMapSlotWall;
        slot[mX][hHeight/2] = &gMapSlotWall;
    }

    // Left / Right
    for(int mY = -hHeight/2; mY <= hHeight/2; mY++)
    {
        // Wall

        slot[-hWidth/2][mY] = &gMapSlotWall;
        slot[hWidth/2][mY] = &gMapSlotWall;
    }

    // Door

    // Select angle (left up / right down)

    // Left Up
    int angleX = homeX;
    int angleY = homeY;

    bool leftUp = true;

    // Right down
    if(luck(50.0f))
    {
        angleX *= -1;
        angleY *= -1;

        leftUp = false;
    }

    // Get indent
    int indentX = 1+randi(hWidth-2);
    int indentY = 1+randi(hHeight-2);

    if(!leftUp)
    {
        indentX *= -1;
        indentY *= -1;
    }

    // Set
    int doorX = angleX + indentX;
    int doorY = angleY + indentY;

    if(luck(50.0f))
    {
        slot[homeX][doorY] = &gMapSlotDoor;
        doorX = angleX;
    }
    else
    {
        slot[doorX][homeY] = &gMapSlotDoor;
        doorY = angleY;
    }

    // Set player coords

    // Get
    int playerX_ = getPlayerX();
    int playerY_ = getPlayerY();

    if(leftUp)
    {
        if(angleX == doorX)
        {
            playerX_ = doorX+1;
            playerY_ = doorY;
        }
        else if(angleY == doorY)
        {
            playerY_ = doorY+1;
            playerX_ = doorX;
        }
    }
    else
    {
        if(angleX == doorX)
        {
            playerX_ = doorX-1;
            playerY_ = doorY;
        }
        else if(angleY == doorY)
        {
            playerY_ = doorY-1;
            playerX_ = doorX;
        }
    }

    // Set
    setPlayerX(playerX_);
    setPlayerY(playerY_);

    // Set free generated slot of player coords
    GMapSlot *slot_;
    while(!slot[getPlayerX()][getPlayerY()]->is_free())
    {
        // Generate
        slot_ = generateSlot();

        // Set
        slot[playerX_][playerY_] = slot_;
    }

    // Generated
    setGenerated(true);
}