Skip to content

Commit

Permalink
Merge branch 'selectionfocus'
Browse files Browse the repository at this point in the history
# Conflicts:
#	libs/render/RenderableCollectorBase.h
  • Loading branch information
codereader committed Nov 5, 2022
2 parents 7029b15 + a12adf2 commit 18dca55
Show file tree
Hide file tree
Showing 79 changed files with 2,830 additions and 536 deletions.
14 changes: 14 additions & 0 deletions include/inode.h
Expand Up @@ -145,6 +145,20 @@ class INode :
// Returns true if this node supports the given state flag
virtual bool supportsStateFlag(unsigned int state) const = 0;

// Defines the active/inactive state of a node
// An inactive node might be rendered differently
enum class RenderState
{
Active,
Inactive
};

// Returns the current render state of this node
virtual RenderState getRenderState() const = 0;

// Sets the render state of this node
virtual void setRenderState(RenderState state) = 0;

/** greebo: Returns true, if the node is not hidden by
* exclusion, filtering or anything else.
*/
Expand Down
3 changes: 3 additions & 0 deletions include/irender.h
Expand Up @@ -497,6 +497,9 @@ enum class BuiltInShaderType
OrthoMergeActionOverlayRemove,
OrthoMergeActionOverlayChange,
OrthoMergeActionOverlayConflict,

// Highly transparent wire shader for inactive nodes
WireframeInactive,
};

// Available types of colour shaders. These areused
Expand Down
41 changes: 28 additions & 13 deletions include/iselection.h
Expand Up @@ -2,7 +2,6 @@

#include <cstddef>
#include "imodule.h"
#include "ivolumetest.h"
#include <memory>
#include <sigc++/signal.h>
#include "imanipulator.h"
Expand Down Expand Up @@ -49,6 +48,16 @@ namespace selection
Edge,
Face,
};

// The selection strategy determining the scene objects chosen for selection tests
enum class SelectionMode
{
Entity, // Entities only
Primitive, // Primitives (no components), entities take precedence
GroupPart, // Child Primitives of non-worldspawn entities
Component, // Components
MergeAction, // Merge Action nodes only
};
}

namespace selection
Expand All @@ -65,15 +74,6 @@ class SelectionSystem :
eCycle, // This is active if the mouse STAYS at the same position and Alt-Shift is held
};

enum EMode
{
eEntity,
ePrimitive,
eGroupPart,
eComponent,
eMergeAction,
};

/** greebo: An SelectionSystem::Observer gets notified
* as soon as the selection is changed.
*/
Expand Down Expand Up @@ -107,12 +107,13 @@ class SelectionSystem :

virtual const SelectionInfo& getSelectionInfo() = 0;

virtual void SetMode(EMode mode) = 0;
virtual EMode Mode() const = 0;
virtual void setSelectionMode(SelectionMode mode) = 0;
virtual SelectionMode getSelectionMode() const = 0;

virtual void SetComponentMode(ComponentSelectionMode mode) = 0;
virtual ComponentSelectionMode ComponentMode() const = 0;

virtual sigc::signal<void, EMode>& signal_selectionModeChanged() = 0;
virtual sigc::signal<void, SelectionMode>& signal_selectionModeChanged() = 0;
virtual sigc::signal<void, ComponentSelectionMode>& signal_componentModeChanged() = 0;

virtual std::size_t countSelected() const = 0;
Expand Down Expand Up @@ -228,6 +229,20 @@ class SelectionSystem :

// Returns the center point of the current selection
virtual Vector3 getCurrentSelectionCenter() = 0;

// Toggles selection focus mode (only possible with a non-empty selection)
// After activating, only items that are part of the set can be selected and manipulated.
// Throws cmd::ExecutionNotPossible when trying to activate with an empty selection
virtual void toggleSelectionFocus() = 0;

// Returns true when focus mode is active
// In focus mode only certain elements in the map can be selected.
// It's also possible to select single parts of selection groups
// without disbanding the group.
virtual bool selectionFocusIsActive() = 0;

// Returns the volume the focus items are occupying
virtual AABB getSelectionFocusBounds() = 0;
};

}
Expand Down
58 changes: 58 additions & 0 deletions include/iselectiontest.h
Expand Up @@ -271,6 +271,12 @@ class Selector
*/
virtual void addIntersection(const SelectionIntersection& intersection) = 0;

// Returns true if no selectable has been chosen
virtual bool empty() const = 0;

// Iterate over every selectable in the pool
virtual void foreachSelectable(const std::function<void(ISelectable*)>& functor) = 0;

