*/
#include "selection.h"
+#include "globaldefs.h"
#include "debugging/debugging.h"
}
-#if defined( _DEBUG )
+#if GDEF_DEBUG
class test_quat
{
public:
class Rotatable
{
public:
+virtual ~Rotatable() = default;
virtual void rotate( const Quaternion& rotation ) = 0;
};
class Translatable
{
public:
+virtual ~Translatable() = default;
virtual void translate( const Vector3& translation ) = 0;
};
}
};
+void GetSelectionAABB( AABB& bounds );
+const Matrix4& ssGetPivot2World();
class Scalable
{
public:
+virtual ~Scalable() = default;
virtual void scale( const Vector3& scaling ) = 0;
};
Vector3 m_start;
Vector3 m_axis;
Scalable& m_scalable;
+
+Vector3 m_choosen_extent;
+
public:
ScaleAxis( Scalable& scalable )
: m_scalable( scalable ){
}
void Construct( const Matrix4& device2manip, const float x, const float y ){
point_on_axis( m_start, m_axis, device2manip, x, y );
+
+ AABB aabb;
+ GetSelectionAABB( aabb );
+ Vector3 transform_origin = vector4_to_vector3( ssGetPivot2World().t() );
+ m_choosen_extent = Vector3( std::max( aabb.origin[0] + aabb.extents[0] - transform_origin[0], - aabb.origin[0] + aabb.extents[0] + transform_origin[0] ),
+ std::max( aabb.origin[1] + aabb.extents[1] - transform_origin[1], - aabb.origin[1] + aabb.extents[1] + transform_origin[1] ),
+ std::max( aabb.origin[2] + aabb.extents[2] - transform_origin[2], - aabb.origin[2] + aabb.extents[2] + transform_origin[2] )
+ );
+
}
void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){
+ //globalOutputStream() << "manip2object: " << manip2object << " device2manip: " << device2manip << " x: " << x << " y:" << y <<"\n";
Vector3 current;
point_on_axis( current, m_axis, device2manip, x, y );
Vector3 delta = vector3_subtracted( current, m_start );
vector3_snap( delta, GetSnapGridSize() );
Vector3 start( vector3_snapped( m_start, GetSnapGridSize() ) );
+ //globalOutputStream() << "start: " << start << " delta: " << delta <<"\n";
Vector3 scale(
start[0] == 0 ? 1 : 1 + delta[0] / start[0],
start[1] == 0 ? 1 : 1 + delta[1] / start[1],
start[2] == 0 ? 1 : 1 + delta[2] / start[2]
);
+
+ for( std::size_t i = 0; i < 3; i++ ){
+ if( m_choosen_extent[i] > 0.0625 ){ //epsilon to prevent too high scale for set of models, having really small extent, formed by origins
+ scale[i] = ( m_choosen_extent[i] + delta[i] ) / m_choosen_extent[i];
+ }
+ }
+
m_scalable.scale( scale );
}
private:
Vector3 m_start;
Scalable& m_scalable;
+
+Vector3 m_choosen_extent;
+
public:
ScaleFree( Scalable& scalable )
: m_scalable( scalable ){
}
void Construct( const Matrix4& device2manip, const float x, const float y ){
point_on_plane( m_start, device2manip, x, y );
+
+ AABB aabb;
+ GetSelectionAABB( aabb );
+ Vector3 transform_origin = vector4_to_vector3( ssGetPivot2World().t() );
+ m_choosen_extent = Vector3( std::max( aabb.origin[0] + aabb.extents[0] - transform_origin[0], - aabb.origin[0] + aabb.extents[0] + transform_origin[0] ),
+ std::max( aabb.origin[1] + aabb.extents[1] - transform_origin[1], - aabb.origin[1] + aabb.extents[1] + transform_origin[1] ),
+ std::max( aabb.origin[2] + aabb.extents[2] - transform_origin[2], - aabb.origin[2] + aabb.extents[2] + transform_origin[2] )
+ );
}
void Transform( const Matrix4& manip2object, const Matrix4& device2manip, const float x, const float y ){
Vector3 current;
start[1] == 0 ? 1 : 1 + delta[1] / start[1],
start[2] == 0 ? 1 : 1 + delta[2] / start[2]
);
+
+ for( std::size_t i = 0; i < 3; i++ ){
+ if( m_choosen_extent[i] > 0.0625 ){
+ scale[i] = ( m_choosen_extent[i] + delta[i] ) / m_choosen_extent[i];
+ }
+ }
+
m_scalable.scale( scale );
}
};
}
};
-#if defined( _DEBUG )
+#if GDEF_DEBUG
#define DEBUG_SELECTION
#endif
bool contains( const Plane3& plane ) const {
return PlaneSet_contains( m_selectedPlanes, plane );
}
-typedef MemberCaller1<SelectedPlaneSet, const Plane3&, &SelectedPlaneSet::insert> InsertCaller;
+typedef MemberCaller<SelectedPlaneSet, void(const Plane3&), &SelectedPlaneSet::insert> InsertCaller;
};
class SelectionCounter
{
public:
-typedef const Selectable& first_argument_type;
+using func = void(const Selectable &);
SelectionCounter( const SelectionChangeCallback& onchanged )
: m_count( 0 ), m_onchanged( onchanged ){
Scale m_scale;
public:
static Shader* m_state;
+bool m_bPreferPointEntsIn2D;
private:
EManipulatorMode m_manipulator_mode;
Manipulator* m_manipulator;
Signal1<const Selectable&> m_selectionChanged_callbacks;
void ConstructPivot() const;
+void setCustomPivotOrigin( Vector3& point ) const;
+public:
+void getSelectionAABB( AABB& bounds ) const;
+private:
mutable bool m_pivotChanged;
bool m_pivot_moving;
+mutable bool m_pivotIsCustom;
void Scene_TestSelect( Selector& selector, SelectionTest& test, const View& view, SelectionSystem::EMode mode, SelectionSystem::EComponentMode componentMode );
eToggle,
eReplace,
eCycle,
+ eSelect,
+ eDeselect,
};
RadiantSelectionSystem() :
+ m_bPreferPointEntsIn2D( true ),
m_undo_begun( false ),
m_mode( ePrimitive ),
m_componentmode( eDefault ),
m_rotate_manipulator( *this, 8, 64 ),
m_scale_manipulator( *this, 0, 64 ),
m_pivotChanged( false ),
- m_pivot_moving( false ){
+ m_pivot_moving( false ),
+ m_pivotIsCustom( false ){
SetManipulatorMode( eTranslate );
pivotChanged();
addSelectionChangeCallback( PivotChangedSelectionCaller( *this ) );
m_pivotChanged = true;
SceneChangeNotify();
}
-typedef ConstMemberCaller<RadiantSelectionSystem, &RadiantSelectionSystem::pivotChanged> PivotChangedCaller;
+typedef ConstMemberCaller<RadiantSelectionSystem, void(), &RadiantSelectionSystem::pivotChanged> PivotChangedCaller;
void pivotChangedSelection( const Selectable& selectable ){
pivotChanged();
}
-typedef MemberCaller1<RadiantSelectionSystem, const Selectable&, &RadiantSelectionSystem::pivotChangedSelection> PivotChangedSelectionCaller;
+typedef MemberCaller<RadiantSelectionSystem, void(const Selectable&), &RadiantSelectionSystem::pivotChangedSelection> PivotChangedSelectionCaller;
void SetMode( EMode mode ){
if ( m_mode != mode ) {
return m_componentmode;
}
void SetManipulatorMode( EManipulatorMode mode ){
+ m_pivotIsCustom = false;
m_manipulator_mode = mode;
switch ( m_manipulator_mode )
{
SelectionChangeCallback getObserver( EMode mode ){
if ( mode == ePrimitive ) {
- return makeCallback1( m_count_primitive );
+ return makeCallback( m_count_primitive );
}
else
{
- return makeCallback1( m_count_component );
+ return makeCallback( m_count_component );
}
}
std::size_t countSelected() const {
void selectionChanged( const Selectable& selectable ){
m_selectionChanged_callbacks( selectable );
}
-typedef MemberCaller1<RadiantSelectionSystem, const Selectable&, &RadiantSelectionSystem::selectionChanged> SelectionChangedCaller;
+typedef MemberCaller<RadiantSelectionSystem, void(const Selectable&), &RadiantSelectionSystem::selectionChanged> SelectionChangedCaller;
void startMove(){
}
}
+void deselectComponentsOrAll( bool components ){
+ if ( components ) {
+ setSelectedAllComponents( false );
+ }
+ else
+ {
+ deselectAll();
+ }
+}
+
void SelectPoint( const View& view, const float device_point[2], const float device_epsilon[2], RadiantSelectionSystem::EModifier modifier, bool face ){
+ //globalOutputStream() << device_point[0] << " " << device_point[1] << "\n";
ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" );
+
if ( modifier == eReplace ) {
- if ( face ) {
- setSelectedAllComponents( false );
- }
- else
- {
- deselectAll();
- }
+ deselectComponentsOrAll( face );
}
-
+/*
+//nothingSelected() doesn't consider faces, selected in non-component mode, m
+ if ( modifier == eCycle && nothingSelected() ){
+ modifier = eReplace;
+ }
+*/
#if defined ( DEBUG_SELECTION )
g_render_clipped.destroy();
#endif
SelectionVolume volume( scissored );
SelectionPool selector;
- if ( face ) {
- Scene_TestSelect_Component( selector, volume, scissored, eFace );
- }
- else
- {
- Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
- }
+ SelectionPool selector_point_ents;
+ const bool prefer_point_ents = m_bPreferPointEntsIn2D && Mode() == ePrimitive && !view.fill() && !face
+ && ( modifier == RadiantSelectionSystem::eReplace || modifier == RadiantSelectionSystem::eSelect || modifier == RadiantSelectionSystem::eDeselect );
- if ( !selector.failed() ) {
+ if( prefer_point_ents ){
+ Scene_TestSelect( selector_point_ents, volume, scissored, eEntity, ComponentMode() );
+ }
+ if( prefer_point_ents && !selector_point_ents.failed() ){
switch ( modifier )
{
- case RadiantSelectionSystem::eToggle:
- {
- SelectableSortedSet::iterator best = selector.begin();
- // toggle selection of the object with least depth
- if ( ( *best ).second->isSelected() ) {
- ( *best ).second->setSelected( false );
- }
- else{
- ( *best ).second->setSelected( true );
- }
- }
- break;
// if cycle mode not enabled, enable it
case RadiantSelectionSystem::eReplace:
{
// select closest
- ( *selector.begin() ).second->setSelected( true );
+ ( *selector_point_ents.begin() ).second->setSelected( true );
}
break;
- // select the next object in the list from the one already selected
- case RadiantSelectionSystem::eCycle:
+ case RadiantSelectionSystem::eSelect:
{
- SelectionPool::iterator i = selector.begin();
- while ( i != selector.end() )
+ SelectionPool::iterator best = selector_point_ents.begin();
+ if( !( *best ).second->isSelected() ){
+ ( *best ).second->setSelected( true );
+ }
+ SelectionPool::iterator i = best;
+ ++i;
+ while ( i != selector_point_ents.end() )
{
- if ( ( *i ).second->isSelected() ) {
- ( *i ).second->setSelected( false );
- ++i;
- if ( i != selector.end() ) {
- i->second->setSelected( true );
+ if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
+ if( !( *i ).second->isSelected() ){
+ ( *i ).second->setSelected( true );
}
- else
- {
- selector.begin()->second->setSelected( true );
+ }
+ else{
+ break;
+ }
+ ++i;
+ }
+ }
+ break;
+ case RadiantSelectionSystem::eDeselect:
+ {
+ SelectionPool::iterator best = selector_point_ents.begin();
+ if( ( *best ).second->isSelected() ){
+ ( *best ).second->setSelected( false );
+ }
+ SelectionPool::iterator i = best;
+ ++i;
+ while ( i != selector_point_ents.end() )
+ {
+ if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
+ if( ( *i ).second->isSelected() ){
+ ( *i ).second->setSelected( false );
}
+ }
+ else{
break;
}
++i;
break;
}
}
+ else{
+ if ( face ){
+ Scene_TestSelect_Component( selector, volume, scissored, eFace );
+ }
+ else{
+ Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
+ }
+
+ if ( !selector.failed() ) {
+ switch ( modifier )
+ {
+ case RadiantSelectionSystem::eToggle:
+ {
+ SelectableSortedSet::iterator best = selector.begin();
+ // toggle selection of the object with least depth
+ if ( ( *best ).second->isSelected() ) {
+ ( *best ).second->setSelected( false );
+ }
+ else{
+ ( *best ).second->setSelected( true );
+ }
+ }
+ break;
+ // if cycle mode not enabled, enable it
+ case RadiantSelectionSystem::eReplace:
+ {
+ // select closest
+ ( *selector.begin() ).second->setSelected( true );
+ }
+ break;
+ // select the next object in the list from the one already selected
+ case RadiantSelectionSystem::eCycle:
+ {
+ bool CycleSelectionOccured = false;
+ SelectionPool::iterator i = selector.begin();
+ while ( i != selector.end() )
+ {
+ if ( ( *i ).second->isSelected() ) {
+ deselectComponentsOrAll( face );
+ ++i;
+ if ( i != selector.end() ) {
+ i->second->setSelected( true );
+ }
+ else
+ {
+ selector.begin()->second->setSelected( true );
+ }
+ CycleSelectionOccured = true;
+ break;
+ }
+ ++i;
+ }
+ if( !CycleSelectionOccured ){
+ deselectComponentsOrAll( face );
+ ( *selector.begin() ).second->setSelected( true );
+ }
+ }
+ break;
+ case RadiantSelectionSystem::eSelect:
+ {
+ SelectionPool::iterator best = selector.begin();
+ if( !( *best ).second->isSelected() ){
+ ( *best ).second->setSelected( true );
+ }
+ SelectionPool::iterator i = best;
+ ++i;
+ while ( i != selector.end() )
+ {
+ if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
+ if( !( *i ).second->isSelected() ){
+ ( *i ).second->setSelected( true );
+ }
+ }
+ else{
+ break;
+ }
+ ++i;
+ }
+ }
+ break;
+ case RadiantSelectionSystem::eDeselect:
+ {
+ SelectionPool::iterator best = selector.begin();
+ if( ( *best ).second->isSelected() ){
+ ( *best ).second->setSelected( false );
+ }
+ SelectionPool::iterator i = best;
+ ++i;
+ while ( i != selector.end() )
+ {
+ if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
+ if( ( *i ).second->isSelected() ){
+ ( *i ).second->setSelected( false );
+ }
+ }
+ else{
+ break;
+ }
+ ++i;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if( modifier == eCycle ){
+ deselectComponentsOrAll( face );
+ }
+ }
}
}
-void SelectArea( const View& view, const float device_point[2], const float device_delta[2], RadiantSelectionSystem::EModifier modifier, bool face ){
- if ( modifier == eReplace ) {
- if ( face ) {
- setSelectedAllComponents( false );
+bool SelectPoint_InitPaint( const View& view, const float device_point[2], const float device_epsilon[2], bool face ){
+ ASSERT_MESSAGE( fabs( device_point[0] ) <= 1.0f && fabs( device_point[1] ) <= 1.0f, "point-selection error" );
+ #if defined ( DEBUG_SELECTION )
+ g_render_clipped.destroy();
+ #endif
+
+ {
+ View scissored( view );
+ ConstructSelectionTest( scissored, SelectionBoxForPoint( device_point, device_epsilon ) );
+
+ SelectionVolume volume( scissored );
+ SelectionPool selector;
+ SelectionPool selector_point_ents;
+ const bool prefer_point_ents = m_bPreferPointEntsIn2D && Mode() == ePrimitive && !view.fill() && !face;
+
+ if( prefer_point_ents ){
+ Scene_TestSelect( selector_point_ents, volume, scissored, eEntity, ComponentMode() );
}
- else
- {
- deselectAll();
+ if( prefer_point_ents && !selector_point_ents.failed() ){
+ SelectableSortedSet::iterator best = selector_point_ents.begin();
+ const bool wasSelected = ( *best ).second->isSelected();
+ ( *best ).second->setSelected( !wasSelected );
+ SelectableSortedSet::iterator i = best;
+ ++i;
+ while ( i != selector_point_ents.end() )
+ {
+ if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
+ ( *i ).second->setSelected( !wasSelected );
+ }
+ else{
+ break;
+ }
+ ++i;
+ }
+ return !wasSelected;
+ }
+ else{//do primitives, if ents failed
+ if ( face ){
+ Scene_TestSelect_Component( selector, volume, scissored, eFace );
+ }
+ else{
+ Scene_TestSelect( selector, volume, scissored, Mode(), ComponentMode() );
+ }
+ if ( !selector.failed() ){
+ SelectableSortedSet::iterator best = selector.begin();
+ const bool wasSelected = ( *best ).second->isSelected();
+ ( *best ).second->setSelected( !wasSelected );
+ SelectableSortedSet::iterator i = best;
+ ++i;
+ while ( i != selector.end() )
+ {
+ if( ( *i ).first.equalEpsilon( ( *best ).first, 0.25f, 0.000001f ) ){
+ ( *i ).second->setSelected( !wasSelected );
+ }
+ else{
+ break;
+ }
+ ++i;
+ }
+ return !wasSelected;
+ }
+ else{
+ return true;
+ }
}
}
+}
+
+void SelectArea( const View& view, const float device_point[2], const float device_delta[2], RadiantSelectionSystem::EModifier modifier, bool face ){
+ if ( modifier == eReplace ) {
+ deselectComponentsOrAll( face );
+ }
#if defined ( DEBUG_SELECTION )
g_render_clipped.destroy();
ostream << " -scale " << m_scale.x() << " " << m_scale.y() << " " << m_scale.z();
}
-void rotateSelected( const Quaternion& rotation ){
+void rotateSelected( const Quaternion& rotation, bool snapOrigin ){
+ if( snapOrigin && !m_pivotIsCustom ){
+ m_pivot2world.tx() = float_snapped( m_pivot2world.tx(), GetSnapGridSize() );
+ m_pivot2world.ty() = float_snapped( m_pivot2world.ty(), GetSnapGridSize() );
+ m_pivot2world.tz() = float_snapped( m_pivot2world.tz(), GetSnapGridSize() );
+ }
startMove();
rotate( rotation );
freezeTransforms();
}
}
-
+#include "map.h"
class testselect_entity_visible : public scene::Graph::Walker
{
: m_selector( selector ), m_test( test ){
}
bool pre( const scene::Path& path, scene::Instance& instance ) const {
+ if( path.top().get_pointer() == Map_GetWorldspawn( g_map ) ||
+ node_is_group( path.top().get() ) ){
+ return false;
+ }
Selectable* selectable = Instance_getSelectable( instance );
if ( selectable != 0
&& Node_isEntity( path.top() ) ) {
#endif
void RadiantSelectionSystem::ConstructPivot() const {
- if ( !m_pivotChanged || m_pivot_moving ) {
+ if ( !m_pivotChanged || m_pivot_moving || m_pivotIsCustom ) {
return;
}
m_pivotChanged = false;
m_object_pivot = bounds.origin;
}
- vector3_snap( m_object_pivot, GetSnapGridSize() );
+ //vector3_snap( m_object_pivot, GetSnapGridSize() );
+ //globalOutputStream() << m_object_pivot << "\n";
m_pivot2world = matrix4_translation_for_vec3( m_object_pivot );
switch ( m_manipulator_mode )
}
}
+void RadiantSelectionSystem::setCustomPivotOrigin( Vector3& point ) const {
+ /*if ( !m_pivotChanged || m_pivot_moving ) {
+ return;
+ }*/
+ //m_pivotChanged = false;
+
+ if ( !nothingSelected() && ( m_manipulator_mode == eTranslate || m_manipulator_mode == eRotate || m_manipulator_mode == eScale ) ) {
+ AABB bounds;
+ if ( Mode() == eComponent ) {
+ Scene_BoundsSelectedComponent( GlobalSceneGraph(), bounds );
+ }
+ else
+ {
+ Scene_BoundsSelected( GlobalSceneGraph(), bounds );
+ }
+ //globalOutputStream() << point << "\n";
+ const float gridsize = GetSnapGridSize();
+ //const float bbox_epsilon = gridsize / 4.0;
+
+ for( std::size_t i = 0; i < 3; i++ ){
+ if( point[i] < 900000 ){
+ float bestsnapDist = fabs( bounds.origin[i] - point[i] );
+ float bestsnapTo = bounds.origin[i];
+ float othersnapDist = fabs( bounds.origin[i] + bounds.extents[i] - point[i] );
+ if( othersnapDist < bestsnapDist ){
+ bestsnapDist = othersnapDist;
+ bestsnapTo = bounds.origin[i] + bounds.extents[i];
+ }
+ othersnapDist = fabs( bounds.origin[i] - bounds.extents[i] - point[i] );
+ if( othersnapDist < bestsnapDist ){
+ bestsnapDist = othersnapDist;
+ bestsnapTo = bounds.origin[i] - bounds.extents[i];
+ }
+ othersnapDist = fabs( float_snapped( point[i], gridsize ) - point[i] );
+ if( othersnapDist < bestsnapDist ){
+ bestsnapDist = othersnapDist;
+ bestsnapTo = float_snapped( point[i], gridsize );
+ }
+ point[i] = bestsnapTo;
+
+/* if( float_equal_epsilon( point[i], bestsnapTo, bbox_epsilon ) ){
+ point[i] = bestsnapTo;
+ }
+ else{
+ point[i] = float_snapped( point[i], gridsize );
+ }
+ */
+ m_pivot2world[i + 12] = point[i]; //m_pivot2world.tx() .ty() .tz()
+ }
+ }
+
+ switch ( m_manipulator_mode )
+ {
+ case eTranslate:
+ break;
+ case eRotate:
+ if ( Mode() == eComponent ) {
+ matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
+ }
+ else
+ {
+ matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
+ }
+ break;
+ case eScale:
+ if ( Mode() == eComponent ) {
+ matrix4_assign_rotation_for_pivot( m_pivot2world, m_component_selection.back() );
+ }
+ else
+ {
+ matrix4_assign_rotation_for_pivot( m_pivot2world, m_selection.back() );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ m_pivotIsCustom = true;
+}
+
+void RadiantSelectionSystem::getSelectionAABB( AABB& bounds ) const {
+ if ( !nothingSelected() ) {
+ if ( Mode() == eComponent ) {
+ Scene_BoundsSelectedComponent( GlobalSceneGraph(), bounds );
+ }
+ else
+ {
+ Scene_BoundsSelected( GlobalSceneGraph(), bounds );
+ }
+ }
+}
+
+void GetSelectionAABB( AABB& bounds ){
+ getSelectionSystem().getSelectionAABB( bounds );
+}
+
+const Matrix4& ssGetPivot2World(){
+ return getSelectionSystem().GetPivot2World();
+}
+
void RadiantSelectionSystem::renderSolid( Renderer& renderer, const VolumeTest& volume ) const {
//if(view->TestPoint(m_object_pivot))
if ( !nothingSelected() ) {
#endif
}
+#include "preferencesystem.h"
+#include "preferences.h"
+
+void SelectionSystem_constructPreferences( PreferencesPage& page ){
+ page.appendCheckBox( "", "Prefer point entities in 2D", getSelectionSystem().m_bPreferPointEntsIn2D );
+}
+void SelectionSystem_constructPage( PreferenceGroup& group ){
+ PreferencesPage page( group.createPage( "Selection", "Selection System Settings" ) );
+ SelectionSystem_constructPreferences( page );
+}
+void SelectionSystem_registerPreferencesPage(){
+ PreferencesDialog_addSettingsPage( FreeCaller<void(PreferenceGroup&), SelectionSystem_constructPage>() );
+}
+
+
void SelectionSystem_OnBoundsChanged(){
getSelectionSystem().pivotChanged();
}
-
SignalHandlerId SelectionSystem_boundsChanged;
void SelectionSystem_Construct(){
g_RadiantSelectionSystem = new RadiantSelectionSystem;
- SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( FreeCaller<SelectionSystem_OnBoundsChanged>() );
+ SelectionSystem_boundsChanged = GlobalSceneGraph().addBoundsChangedCallback( FreeCaller<void(), SelectionSystem_OnBoundsChanged>() );
GlobalShaderCache().attachRenderable( getSelectionSystem() );
+
+ GlobalPreferenceSystem().registerPreference( "PreferPointEntsIn2D", make_property_string( getSelectionSystem().m_bPreferPointEntsIn2D ) );
+ SelectionSystem_registerPreferencesPage();
}
void SelectionSystem_Destroy(){
return WindowVector( window_constrained( window.x(), x, width ), window_constrained( window.y(), y, height ) );
}
-typedef Callback1<DeviceVector> MouseEventCallback;
+typedef Callback<void(DeviceVector)> MouseEventCallback;
Single<MouseEventCallback> g_mouseMovedCallback;
Single<MouseEventCallback> g_mouseUpCallback;
#if 1
const ButtonIdentifier c_button_select = c_buttonLeft;
+const ButtonIdentifier c_button_select2 = c_buttonRight;
const ModifierFlags c_modifier_manipulator = c_modifierNone;
const ModifierFlags c_modifier_toggle = c_modifierShift;
const ModifierFlags c_modifier_replace = c_modifierShift | c_modifierAlt;
class Selector_
{
RadiantSelectionSystem::EModifier modifier_for_state( ModifierFlags state ){
- if ( state == c_modifier_toggle || state == c_modifier_toggle_face ) {
- return RadiantSelectionSystem::eToggle;
- }
- if ( state == c_modifier_replace || state == c_modifier_replace_face ) {
- return RadiantSelectionSystem::eReplace;
+ if ( ( state == c_modifier_toggle || state == c_modifier_toggle_face || state == c_modifier_face ) ) {
+ if( m_mouse2 ){
+ return RadiantSelectionSystem::eReplace;
+ }
+ else{
+ return RadiantSelectionSystem::eToggle;
+ }
}
return RadiantSelectionSystem::eManipulator;
}
DeviceVector m_start;
DeviceVector m_current;
DeviceVector m_epsilon;
-std::size_t m_unmoved_replaces;
ModifierFlags m_state;
+bool m_mouse2;
+bool m_mouseMoved;
+bool m_mouseMovedWhilePressed;
+bool m_paintSelect;
const View* m_view;
RectangleCallback m_window_update;
-Selector_() : m_start( 0.0f, 0.0f ), m_current( 0.0f, 0.0f ), m_unmoved_replaces( 0 ), m_state( c_modifierNone ){
+Selector_() : m_start( 0.0f, 0.0f ), m_current( 0.0f, 0.0f ), m_state( c_modifierNone ), m_mouse2( false ), m_mouseMoved( false ), m_mouseMovedWhilePressed( false ){
}
void draw_area(){
DeviceVector delta( position - m_start );
if ( fabs( delta.x() ) > m_epsilon.x() && fabs( delta.y() ) > m_epsilon.y() ) {
DeviceVector delta( position - m_start );
- getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
+ //getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
+ getSelectionSystem().SelectArea( *m_view, &m_start[0], &delta[0], RadiantSelectionSystem::eToggle, ( m_state & c_modifier_face ) != c_modifierNone );
}
- else
- {
- if ( modifier == RadiantSelectionSystem::eReplace && m_unmoved_replaces++ > 0 ) {
+ else if( !m_mouseMovedWhilePressed ){
+ if ( modifier == RadiantSelectionSystem::eReplace && !m_mouseMoved ) {
modifier = RadiantSelectionSystem::eCycle;
}
getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, ( m_state & c_modifier_face ) != c_modifierNone );
draw_area();
}
+void testSelect_simpleM1( DeviceVector position ){
+ /*RadiantSelectionSystem::EModifier modifier = RadiantSelectionSystem::eReplace;
+ DeviceVector delta( position - m_start );
+ if ( fabs( delta.x() ) < m_epsilon.x() && fabs( delta.y() ) < m_epsilon.y() ) {
+ modifier = RadiantSelectionSystem::eCycle;
+ }
+ getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], modifier, false );*/
+ getSelectionSystem().SelectPoint( *m_view, &position[0], &m_epsilon[0], m_mouseMoved ? RadiantSelectionSystem::eReplace : RadiantSelectionSystem::eCycle, false );
+ m_start = m_current = device_constrained( position );
+}
+
+
bool selecting() const {
- return m_state != c_modifier_manipulator;
+ return m_state != c_modifier_manipulator && m_mouse2;
}
void setState( ModifierFlags state ){
void mouseDown( DeviceVector position ){
m_start = m_current = device_constrained( position );
+ if( !m_mouse2 && m_state != c_modifierNone ){
+ m_paintSelect = getSelectionSystem().SelectPoint_InitPaint( *m_view, &position[0], &m_epsilon[0], ( m_state & c_modifier_face ) != c_modifierNone );
+ }
}
void mouseMoved( DeviceVector position ){
m_current = device_constrained( position );
- draw_area();
+ m_mouseMovedWhilePressed = true;
+ if( m_mouse2 ){
+ draw_area();
+ }
+ else if( m_state != c_modifier_manipulator ){
+ getSelectionSystem().SelectPoint( *m_view, &m_current[0], &m_epsilon[0],
+ m_paintSelect ? RadiantSelectionSystem::eSelect : RadiantSelectionSystem::eDeselect,
+ ( m_state & c_modifier_face ) != c_modifierNone );
+ }
}
-typedef MemberCaller1<Selector_, DeviceVector, &Selector_::mouseMoved> MouseMovedCaller;
+typedef MemberCaller<Selector_, void(DeviceVector), &Selector_::mouseMoved> MouseMovedCaller;
void mouseUp( DeviceVector position ){
- testSelect( device_constrained( position ) );
+ if( m_mouse2 ){
+ testSelect( device_constrained( position ) );
+ }
+ else{
+ m_start = m_current = DeviceVector( 0.0f, 0.0f );
+ }
g_mouseMovedCallback.clear();
g_mouseUpCallback.clear();
}
-typedef MemberCaller1<Selector_, DeviceVector, &Selector_::mouseUp> MouseUpCaller;
+typedef MemberCaller<Selector_, void(DeviceVector), &Selector_::mouseUp> MouseUpCaller;
};
void mouseMoved( DeviceVector position ){
getSelectionSystem().MoveSelected( *m_view, &position[0] );
}
-typedef MemberCaller1<Manipulator_, DeviceVector, &Manipulator_::mouseMoved> MouseMovedCaller;
+typedef MemberCaller<Manipulator_, void(DeviceVector), &Manipulator_::mouseMoved> MouseMovedCaller;
void mouseUp( DeviceVector position ){
getSelectionSystem().endMove();
g_mouseMovedCallback.clear();
g_mouseUpCallback.clear();
}
-typedef MemberCaller1<Manipulator_, DeviceVector, &Manipulator_::mouseUp> MouseUpCaller;
+typedef MemberCaller<Manipulator_, void(DeviceVector), &Manipulator_::mouseUp> MouseUpCaller;
};
void Scene_copyClosestTexture( SelectionTest& test );
m_selector.m_epsilon = m_manipulator.m_epsilon = epsilon;
}
void onMouseDown( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){
- if ( button == c_button_select ) {
+ if ( button == c_button_select || ( button == c_button_select2 && modifiers != c_modifierNone ) ) {
m_mouse_down = true;
+ //m_selector.m_mouseMoved = false;
DeviceVector devicePosition( window_to_normalised_device( position, m_width, m_height ) );
if ( modifiers == c_modifier_manipulator && m_manipulator.mouseDown( devicePosition ) ) {
}
else
{
+ if ( button == c_button_select ) {
+ m_selector.m_mouse2 = false;
+ }
+ else{
+ m_selector.m_mouse2 = true;
+ }
m_selector.mouseDown( devicePosition );
g_mouseMovedCallback.insert( MouseEventCallback( Selector_::MouseMovedCaller( m_selector ) ) );
g_mouseUpCallback.insert( MouseEventCallback( Selector_::MouseUpCaller( m_selector ) ) );
}
}
void onMouseMotion( const WindowVector& position, ModifierFlags modifiers ){
- m_selector.m_unmoved_replaces = 0;
-
+ m_selector.m_mouseMoved = true;
if ( m_mouse_down && !g_mouseMovedCallback.empty() ) {
+ m_selector.m_mouseMovedWhilePressed = true;
g_mouseMovedCallback.get() ( window_to_normalised_device( position, m_width, m_height ) );
}
}
void onMouseUp( const WindowVector& position, ButtonIdentifier button, ModifierFlags modifiers ){
- if ( button == c_button_select && !g_mouseUpCallback.empty() ) {
+ if ( ( button == c_button_select || button == c_button_select2 ) && !g_mouseUpCallback.empty() ) {
m_mouse_down = false;
g_mouseUpCallback.get() ( window_to_normalised_device( position, m_width, m_height ) );
}
+ //L button w/o scene changed = tunnel selection
+ if( // !getSelectionSystem().m_undo_begun &&
+ modifiers == c_modifierNone && button == c_button_select &&
+ //( !m_selector.m_mouseMoved || !m_mouse_down ) &&
+ !m_selector.m_mouseMovedWhilePressed &&
+ ( getSelectionSystem().Mode() != SelectionSystem::eComponent || getSelectionSystem().ManipulatorMode() != SelectionSystem::eDrag ) ){
+ m_selector.testSelect_simpleM1( device_constrained( window_to_normalised_device( position, m_width, m_height ) ) );
+ }
+ //getSelectionSystem().m_undo_begun = false;
+ m_selector.m_mouseMoved = false;
+ m_selector.m_mouseMovedWhilePressed = false;
}
void onModifierDown( ModifierFlags type ){
m_selector.modifierEnable( type );