Skip to content

Commit

Permalink
Improve Link support to Arch BuildingPart
Browse files Browse the repository at this point in the history
BuildingPart is a special plain group that has its own display mode
(presumably for annotation and stuff). This patch adds a 'tailChild'
field to SoFCSwitch which will be traversed as long as its 'whichChild'
is not -1. The plain group coin3D node tree snapshot uses its field to
render the group children along with group's own display mode.
  • Loading branch information
realthunder committed Dec 3, 2019
1 parent 028edc7 commit 88174b7
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 41 deletions.
69 changes: 63 additions & 6 deletions src/Gui/SoFCUnifiedSelection.cpp
Expand Up @@ -1180,6 +1180,7 @@ SoFCSwitch::SoFCSwitch()
{
SO_NODE_CONSTRUCTOR(SoFCSwitch);
SO_NODE_ADD_FIELD(defaultChild, (0));
SO_NODE_ADD_FIELD(tailChild, (-1));
SO_NODE_ADD_FIELD(overrideSwitch,(OverrideNone));
SO_NODE_DEFINE_ENUM_VALUE(OverrideSwitch, OverrideNone);
SO_NODE_DEFINE_ENUM_VALUE(OverrideSwitch, OverrideDefault);
Expand Down Expand Up @@ -1265,6 +1266,7 @@ void SoFCSwitch::doAction(SoAction *action) {
((SoCallbackAction *)action)->isCallbackAll()))
{
inherited::doAction(action);
traverseTail(action,whichChild.getValue());
return;
}

Expand Down Expand Up @@ -1310,6 +1312,7 @@ void SoFCSwitch::doAction(SoAction *action) {

if(idx!=SO_SWITCH_ALL && (idx<0 || idx>=this->getNumChildren())) {
inherited::doAction(action);
traverseTail(action,whichChild.getValue());
return;
}

Expand Down Expand Up @@ -1358,13 +1361,68 @@ void SoFCSwitch::doAction(SoAction *action) {
break;
}
}
} else
} else {
this->children->traverse(action, idx);
traverseTail(action,idx);
}

if(tstate.to_ulong())
_SwitchTraverseStack.pop_back();
}

void SoFCSwitch::notify(SoNotList * nl)
{
// SoSwitch ignores child change other than whichChild. But we shall
// include tailChild and defaultChild as well.

SoNotRec * rec = nl->getLastRec();
SbBool ignoreit = FALSE;

// if getBase() == this, the notification is from a field under this
// node, and should _not_ be ignored
if (rec && (rec->getBase() != (SoBase*) this)) {
int which = this->whichChild.getValue();
int tail = this->tailChild.getValue();
int def = this->defaultChild.getValue();
if(which==-1 && tail==-1 && def==-1)
ignoreit = TRUE;
else if(which!=SO_SWITCH_ALL && def!=SO_SWITCH_ALL) {
int fromchild = this->findChild((SoNode*) rec->getBase());
if (fromchild >= 0
&& fromchild!=which
&& fromchild!=tail
&& fromchild!=def)
{
ignoreit = TRUE;
}
}
}
if (!ignoreit)
SoGroup::notify(nl);
}

void SoFCSwitch::traverseTail(SoAction *action, int idx) {
int tail = tailChild.getValue();
if(tail<0 || idx==tail || tail>=getNumChildren())
return;

int numindices = 0;
const int * indices = 0;
SoAction::PathCode pathcode = action->getPathCode(numindices, indices);
if(pathcode != SoAction::IN_PATH) {
this->children->traverse(action,tail);
return;
}

// If traverse in path, traverse if tailChild is in the path
for (int i = 0; i < numindices; i++) {
if (indices[i] == tail) {
this->children->traverse(action, tail);
break;
}
}
}

