/** * 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); }
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); } }
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(); }
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(); }
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; } }