Skip to content

Commit

Permalink
Let operators create layers beyond 256 of them
Browse files Browse the repository at this point in the history
They were allowed to do this all along, the client just didn't attempt
to to so. It will now start creating layers owned by user 0 (the server)
and then create layers for user 255 and descending from there. This
doesn't remove the layer limit, but it allows for a workaround when e.g.
doing animations, you just need op permissions for it.
  • Loading branch information
askmeaboutlo0m committed Sep 16, 2023
1 parent 3d894b4 commit d464a68
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Unreleased Version 2.2.0-pre
* Feature: Add compatibility for Drawpile 2.1's broken indirect mode.
* Fix: Make the receive delay not delay your own undos.
* Feature: Add a setting for the background color behind the canvas. Thanks to Nightshade for suggesting.
* Feature: Let operators create layers beyond the 256 per-user maximum. They will use layers of user 0 first, then 255, 254 etc. Thanks to haxekhaex2 for reporting.

2023-08-26 Version 2.2.0-beta.7
* Fix: Make classic brushes not go brighter when smudging into transparency. Thanks to cada for reporting.
Expand Down
6 changes: 4 additions & 2 deletions src/desktop/docks/layerlistdock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ void LayerList::changeLayerAcl(bool lock, DP_AccessTier tier, QVector<uint8_t> e

void LayerList::addLayerOrGroup(bool group, bool duplicateKeyFrame, bool keyFrame, int keyFrameOffset)
{
const canvas::LayerListModel *layers = m_canvas->layerlist();
canvas::LayerListModel *layers = m_canvas->layerlist();
Q_ASSERT(layers);

const int id = layers->getAvailableLayerId();
Expand Down Expand Up @@ -430,6 +430,7 @@ void LayerList::addLayerOrGroup(bool group, bool duplicateKeyFrame, bool keyFram
layers->getAvailableLayerName(baseName));
}

layers->setLayerIdToSelect(id);
drawdance::Message messages[] = {
drawdance::Message::makeUndoPoint(contextId), layerMsg, keyFrameMsg,
moveMsg};
Expand Down Expand Up @@ -507,7 +508,7 @@ void LayerList::duplicateLayer()
const QModelIndex index = currentSelection();
const canvas::LayerListItem layer = index.data().value<canvas::LayerListItem>();

const canvas::LayerListModel *layers = m_canvas->layerlist();
canvas::LayerListModel *layers = m_canvas->layerlist();
Q_ASSERT(layers);

const int id = layers->getAvailableLayerId();
Expand All @@ -530,6 +531,7 @@ void LayerList::duplicateLayer()
layers->getAvailableLayerName(layer.title));
}

layers->setLayerIdToSelect(id);
drawdance::Message messages[] = {
drawdance::Message::makeUndoPoint(contextId), msg};
emit layerCommands(DP_ARRAY_LENGTH(messages), messages);
Expand Down
54 changes: 43 additions & 11 deletions src/libclient/canvas/layerlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ namespace canvas {

LayerListModel::LayerListModel(QObject *parent)
: QAbstractItemModel(parent), m_aclstate(nullptr),
m_rootLayerCount(0), m_defaultLayer(0), m_autoselectAny(true), m_frameMode(false)
m_rootLayerCount(0), m_defaultLayer(0), m_autoselectAny(true),
m_frameMode(false), m_layerIdToSelect(0)
{
}

Expand Down Expand Up @@ -285,7 +286,7 @@ static bool isNewLayerId(
}

static int getAutoselect(
uint8_t localUser, bool autoselectAny, int defaultLayer,
uint8_t localUser, bool autoselectAny, int layerIdToSelect, int defaultLayer,
const QVector<LayerListItem> &oldItems, const QVector<LayerListItem> &newItems)
{
if(autoselectAny) {
Expand All @@ -307,7 +308,9 @@ static int getAutoselect(
// We already participated: we might have just created a new layer,
// try to select that one.
for(const LayerListItem &newItem : newItems) {
if(isNewLayerId(oldItems, newItem) && newItem.creatorId() == localUser) {
if(isNewLayerId(oldItems, newItem) &&
(newItem.creatorId() == localUser ||
newItem.id == layerIdToSelect)) {
return newItem.id;
}
}
Expand All @@ -324,7 +327,16 @@ void LayerListModel::setLayers(const drawdance::LayerPropsList &lpl)

const uint8_t localUser = m_aclstate ? m_aclstate->localUserId() : 0;
int autoselect = getAutoselect(
localUser, m_autoselectAny, m_defaultLayer, m_items, newItems);
localUser, m_autoselectAny, m_layerIdToSelect, m_defaultLayer, m_items, newItems);

if(m_layerIdToSelect != 0) {
for(const LayerListItem &item : newItems) {
if(item.id == m_layerIdToSelect) {
m_layerIdToSelect = 0;
break;
}
}
}

beginResetModel();
m_rootLayerCount = lpl.count();
Expand Down Expand Up @@ -469,19 +481,39 @@ int LayerListModel::getAvailableLayerId() const
{
Q_ASSERT(m_aclstate);

const int prefix = int(m_aclstate->localUserId()) << 8;
QList<int> takenIds;
QSet<int> takenIds;
takenIds.insert(0);
for(const LayerListItem &item : m_items) {
if((item.id & 0xff00) == prefix)
takenIds.append(item.id);
takenIds.insert(item.id);
}

int localUserId = m_aclstate->localUserId();
int layerId = searchAvailableLayerId(takenIds, localUserId);
if(layerId == 0 && m_aclstate->amOperator()) {
layerId = searchAvailableLayerId(takenIds, 0);
if(layerId == 0) {
for(int i = 255; i > 0; --i) {
layerId = searchAvailableLayerId(takenIds, i);
if(layerId != 0) {
break;
}
}
}
}

for(int i=0;i<256;++i) {
return layerId;
}

int LayerListModel::searchAvailableLayerId(
const QSet<int> &takenIds, int contextId)
{
int prefix = contextId << 8;
for(int i = 0; i < 256; ++i) {
int id = prefix | i;
if(!takenIds.contains(id))
if(!takenIds.contains(id)) {
return id;
}
}

return 0;
}

Expand Down
5 changes: 5 additions & 0 deletions src/libclient/canvas/layerlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ class LayerListModel final : public QAbstractItemModel {
*/
void setAutoselectAny(bool autoselect) { m_autoselectAny = autoselect; }

void setLayerIdToSelect(int layerId) { m_layerIdToSelect = layerId; }

/**
* @brief Get the default layer to select when logging in
* Zero means no default.
Expand Down Expand Up @@ -170,6 +172,8 @@ public slots:
void layersVisibleInFrameChanged();

private:
static int searchAvailableLayerId(const QSet<int> &takenIds, int contextId);

void flattenKeyFrameLayer(
QVector<KeyFrameLayerItem> &items, int &index, int &layerIndex,
int relIndex, const QHash<int, bool> &layerVisibiltiy) const;
Expand All @@ -182,6 +186,7 @@ public slots:
uint16_t m_defaultLayer;
bool m_autoselectAny;
bool m_frameMode;
int m_layerIdToSelect;
};

/**
Expand Down

0 comments on commit d464a68

Please sign in to comment.