void SoFCSwitch::getBoundingBox(SoGetBoundingBoxAction * action)
{
if(cb)
Expand Down Expand Up @@ -2352,11 +2410,10 @@ void SoFCPathAnnotation::GLRenderBelowPath(SoGLRenderAction * action)
bool bbox = ViewParams::instance()->getShowSelectionBoundingBox();
if(!bbox) {
for(int i=0,count=path->getLength();i<count;++i) {
if(!path->getNode(i)->isOfType(SoFCSelectionRoot::getClassTypeId()))
continue;
auto node = static_cast<SoFCSelectionRoot*>(path->getNode(i));
if(node->selectionStyle.getValue()==SoFCSelectionRoot::Box) {
bbox = true;
auto node = path->getNodeFromTail(i);
if(node->isOfType(SoFCSelectionRoot::getClassTypeId())) {
if (static_cast<SoFCSelectionRoot*>(node)->selectionStyle.getValue() == SoFCSelectionRoot::Box)
bbox = true;
break;
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/Gui/SoFCUnifiedSelection.h
Expand Up @@ -249,6 +249,8 @@ class GuiExport SoFCSwitch : public SoSwitch {
public:
/// Stores the child index used in switching override mode
SoSFInt32 defaultChild;
/// Stores the child index that will be traversed as long as the switch index is not -1
SoSFInt32 tailChild;

enum OverrideSwitch {
/// No switch override
Expand All @@ -275,6 +277,7 @@ class GuiExport SoFCSwitch : public SoSwitch {
virtual void callback(SoCallbackAction *action);
virtual void pick(SoPickAction *action);
virtual void handleEvent(SoHandleEventAction *action);
virtual void notify(SoNotList * nl);

/// Enables switching override for the give action
static void switchOverride(SoAction *action, OverrideSwitch o=OverrideDefault);
Expand All @@ -300,6 +303,10 @@ class GuiExport SoFCSwitch : public SoSwitch {
void setBBoxCallback(F f) {
cb = f;
}

private:
void traverseTail(SoAction *action, int idx);

private:
std::function<void(void)> cb;
};
Expand Down
25 changes: 18 additions & 7 deletions src/Gui/ViewProviderGeoFeatureGroupExtension.cpp
Expand Up @@ -95,14 +95,27 @@ void ViewProviderGeoFeatureGroupExtension::extensionAttach(App::DocumentObject*
}

bool ViewProviderGeoFeatureGroupExtension::extensionHandleChildren3D(
const std::vector<App::DocumentObject*> &children)
const std::vector<App::DocumentObject*> &)
{
getExtendedViewProvider();
if(linkView) {
linkView->setChildren(children);
buildChildren3D();
return true;
}
return false;
}

void ViewProviderGeoFeatureGroupExtension::buildChildren3D() {
if(!linkView)
return;

auto children = getExtendedViewProvider()->claimChildren3D();
for(auto it=children.begin();it!=children.end();) {
if(App::GroupExtension::getGroupOfObject(*it))
it = children.erase(it);
else
++it;
}
linkView->setChildren(children);
}

bool ViewProviderGeoFeatureGroupExtension::extensionGetElementPicked(
Expand Down Expand Up @@ -159,10 +172,8 @@ void ViewProviderGeoFeatureGroupExtension::extensionUpdateData(const App::Proper
ext->checkParentGroup();
plainGroupConns.push_back(
ext->Group.signalChanged.connect([=](const App::Property &){
auto owner = this->getExtendedViewProvider();
if(owner && this->linkView)
this->linkView->setChildren(owner->claimChildren3D());
}));
this->buildChildren3D();
}));
}
}
} else if(prop == &group->placement())
Expand Down
1 change: 1 addition & 0 deletions src/Gui/ViewProviderGeoFeatureGroupExtension.h
Expand Up @@ -69,6 +69,7 @@ class GuiExport ViewProviderGeoFeatureGroupExtension : public ViewProviderGroupE

protected:
void buildExport() const;
void buildChildren3D();

protected:
SoGroup *pcGroupChildren;
Expand Down
85 changes: 58 additions & 27 deletions src/Gui/ViewProviderLink.cpp
Expand Up @@ -125,7 +125,7 @@ class Gui::LinkInfo {
SoNodeSensor transformSensor;

std::array<CoinPtr<SoSeparator>,LinkView::SnapshotMax> pcSnapshots;
std::array<CoinPtr<SoSwitch>,LinkView::SnapshotMax> pcSwitches;
std::array<CoinPtr<SoFCSwitch>,LinkView::SnapshotMax> pcSwitches;
CoinPtr<SoSwitch> pcLinkedSwitch;

// for group type view providers
Expand Down Expand Up @@ -289,13 +289,10 @@ class Gui::LinkInfo {
if(!pcSwitches[i] || (node && node!=pcSwitches[i]))
continue;

if(pcSwitches[i]->isOfType(SoFCSwitch::getClassTypeId())) {
auto node = static_cast<SoFCSwitch*>(pcSwitches[i].get());
if(node->defaultChild.getValue() != defIndex)
node->defaultChild.setValue(defIndex);
if(node->overrideSwitch.getValue() != overrideSwitch)
node->overrideSwitch.setValue(overrideSwitch);
}
if(pcSwitches[i]->defaultChild.getValue() != defIndex)
pcSwitches[i]->defaultChild.setValue(defIndex);
if(pcSwitches[i]->overrideSwitch.getValue() != overrideSwitch)
pcSwitches[i]->overrideSwitch.setValue(overrideSwitch);

int count = pcSwitches[i]->getNumChildren();
if((!pcLinked->Visibility.getValue() && i==LinkView::SnapshotChild) || !count)
Expand Down Expand Up @@ -402,6 +399,13 @@ class Gui::LinkInfo {
pcModeSwitch = new SoFCSwitch;
}

if(pcSnapshot->isOfType(SoFCSelectionRoot::getClassTypeId())
&& root->isOfType(SoFCSelectionRoot::getClassTypeId()))
{
static_cast<SoFCSelectionRoot*>(pcSnapshot.get())->selectionStyle =
static_cast<SoFCSelectionRoot*>(root)->selectionStyle.getValue();
}

pcLinkedSwitch.reset();

coinRemoveAllChildren(pcSnapshot);
Expand Down Expand Up @@ -452,8 +456,11 @@ class Gui::LinkInfo {
else
pcModeSwitch->addChild(child);
}
if(pcChildGroup && !childRoot)
if(pcChildGroup && !childRoot) {
pcModeSwitch->addChild(pcChildGroup);
if(type == LinkView::SnapshotChild)
pcModeSwitch->tailChild = pcModeSwitch->getNumChildren()-1;
}
}
updateSwitch(pcUpdateSwitch);
return pcSnapshot;
Expand Down Expand Up @@ -491,9 +498,7 @@ class Gui::LinkInfo {
void updateChildren() {
if(isLinked()) {
if(!pcLinked->getChildRoot()) {
if(pcLinked->getObject()->hasExtension(
App::GroupExtension::getExtensionClassTypeId(),false))
{
if(App::GeoFeatureGroupExtension::isNonGeoGroup(pcLinked->getObject())) {
childSensor.detach();
_updateChildren(pcLinked->claimChildren());
return;
Expand Down Expand Up @@ -615,10 +620,7 @@ class Gui::LinkInfo {

if(path){
appendPath(path,pcChildGroup);
if(pcLinked->getChildRoot())
type = LinkView::SnapshotChild;
else
type = LinkView::SnapshotVisible;
type = LinkView::SnapshotChild;
}

// Special handling of nodes with childRoot, especially geo feature
Expand Down Expand Up @@ -940,22 +942,44 @@ class LinkView::Element : public LinkOwner {
else
coinRemoveAllChildren(pcSwitch);

if(isGroup && linkInfo->pcLinked->getDefaultMode()>=0)
isGroup = false;

if(!isGroup)
pcRoot = linkInfo->getSnapshot(nodeType);
else {
if(!pcRoot)
pcRoot = new SoFCSelectionRoot(true);
else
coinRemoveAllChildren(pcRoot);
auto groupSep = linkInfo->pcLinked->getRoot();
if(pcRoot->isOfType(SoFCSelectionRoot::getClassTypeId())
&& groupSep->isOfType(SoFCSelectionRoot::getClassTypeId()))
{
auto groot = static_cast<SoFCSelectionRoot*>(groupSep);
auto root = static_cast<SoFCSelectionRoot*>(pcRoot.get());
root->selectionStyle.disconnect();
root->selectionStyle.connectFrom(&groot->selectionStyle);
}
pcRoot->setName(obj->getFullName().c_str());
}
pcSwitch->addChild(pcRoot);
pcSwitch->whichChild = 0;
}

SoNode *initGroup() {
if(!isGroup)
return 0;
coinRemoveAllChildren(pcRoot);

// In case the plain group has its own display mode, we add it as the
// first child.
if(isLinked() && linkInfo->pcLinked->getDefaultMode()>=0) {
nodeType = SnapshotVisible;
auto node = linkInfo->getSnapshot(nodeType);
pcRoot->addChild(node);
return node;
}
return 0;
}

bool isLinked() const{
return linkInfo && linkInfo->isLinked();
}
Expand Down Expand Up @@ -1212,7 +1236,7 @@ void LinkView::setSize(int _size) {
nodeArray.push_back(std::unique_ptr<Element>(new Element(*this)));
auto &info = *nodeArray.back();
info.pcTransform = new SoTransform;
info.pcSwitch = new SoSwitch;
info.pcSwitch = new SoFCSwitch;
info.pcRoot = new SoFCSelectionRoot;
info.pcRoot->addChild(info.pcTransform);
info.pcSwitch->addChild(info.pcRoot);
Expand Down Expand Up @@ -1261,10 +1285,10 @@ void LinkView::setChildren(const std::vector<App::DocumentObject*> &children,
resetRoot();

if(childType<0 || childType!=type) {
nameMap.clear();
nodeMap.clear();
nodeArray.clear();
}
nameMap.clear();
nodeMap.clear();
childType = type;

if(nodeArray.size() > children.size())
Expand All @@ -1280,14 +1304,15 @@ void LinkView::setChildren(const std::vector<App::DocumentObject*> &children,
auto &info = *nodeArray[i];
info.groupIndex = -1;
info.link(obj);
if(info.pcSwitch)
if(info.pcSwitch && childType!=SnapshotChild)
info.pcSwitch->whichChild = (vis.size()<=i||vis[i])?0:-1;
if(info.isGroup) {
coinRemoveAllChildren(info.pcRoot);
auto node = info.initGroup();
if(node)
nodeMap[node] = i;
groups.emplace(obj,i);
}
}
nodeMap.clear();
for(size_t i=0;i<nodeArray.size();++i) {
auto &info = *nodeArray[i];
if(!info.isLinked())
Expand Down Expand Up @@ -1332,7 +1357,7 @@ void LinkView::setTransform(int index, const Base::Matrix4D &mat) {

void LinkView::setElementVisible(int idx, bool visible) {
if(idx>=0 && idx<(int)nodeArray.size()) {
if(nodeArray[idx]->pcSwitch)
if(nodeArray[idx]->pcSwitch && nodeArray[idx]->nodeType!=SnapshotChild)
nodeArray[idx]->pcSwitch->whichChild = visible?0:-1;
}
}
Expand Down Expand Up @@ -1528,6 +1553,12 @@ bool LinkView::linkGetElementPicked(const SoPickedPoint *pp, std::string &subnam
auto iter = nodeMap.find(path->getNode(idx));
if(iter == nodeMap.end())
return false;
if(nodeIdx == iter->second) {
// In case the plain group has its own mode, we'll insert a
// snapshot as the first child. So it is possible for the
// nodeMap points to the group itself.
break;
}
nodeIdx = iter->second;
}
auto &info = *nodeArray[nodeIdx];
Expand All @@ -1536,7 +1567,7 @@ bool LinkView::linkGetElementPicked(const SoPickedPoint *pp, std::string &subnam
else
ss << info.linkInfo->getLinkedName() << '.';
if(info.isLinked()) {
if(!info.linkInfo->getElementPicked(false,childType,pp,ss))
if(!info.linkInfo->getElementPicked(false,info.nodeType,pp,ss))
return false;
subname = ss.str();
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Arch/ArchBuildingPart.py
Expand Up @@ -582,7 +582,7 @@ def attach(self,vobj):
self.Object = vobj.Object
self.clip = None
from pivy import coin
self.sep = coin.SoGroup()
self.sep = coin.SoSeparator()
self.mat = coin.SoMaterial()
self.sep.addChild(self.mat)
self.dst = coin.SoDrawStyle()
Expand Down

0 comments on commit 88174b7

Please sign in to comment.