Exemple #1
0
void MapView::draw(const Rect& rect)
{
    // update visible tiles cache when needed
    if(m_mustUpdateVisibleTilesCache || m_updateTilesPos > 0)
        updateVisibleTilesCache(m_mustUpdateVisibleTilesCache ? 0 : m_updateTilesPos);

    float scaleFactor = m_tileSize/(float)Otc::TILE_PIXELS;
    Position cameraPosition = getCameraPosition();

    int drawFlags = 0;
    if(m_viewMode == NEAR_VIEW)
        drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls |
                    Otc::DrawItems | Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawMissiles | Otc::DrawAnimations;
    else
        drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawItems;

    Size tileSize = Size(1,1) * m_tileSize;
    if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) {
        m_framebuffer->bind();

        if(m_mustCleanFramebuffer) {
            Rect clearRect = Rect(0, 0, m_drawDimension * m_tileSize);
            g_painter->setColor(Color::black);
            g_painter->drawFilledRect(clearRect);
        }
        g_painter->setColor(Color::white);

        auto it = m_cachedVisibleTiles.begin();
        auto end = m_cachedVisibleTiles.end();
        for(int z=m_cachedLastVisibleFloor;z>=m_cachedFirstVisibleFloor;--z) {
            while(it != end) {
                const TilePtr& tile = *it;
                Position tilePos = tile->getPosition();
                if(tilePos.z != z)
                    break;
                else
                    ++it;

                if(!m_drawMinimapColors)
                    tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags);
                else {
                    uint8 c = tile->getMinimapColorByte();
                    if(c == 0)
                        continue;

                    g_painter->setColor(Color::from8bit(c));
                    g_painter->drawFilledRect(Rect(transformPositionTo2D(tilePos, cameraPosition), tileSize));
                }
            }

            if(drawFlags & Otc::DrawMissiles && !m_drawMinimapColors) {
                for(const MissilePtr& missile : g_map.getFloorMissiles(z)) {
                    missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), scaleFactor, drawFlags & Otc::DrawAnimations);
                }
            }
        }

        m_framebuffer->release();

        // generating mipmaps each frame can be slow in older cards
        //m_framebuffer->getTexture()->buildHardwareMipmaps();

        m_mustDrawVisibleTilesCache = false;
    }


    Point drawOffset = ((m_drawDimension - m_visibleDimension - Size(1,1)).toPoint()/2) * m_tileSize;
    if(isFollowingCreature())
        drawOffset += m_followingCreature->getWalkOffset() * scaleFactor;

    Size srcSize = rect.size();
    Size srcVisible = m_visibleDimension * m_tileSize;
    srcSize.scale(srcVisible, Fw::KeepAspectRatio);
    drawOffset.x += (srcVisible.width() - srcSize.width()) / 2;
    drawOffset.y += (srcVisible.height() - srcSize.height()) / 2;
    Rect srcRect = Rect(drawOffset, srcSize);

    g_painter->setColor(Color::white);
    glDisable(GL_BLEND);
    g_painter->setShaderProgram(m_shader);
#if 0
    // debug source area
    g_painter->saveAndResetState();
    m_framebuffer->bind();
    g_painter->setColor(Color::green);
    g_painter->drawBoundingRect(srcRect, 2);
    m_framebuffer->release();
    g_painter->restoreSavedState();
    m_framebuffer->draw(rect);
#else
    m_framebuffer->draw(rect, srcRect);
