Example #1
0
/**
 * Merges the tile layer of its brush item into the current map.
 *
 * \a flags can be set to Mergeable, which applies to the undo command.
 *
 * \a paintedRegions is an optional argument that can be used to accumilate
 * the regions touched for each tile layer.
 */
void StampBrush::doPaint(int flags, QHash<TileLayer*, QRegion> *paintedRegions)
{
    // local reference to avoid issues when member gets cleared
    SharedMap preview = mPreviewMap;
    if (!preview)
        return;

    mapDocument()->paintTileLayers(preview.data(),
                                   (flags & Mergeable) == Mergeable,
                                   &mMissingTilesets,
                                   paintedRegions);
}
Example #2
0
void ArrayData::getChildren(std::vector<TypedValue *> &out) {
  if (isSharedMap()) {
    SharedMap *sm = static_cast<SharedMap *>(this);
    sm->getChildren(out);
    return;
  }
  for (ssize_t pos = iter_begin();
      pos != ArrayData::invalid_index;
      pos = iter_advance(pos)) {
    TypedValue *tv = nvGetValueRef(pos);
    out.push_back(tv);
  }
}
Example #3
0
void Array::escalate() {
  if (m_px) {
    SharedMap *mapShared = dynamic_cast<SharedMap *>(m_px);
    if (mapShared) {
      SmartPtr<ArrayData>::operator=(mapShared->escalate());
      return;
    }
    if (!RuntimeOption::UseZendArray) {
      VectorLong *vecLong = dynamic_cast<VectorLong *>(m_px);
      if (vecLong) {
        SmartPtr<ArrayData>::operator=(NEW(MapVariant)(vecLong));
        return;
      }

      VectorString *vecString = dynamic_cast<VectorString *>(m_px);
      if (vecString) {
        SmartPtr<ArrayData>::operator=(NEW(MapVariant)(vecString));
        return;
      }
      VectorVariant *vecVariant = dynamic_cast<VectorVariant *>(m_px);
      if (vecVariant) {
        SmartPtr<ArrayData>::operator=(NEW(MapVariant)(vecVariant));
        return;
      }

      MapLong *mapLong = dynamic_cast<MapLong *>(m_px);
      if (mapLong) {
        SmartPtr<ArrayData>::operator=(NEW(MapVariant)(mapLong));
        return;
      }

      MapString *mapString = dynamic_cast<MapString *>(m_px);
      if (mapString) {
        SmartPtr<ArrayData>::operator=(NEW(MapVariant)(mapString));
        return;
      }

      SharedMap *mapShared = dynamic_cast<SharedMap *>(m_px);
      if (mapShared) {
        SmartPtr<ArrayData>::operator=(mapShared->escalate());
        return;
      }

      ASSERT(dynamic_cast<EmptyArray *>(m_px) ||
             dynamic_cast<VectorVariant *>(m_px) ||
             dynamic_cast<MapVariant *>(m_px));
    }
  }
}
void SharedVariant::loadElems(ArrayData *&elems,
                                    const SharedMap &sharedMap,
                                    bool keepRef /* = false */) {
  ASSERT(is(KindOfArray));
  uint count = arrSize();
  ArrayInit ai(count, getIsVector(), keepRef);
  for (uint i = 0; i < count; i++) {
    if (getIsVector()) {
      ai.add((int64)i, sharedMap.getValueRef(i), true);
    } else {
      ai.add(m_data.map->getKeyIndex(i)->toLocal(), sharedMap.getValueRef(i),
             true);
    }
  }
  elems = ai.create();
  if (elems->isStatic()) elems = elems->copy();
}
Example #5
0
HOT_FUNC
void ArrayData::release() {
  if (isHphpArray()) {
    HphpArray* that = static_cast<HphpArray*>(this);
    that->release();
    return;
  }
  if (isSharedMap()) {
    SharedMap* that = static_cast<SharedMap*>(this);
    that->release();
    return;
  }
  if (isArrayShell()) {
    auto that = static_cast<ArrayShell*>(this);
    that->release();
    return;
  }
  assert(m_kind == kNameValueTableWrapper);
  // NameValueTableWrapper: nop.
}
void SharedVariant::loadElems(ArrayData *&elems,
                              const SharedMap &sharedMap,
                              bool keepRef /* = false */,
                              bool mapInit /* = false */) {
  assert(is(KindOfArray));
  uint count = arrSize();
  bool isVector = getIsVector();
  ArrayInit ai = keepRef ? ArrayInit(count, true) :
                 mapInit ? ArrayInit(count, ArrayInit::mapInit) :
                 isVector ? ArrayInit(count, ArrayInit::vectorInit) :
                 ArrayInit(count, false);
  if (isVector) {
    for (uint i = 0; i < count; i++) {
      ai.set(sharedMap.getValueRef(i));
    }
  } else {
    for (uint i = 0; i < count; i++) {
      ai.add(m_data.map->getKeyIndex(i)->toLocal(), sharedMap.getValueRef(i),
             true);
    }
  }
  elems = ai.create();
  if (elems->isStatic()) elems = elems->copy();
}
Example #7
0
void StampBrush::drawPreviewLayer(const QVector<QPoint> &points)
{
    mPreviewMap.clear();

    if (mStamp.isEmpty() && !mIsWangFill)
        return;

    if (mIsRandom) {
        if (mRandomCellPicker.isEmpty())
            return;

        QRect bounds;
        for (const QPoint &p : points)
            bounds |= QRect(p, p);

        SharedMap preview = SharedMap::create(mapDocument()->map()->orientation(),
                                              bounds.size(),
                                              mapDocument()->map()->tileSize());

        std::unique_ptr<TileLayer> previewLayer {
            new TileLayer(QString(), bounds.topLeft(), bounds.size())
        };

        for (const QPoint &p : points) {
            const Cell &cell = mRandomCellPicker.pick();
            previewLayer->setCell(p.x() - bounds.left(),
                                  p.y() - bounds.top(),
                                  cell);
        }

        preview->addLayer(previewLayer.release());
        preview->addTilesets(preview->usedTilesets());
        mPreviewMap = preview;
    } else if (mIsWangFill) {
        if (!mWangSet)
            return;

        const TileLayer *tileLayer = currentTileLayer();
        if (!tileLayer)
            return;

        QRegion paintedRegion;
        for (const QPoint &p : points)
            paintedRegion += QRect(p, p);

        const QRect bounds = paintedRegion.boundingRect();
        SharedMap preview = SharedMap::create(mapDocument()->map()->orientation(),
                                              bounds.size(),
                                              mapDocument()->map()->tileSize());

        std::unique_ptr<TileLayer> previewLayer {
            new TileLayer(QString(), bounds.topLeft(), bounds.size())
        };

        WangFiller wangFiller(mWangSet,
                              dynamic_cast<StaggeredRenderer *>(mapDocument()->renderer()),
                              mapDocument()->map()->staggerAxis());

        for (const QPoint &p : points) {
            Cell cell = wangFiller.findFittingCell(*tileLayer,
                                                   *previewLayer,
                                                   paintedRegion,
                                                   p);

            previewLayer->setCell(p.x() - bounds.left(),
                                  p.y() - bounds.top(),
                                  cell);
        }

        preview->addLayer(previewLayer.release());
        preview->addTileset(mWangSet->tileset()->sharedPointer());
        mPreviewMap = preview;
    } else {
        QRegion paintedRegion;
        QVector<PaintOperation> operations;
        QHash<const Map *, QRegion> regionCache;
        QHash<const Map *, Map *> shiftedCopies;

        for (const QPoint &p : points) {
            Map *map = mStamp.randomVariation().map;
            mapDocument()->unifyTilesets(map, mMissingTilesets);

            Map::StaggerAxis mapStaggerAxis = mapDocument()->map()->staggerAxis();

            // if staggered map, makes sure stamp stays the same
            if (mapDocument()->map()->isStaggered()
                    && ((mapStaggerAxis == Map::StaggerY) ? map->height() > 1 : map->width() > 1)) {

                Map::StaggerIndex mapStaggerIndex = mapDocument()->map()->staggerIndex();
                Map::StaggerIndex stampStaggerIndex = map->staggerIndex();

                if (mapStaggerAxis == Map::StaggerY) {
                    bool topIsOdd = (p.y() - map->height() / 2) & 1;

                    if ((stampStaggerIndex == mapStaggerIndex) == topIsOdd) {
                        Map *shiftedMap = shiftedCopies.value(map);
                        if (!shiftedMap) {
                            shiftedMap = new Map(*map);
                            shiftedCopies.insert(map, shiftedMap);

                            LayerIterator it(shiftedMap, Layer::TileLayerType);
                            while (auto tileLayer = static_cast<TileLayer*>(it.next()))
                                shiftRows(tileLayer, stampStaggerIndex);
                        }
                        map = shiftedMap;
                    }
                } else {
                    bool leftIsOdd = (p.x() - map->width() / 2) & 1;

                    if ((stampStaggerIndex == mapStaggerIndex) == leftIsOdd) {
                        Map *shiftedMap = shiftedCopies.value(map);
                        if (!shiftedMap) {
                            shiftedMap = new Map(*map);
                            shiftedCopies.insert(map, shiftedMap);

                            LayerIterator it(shiftedMap, Layer::TileLayerType);
                            while (auto tileLayer = static_cast<TileLayer*>(it.next()))
                                shiftColumns(tileLayer, stampStaggerIndex);
                        }
                        map = shiftedMap;
                    }
                }
            }

            QRegion stampRegion;
            if (regionCache.contains(map)) {
                stampRegion = regionCache.value(map);
            } else {
                stampRegion = map->tileRegion();
                regionCache.insert(map, stampRegion);
            }

            QPoint centered(p.x() - map->width() / 2,
                            p.y() - map->height() / 2);

            const QRegion region = stampRegion.translated(centered.x(),
                                                          centered.y());
            if (!paintedRegion.intersects(region)) {
                paintedRegion += region;

                PaintOperation op = { centered, map };
                operations.append(op);
            }
        }

        const QRect bounds = paintedRegion.boundingRect();
        SharedMap preview = SharedMap::create(mapDocument()->map()->orientation(),
                                              bounds.size(),
                                              mapDocument()->map()->tileSize());

        for (const PaintOperation &op : operations) {
            LayerIterator layerIterator(op.stamp, Layer::TileLayerType);
            while (auto tileLayer = static_cast<TileLayer*>(layerIterator.next())) {
                TileLayer *target = findTileLayerByName(*preview, tileLayer->name());
                if (!target) {
                    target = new TileLayer(tileLayer->name(), bounds.topLeft(), bounds.size());
                    preview->addLayer(target);
                }
                target->merge(op.pos - bounds.topLeft() + tileLayer->position(), tileLayer);
            }
        }

        qDeleteAll(shiftedCopies);

        preview->addTilesets(preview->usedTilesets());
        mPreviewMap = preview;
    }
}