diff -r 7986584e7498 -r 9ecc878c7dea src/editmodes/magicWandMode.cpp --- a/src/editmodes/magicWandMode.cpp Sun Sep 06 20:45:51 2015 +0300 +++ b/src/editmodes/magicWandMode.cpp Tue Sep 22 00:59:21 2015 +0300 @@ -30,8 +30,12 @@ { // Note: this deliberately only takes vertex-objects into account. // The magic wand does not process subparts. - for (int i = 0; i < obj->numVertices(); ++i) - m_vertices[obj->vertex (i)] << obj; + if (obj->hasVertices()) + { + LDVertexObject* vo = static_cast (obj); + for (int i = 0; i < vo->numVertices(); ++i) + m_vertices[vo->vertex (i)] << vo; + } } } @@ -40,11 +44,11 @@ return EditModeType::MagicWand; } -void MagicWandMode::fillBoundaries (LDObject* obj, QVector& boundaries, QVector& candidates) +void MagicWandMode::fillBoundaries (LDVertexObject* obj, Boundaries& boundaries, Candidates& candidates) { // All boundaries obviously share vertices with the object, therefore they're all in the list // of candidates. - for (LDObject* candidate : candidates) + for (LDVertexObject* candidate : candidates) { if (not isOneOf (candidate->type(), OBJ_Line, OBJ_CondLine) or candidate->vertex (0) == candidate->vertex (1)) continue; @@ -64,16 +68,15 @@ m_selection << candidate; else boundaries.append (std::make_tuple (candidate->vertex (0), candidate->vertex (1))); - break; } } } } -void MagicWandMode::doMagic (LDObject* obj, MagicWandMode::MagicType type) +void MagicWandMode::doMagic (LDObject* input, MagicType type) { - if (obj == nullptr) + if (input == nullptr or not input->hasVertices()) { if (type == Set) { @@ -84,8 +87,9 @@ return; } - int matchesneeded = 0; - QVector boundaries; + LDVertexObject* obj = static_cast (input); + int matchesneeded = (obj->numVertices() == 2) ? 1 : 2; + Boundaries boundaries; LDObjectType objtype = obj->type(); if (type != InternalRecursion) @@ -94,23 +98,7 @@ m_selection.append (obj); } - switch (obj->type()) - { - case OBJ_Line: - case OBJ_CondLine: - matchesneeded = 1; - break; - - case OBJ_Triangle: - case OBJ_Quad: - matchesneeded = 2; - break; - - default: - return; - } - - QVector candidates; + Candidates candidates; // Get the list of objects that touch this object, i.e. share a vertex // with this. @@ -123,57 +111,38 @@ if (matchesneeded > 1) fillBoundaries (obj, boundaries, candidates); - for (LDObject* candidate : candidates) + for (LDVertexObject* candidate : candidates) { - try - { - // If we're doing this on lines, we need exact type match. Surface types (quads and - // triangles) can be mixed. Also don't consider self a candidate, and don't consider - // objects we have already processed. - if ((candidate == obj) or - (candidate->color() != obj->color()) or - (m_selection.contains (candidate)) or - (matchesneeded == 1 and (candidate->type() != objtype)) or - ((candidate->numVertices() > 2) ^ (matchesneeded == 2))) - { - throw 0; - } - - // Now ensure the two objects share enough vertices. - QVector matches; - - for (int i = 0; i < obj->numVertices(); ++i) - { - for (int j = 0; j < candidate->numVertices(); ++j) - { - if (obj->vertex(i) == candidate->vertex(j)) - { - matches << obj->vertex(i); - break; - } - } - } - - if (matches.size() < matchesneeded) - throw 0; // Not enough matches. - - // Check if a boundary gets in between the objects. - for (auto boundary : boundaries) - { - if (isOneOf (matches[0], std::get<0> (boundary), std::get<1> (boundary)) and - isOneOf (matches[1], std::get<0> (boundary), std::get<1> (boundary))) - { - throw 0; - } - } - - m_selection.append (candidate); - doMagic (candidate, InternalRecursion); - } - catch (int&) + // If we're doing this on lines, we need exact type match. Surface types (quads and + // triangles) can be mixed. Also don't consider self a candidate, and don't consider + // objects we have already processed. + if ((candidate == obj) or + (candidate->color() != obj->color()) or + (m_selection.contains (candidate)) or + (matchesneeded == 1 and (candidate->type() != objtype)) or + ((candidate->numVertices() > 2) ^ (matchesneeded == 2))) { continue; } + + // Now ensure the two objects share enough vertices. + QSet matches = obj->vertexSet(); + matches.intersect (candidate->vertexSet()); + + if (matches.size() < matchesneeded) + goto skipthis; // Not enough matches. + + // Check if a boundary gets in between the objects. + for (const Boundary& boundary : boundaries) + { + if (matches.contains (std::get<0>(boundary)) and matches.contains (std::get<1>(boundary))) + goto skipthis; + } + + m_selection.append (candidate); + doMagic (candidate, InternalRecursion); +skipthis: + continue; } switch (type) @@ -212,7 +181,8 @@ else if (data.keymods & Qt::ControlModifier) wandtype = MagicWandMode::Subtractive; - doMagic (renderer()->pickOneObject (data.ev->x(), data.ev->y()), wandtype); + LDObject* obj = renderer()->pickOneObject (data.ev->x(), data.ev->y()); + doMagic (obj, wandtype); return true; }