#endif
    g_painter->resetShaderProgram();
    glEnable(GL_BLEND);


    // this could happen if the player position is not known yet
    if(!cameraPosition.isValid())
        return;

    float horizontalStretchFactor = rect.width() / (float)srcRect.width();
    float verticalStretchFactor = rect.height() / (float)srcRect.height();

    // avoid drawing texts on map in far zoom outs
    if(m_viewMode == NEAR_VIEW && m_drawTexts) {
        for(const CreaturePtr& creature : m_cachedFloorVisibleCreatures) {
            Point creatureOffset = Point(16 - creature->getDisplacementX(), -3 - creature->getDisplacementY());
            Position pos = creature->getPosition();
            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p += (creature->getDrawOffset() + creatureOffset) * scaleFactor;
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();

            creature->drawInformation(p, g_map.isCovered(pos, m_cachedFirstVisibleFloor), rect);
        }

        for(const StaticTextPtr& staticText : g_map.getStaticTexts()) {
            Position pos = staticText->getPosition();

            // ony draw static texts from current camera floor, unless yells
            //if(pos.z != cameraPosition.z && !staticText->isYell())
            //    continue;

            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();
            staticText->drawText(p, rect);
        }

        for(const AnimatedTextPtr& animatedText : g_map.getAnimatedTexts()) {
            Position pos = animatedText->getPosition();

            // only draw animated texts from visible floors
            if(pos.z < m_cachedFirstVisibleFloor || pos.z > m_cachedLastVisibleFloor)
                continue;

            // dont draw animated texts from covered tiles
            if(pos.z != cameraPosition.z && g_map.isCovered(pos, m_cachedFirstVisibleFloor))
                continue;

            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();
            animatedText->drawText(p, rect);
        }
    } else if(m_viewMode > NEAR_VIEW) {
        // draw a cross in the center instead of our creature
        /*
            Known Issue: Changing Z axis causes the cross to go off a little bit.
        */
        Rect vRect(0, 0, 2, 10);
        Rect hRect(0, 0, 10, 2);
        g_painter->setColor(Color::white);

        if(!m_follow && m_followingCreature)
        {
            Position pos = m_followingCreature->getPosition();
            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();

            vRect.setX(p.x); vRect.setY(p.y - 4);
            hRect.setX(p.x - 4); hRect.setY(p.y);

            hRect.setWidth(10); hRect.setHeight(2);
            vRect.setWidth(2); vRect.setHeight(10);
        }
        else {
            vRect.moveCenter(rect.center());
            hRect.moveCenter(rect.center());
        }

        g_painter->drawFilledRect(vRect);
        g_painter->drawFilledRect(hRect);
    }
}
Exemple #2
0
void MapView::draw(const Rect& rect)
{
    // update visible tiles cache when needed
    if(m_mustUpdateVisibleTilesCache || m_updateTilesPos > 0)
        updateVisibleTilesCache(m_mustUpdateVisibleTilesCache ? 0 : m_updateTilesPos);

    float scaleFactor = m_tileSize/(float)Otc::TILE_PIXELS;
    Position cameraPosition = getCameraPosition();

    int drawFlags = 0;
    if(m_viewMode == NEAR_VIEW)
        drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls |
                    Otc::DrawItems | Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawMissiles | Otc::DrawAnimations;
    else
        drawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawItems;

    if(m_mustDrawVisibleTilesCache || (drawFlags & Otc::DrawAnimations)) {
        m_framebuffer->bind();

        if(m_mustCleanFramebuffer) {
            Rect clearRect = Rect(0, 0, m_drawDimension * m_tileSize);
            g_painter->setColor(Color::black);
            g_painter->drawFilledRect(clearRect);

            if(m_drawLights) {
                m_lightView->reset();
                m_lightView->resize(m_framebuffer->getSize());

                Light ambientLight;
                if(cameraPosition.z <= Otc::SEA_FLOOR) {
                    ambientLight = g_map.getLight();
                } else {
                    ambientLight.color = 215;
                    ambientLight.intensity = 0;
                }
                ambientLight.intensity = std::max<int>(m_minimumAmbientLight*255, ambientLight.intensity);
                m_lightView->setGlobalLight(ambientLight);
            }
        }
        g_painter->setColor(Color::white);

        auto it = m_cachedVisibleTiles.begin();
        auto end = m_cachedVisibleTiles.end();
        for(int z=m_cachedLastVisibleFloor;z>=m_cachedFirstVisibleFloor;--z) {

            while(it != end) {
                const TilePtr& tile = *it;
                Position tilePos = tile->getPosition();
                if(tilePos.z != z)
                    break;
                else
                    ++it;

                tile->draw(transformPositionTo2D(tilePos, cameraPosition), scaleFactor, drawFlags, m_lightView.get());
            }

            if(drawFlags & Otc::DrawMissiles) {
                for(const MissilePtr& missile : g_map.getFloorMissiles(z)) {
                    missile->draw(transformPositionTo2D(missile->getPosition(), cameraPosition), scaleFactor, drawFlags & Otc::DrawAnimations, m_lightView.get());
                }
            }
        }

        m_framebuffer->release();

        // generating mipmaps each frame can be slow in older cards
        //m_framebuffer->getTexture()->buildHardwareMipmaps();

        m_mustDrawVisibleTilesCache = false;
    }


    float fadeOpacity = 1.0f;
    if(!m_shaderSwitchDone && m_fadeOutTime > 0) {
        fadeOpacity = 1.0f - (m_fadeTimer.timeElapsed() / m_fadeOutTime);
        if(fadeOpacity < 0.0f) {
            m_shader = m_nextShader;
            m_nextShader = nullptr;
            m_shaderSwitchDone = true;
            m_fadeTimer.restart();
        }
    }

    if(m_shaderSwitchDone && m_shader && m_fadeInTime > 0)
        fadeOpacity = std::min(m_fadeTimer.timeElapsed() / m_fadeInTime, 1.0f);

    Rect srcRect = calcFramebufferSource(rect.size());
    Point drawOffset = srcRect.topLeft();

    if(m_shader && g_painter->hasShaders() && g_graphics.shouldUseShaders() && m_viewMode == NEAR_VIEW) {
        Rect framebufferRect = Rect(0,0, m_drawDimension * m_tileSize);
        Point center = srcRect.center();
        Point globalCoord = Point(cameraPosition.x - m_drawDimension.width()/2, -(cameraPosition.y - m_drawDimension.height()/2)) * m_tileSize;
        m_shader->bind();
        m_shader->setUniformValue(ShaderManager::MAP_CENTER_COORD, center.x / (float)framebufferRect.width(), 1.0f - center.y / (float)framebufferRect.height());
        m_shader->setUniformValue(ShaderManager::MAP_GLOBAL_COORD, globalCoord.x / (float)framebufferRect.height(), globalCoord.y / (float)framebufferRect.height());
        m_shader->setUniformValue(ShaderManager::MAP_ZOOM, scaleFactor);
        g_painter->setShaderProgram(m_shader);
    }

    g_painter->setColor(Color::white);
    g_painter->setOpacity(fadeOpacity);
    glDisable(GL_BLEND);
#if 0
    // debug source area
    g_painter->saveAndResetState();
    m_framebuffer->bind();
    g_painter->setColor(Color::green);
    g_painter->drawBoundingRect(srcRect, 2);
    m_framebuffer->release();
    g_painter->restoreSavedState();
    m_framebuffer->draw(rect);
#else
    m_framebuffer->draw(rect, srcRect);
#endif
    g_painter->resetShaderProgram();
    g_painter->resetOpacity();
    glEnable(GL_BLEND);


    // this could happen if the player position is not known yet
    if(!cameraPosition.isValid())
        return;

    float horizontalStretchFactor = rect.width() / (float)srcRect.width();
    float verticalStretchFactor = rect.height() / (float)srcRect.height();

    // avoid drawing texts on map in far zoom outs
    if(m_viewMode == NEAR_VIEW) {
        for(const CreaturePtr& creature : m_cachedFloorVisibleCreatures) {
            if(!creature->canBeSeen())
                continue;

            PointF jumpOffset = creature->getJumpOffset() * scaleFactor;
            Point creatureOffset = Point(16 - creature->getDisplacementX(), - creature->getDisplacementY() - 2);
            Position pos = creature->getPosition();
            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p += (creature->getDrawOffset() + creatureOffset) * scaleFactor - Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y));
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();

            int flags = 0;
            if(m_drawNames){ flags = Otc::DrawNames; }
            if(m_drawHealthBars) { flags |= Otc::DrawBars; }
            creature->drawInformation(p, g_map.isCovered(pos, m_cachedFirstVisibleFloor), rect, flags);
        }
    }

    // lights are drawn after names and before texts
    if(m_drawLights)
        m_lightView->draw(rect, srcRect);

    if(m_viewMode == NEAR_VIEW && m_drawTexts) {
        for(const StaticTextPtr& staticText : g_map.getStaticTexts()) {
            Position pos = staticText->getPosition();

            // ony draw static texts from current camera floor, unless yells
            //if(pos.z != cameraPosition.z && !staticText->isYell())
            //    continue;

            if(pos.z != cameraPosition.z && staticText->getMessageMode() == Otc::MessageNone)
                continue;

            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();
            staticText->drawText(p, rect);
        }

        for(const AnimatedTextPtr& animatedText : g_map.getAnimatedTexts()) {
            Position pos = animatedText->getPosition();

            /*
            // only draw animated texts from visible floors
            if(pos.z < m_cachedFirstVisibleFloor || pos.z > m_cachedLastVisibleFloor)
                continue;

            // dont draw animated texts from covered tiles
            if(pos.z != cameraPosition.z && g_map.isCovered(pos, m_cachedFirstVisibleFloor))
                continue;
            */
            if(pos.z != cameraPosition.z)
                continue;

            Point p = transformPositionTo2D(pos, cameraPosition) - drawOffset;
            p.x = p.x * horizontalStretchFactor;
            p.y = p.y * verticalStretchFactor;
            p += rect.topLeft();
            animatedText->drawText(p, rect);
        }
    }
}