/// Add a selectable object and immediately commit it with a null intersection
void addWithNullIntersection(ISelectable& selectable)
{
Expand Down Expand Up @@ -337,3 +343,55 @@ typedef std::shared_ptr<PlaneSelectable> PlaneSelectablePtr;
inline PlaneSelectablePtr Node_getPlaneSelectable(const scene::INodePtr& node) {
return std::dynamic_pointer_cast<PlaneSelectable>(node);
}

namespace selection
{

/**
* Interface of a scene walker that can be used to test
* some or all nodes of the scene for selection.
*
* All qualified scene nodes are tested for selection and
* stored internally. Use the foreachSelectable() method
* to iterate over the selectables.
*/
class ISceneSelectionTester
{
public:
using Ptr = std::shared_ptr<ISceneSelectionTester>;

virtual ~ISceneSelectionTester() {}

// Tests all qualified nodes in the scene for selection
// and stores the ones passing the test internally
virtual void testSelectScene(const VolumeTest& view, SelectionTest& test) = 0;

// Tests all qualified nodes in the scene for selection
// all passing selectables are stored internally if they pass the given predicate
virtual void testSelectSceneWithFilter(const VolumeTest& view, SelectionTest& test,
const std::function<bool(ISelectable*)>& predicate) = 0;

// Returns true if the tester found one or more selectables passing the test
virtual bool hasSelectables() const = 0;

// Iterates over the selectables that were passing the test
virtual void foreachSelectable(const std::function<void(ISelectable*)>& functor) = 0;
};

/**
* Factory interface used to acquire ISceneSelectionTester
* instances suitable for a given purpose.
*/
class ISceneSelectionTesterFactory
{
public:
virtual ~ISceneSelectionTesterFactory() {}

/**
* Returns an instance of a selection tester suitable for testing
* scene nodes according to the given purpose/selection mode.
*/
virtual ISceneSelectionTester::Ptr createSceneSelectionTester(SelectionMode mode) = 0;
};

} // namespace
16 changes: 9 additions & 7 deletions include/ui/ieventmanager.h
@@ -1,13 +1,10 @@
#pragma once

#include <list>
#include <map>
#include <string>

#include <memory>
#include <functional>

#include "imodule.h"
#include <functional>

class wxWindow;
class wxMenuItem;
Expand Down Expand Up @@ -38,6 +35,8 @@ namespace ui
class IAccelerator
{
public:
using Ptr = std::shared_ptr<IAccelerator>;

// destructor
virtual ~IAccelerator() {}

Expand Down Expand Up @@ -107,7 +106,7 @@ class IEventVisitor
virtual void visit(const std::string& eventName, const IAccelerator& accel) = 0;
};

const char* const MODULE_EVENTMANAGER("EventManager");
constexpr const char* const MODULE_EVENTMANAGER("EventManager");

// The function object invoked when a ToggleEvent is changing states
// The passed boolean indicates the new toggle state (true = active/toggled)
Expand Down Expand Up @@ -172,6 +171,10 @@ class IEventManager :
// Disconnects the given command from any accelerators
virtual void disconnectAccelerator(const std::string& command) = 0;

// Returns the accelerator that is bound to the given event (name)
// Returns an empty reference if either event or accelerator were not found.
virtual IAccelerator::Ptr findAcceleratorForEvent(const std::string& eventName) = 0;

// Register the given menu item with the given command. The event manager updates this item
// when the accelerator association changes
virtual void registerMenuItem(const std::string& eventName, wxMenuItem* item) = 0;
Expand Down Expand Up @@ -200,9 +203,8 @@ class IEventManager :
*/
virtual std::string getEventStr(wxKeyEvent& ev) = 0;
};
typedef std::shared_ptr<IEventManager> IEventManagerPtr;

// This is the accessor for the event manager
// Global accessor for the event manager
inline IEventManager& GlobalEventManager()
{
static module::InstanceReference<IEventManager> _reference(MODULE_EVENTMANAGER);
Expand Down
1 change: 1 addition & 0 deletions install/input.xml
Expand Up @@ -152,6 +152,7 @@
<shortcut command="DragVertices" key="V" />
<shortcut command="DragEdges" key="E" />
<shortcut command="DragFaces" key="F" />
<shortcut command="ToggleSelectionFocus" key="F" modifiers="CONTROL" />
<shortcut command="ThickenPatchDialog" key="T" modifiers="CONTROL" />
<shortcut command="ToggleShowAllLightRadii" key="F" modifiers="CONTROL+SHIFT+ALT" />
<shortcut command="ToggleClipper" key="X" />
Expand Down
1 change: 0 additions & 1 deletion install/user.xml
Expand Up @@ -67,7 +67,6 @@
<defaultPivotLocationIgnoresLightVolumes value="1" />
<selectionEpsilon value="8.0" />
<dragResizeEntitiesSymmetrically value="1" />
<transientComponentSelection value="1" />
<offsetClonedObjects value="1" />
<manipulatorFontSize value="14" />
<manipulatorFontStyle value="Sans" />
Expand Down
2 changes: 0 additions & 2 deletions libs/render/RenderableCollectionWalker.h
@@ -1,8 +1,6 @@
#pragma once

#include "iselection.h"
#include "iscenegraph.h"
#include <functional>
#include "render/RenderableCollectorBase.h"

namespace render
Expand Down
8 changes: 4 additions & 4 deletions libs/render/RenderableCollectorBase.h
Expand Up @@ -26,7 +26,7 @@ class RenderableCollectorBase :
_flags(Highlight::Flags::NoHighlight)
{}

virtual ~RenderableCollectorBase()
~RenderableCollectorBase() override
{}

bool hasHighlightFlags() const override
Expand Down Expand Up @@ -56,9 +56,9 @@ class RenderableCollectorBase :
node->onPreRender(volume);

// greebo: Highlighting propagates to child nodes
scene::INodePtr parent = node->getParent();
auto parent = node->getParent();

std::size_t highlightFlags = node->getHighlightFlags();
auto highlightFlags = node->getHighlightFlags();

auto nodeType = node->getNodeType();

Expand Down Expand Up @@ -122,7 +122,7 @@ class RenderableCollectorBase :

if (highlightFlags & Renderable::Highlight::Selected)
{
if (GlobalSelectionSystem().Mode() != selection::SelectionSystem::eComponent)
if (GlobalSelectionSystem().getSelectionMode() != selection::SelectionMode::Component)
{
setHighlightFlag(Highlight::Faces, true);
}
Expand Down
9 changes: 5 additions & 4 deletions libs/scene/Group.h
@@ -1,5 +1,6 @@
#pragma once

#include "i18n.h"
#include "imap.h"
#include "iundo.h"
#include "iselection.h"
Expand Down Expand Up @@ -34,8 +35,8 @@ inline void checkGroupSelectedAvailable()
throw cmd::ExecutionNotPossible(_("No map loaded"));
}

if (GlobalSelectionSystem().Mode() != SelectionSystem::ePrimitive &&
GlobalSelectionSystem().Mode() != SelectionSystem::eGroupPart)
if (GlobalSelectionSystem().getSelectionMode() != SelectionMode::Primitive &&
GlobalSelectionSystem().getSelectionMode() != SelectionMode::GroupPart)
{
throw cmd::ExecutionNotPossible(_("Groups can be formed in Primitive and Group Part selection mode only"));
}
Expand Down Expand Up @@ -109,8 +110,8 @@ inline void checkUngroupSelectedAvailable()
throw cmd::ExecutionNotPossible(_("No map loaded"));
}

if (GlobalSelectionSystem().Mode() != SelectionSystem::ePrimitive &&
GlobalSelectionSystem().Mode() != SelectionSystem::eGroupPart)
if (GlobalSelectionSystem().getSelectionMode() != SelectionMode::Primitive &&
GlobalSelectionSystem().getSelectionMode() != SelectionMode::GroupPart)
{
throw cmd::ExecutionNotPossible(_("Groups can be dissolved in Primitive and Group Part selection mode only"));
}
Expand Down
20 changes: 18 additions & 2 deletions libs/scene/Node.cpp
Expand Up @@ -23,7 +23,8 @@ Node::Node() :
_local2world(Matrix4::getIdentity()),
_instantiated(false),
_forceVisible(false),
_renderEntity(nullptr)
_renderEntity(nullptr),
_renderState(RenderState::Active)
{
// Each node is part of layer 0 by default
_layers.insert(0);
Expand All @@ -43,7 +44,8 @@ Node::Node(const Node& other) :
_instantiated(false),
_forceVisible(false),
_layers(other._layers),
_renderEntity(other._renderEntity)
_renderEntity(other._renderEntity),
_renderState(other._renderState)
{}

scene::INodePtr Node::getSelf()
Expand Down Expand Up @@ -539,6 +541,20 @@ bool Node::isForcedVisible() const
return _forceVisible;
}

INode::RenderState Node::getRenderState() const
{
return _renderState;
}

void Node::setRenderState(RenderState state)
{
if (state != _renderState)
{
_renderState = state;
onRenderStateChanged();
}
}

unsigned long Node::_maxNodeId = 0;

} // namespace scene

0 comments on commit 18dca55

Please sign in to comment.