1+ using OpenDreamClient . Interface . Controls . UI ;
12using OpenDreamClient . Rendering ;
23using OpenDreamShared . Dream ;
34using OpenDreamShared . Rendering ;
45using Robust . Client . AutoGenerated ;
5- using Robust . Client . GameObjects ;
66using Robust . Client . Player ;
77using Robust . Client . UserInterface ;
88using Robust . Client . UserInterface . Controls ;
99using Robust . Client . UserInterface . XAML ;
1010using Robust . Shared . Map ;
11+ using Robust . Shared . Map . Components ;
1112
1213namespace OpenDreamClient . Input . ContextMenu ;
1314
@@ -16,12 +17,12 @@ internal sealed partial class ContextMenuPopup : Popup {
1617 [ Dependency ] private readonly IPlayerManager _playerManager = default ! ;
1718 [ Dependency ] private readonly IEntityManager _entityManager = default ! ;
1819 [ Dependency ] private readonly IEntitySystemManager _entitySystemManager = default ! ;
19- [ Dependency ] private readonly IMapManager _mapManager = default ! ;
2020 [ Dependency ] private readonly IUserInterfaceManager _uiManager = default ! ;
2121 private readonly ClientAppearanceSystem _appearanceSystem ;
22- private readonly TransformSystem _transformSystem ;
2322 private readonly ClientVerbSystem _verbSystem ;
2423 private readonly DMISpriteSystem _spriteSystem ;
24+ private readonly EntityLookupSystem _lookupSystem ;
25+ private readonly MouseInputSystem _mouseInputSystem ;
2526 private readonly EntityQuery < DMISpriteComponent > _spriteQuery ;
2627 private readonly EntityQuery < TransformComponent > _xformQuery ;
2728 private readonly EntityQuery < DreamMobSightComponent > _mobSightQuery ;
@@ -34,47 +35,64 @@ public ContextMenuPopup() {
3435 IoCManager . InjectDependencies ( this ) ;
3536 RobustXamlLoader . Load ( this ) ;
3637
37- _transformSystem = _entitySystemManager . GetEntitySystem < TransformSystem > ( ) ;
3838 _verbSystem = _entitySystemManager . GetEntitySystem < ClientVerbSystem > ( ) ;
3939 _appearanceSystem = _entitySystemManager . GetEntitySystem < ClientAppearanceSystem > ( ) ;
4040 _spriteSystem = _entitySystemManager . GetEntitySystem < DMISpriteSystem > ( ) ;
41+ _lookupSystem = _entitySystemManager . GetEntitySystem < EntityLookupSystem > ( ) ;
42+ _mouseInputSystem = _entitySystemManager . GetEntitySystem < MouseInputSystem > ( ) ;
4143 _spriteQuery = _entityManager . GetEntityQuery < DMISpriteComponent > ( ) ;
4244 _xformQuery = _entityManager . GetEntityQuery < TransformComponent > ( ) ;
4345 _mobSightQuery = _entityManager . GetEntityQuery < DreamMobSightComponent > ( ) ;
4446 }
4547
46- public void RepopulateEntities ( ClientObjectReference [ ] entities , uint ? turfId ) {
48+ public void RepopulateEntities ( ScalingViewport viewport , Vector2 relativePos , ScreenCoordinates pointerLocation ) {
4749 ContextMenu . RemoveAllChildren ( ) ;
4850
49- foreach ( var objectReference in entities ) {
50- var name = _appearanceSystem . GetName ( objectReference ) ;
51- DreamIcon ? icon = null ;
52-
53- switch ( objectReference . Type ) {
54- case ClientObjectReference . RefType . Entity : {
55- var entity = _entityManager . GetEntity ( objectReference . Entity ) ;
56- if ( _xformQuery . TryGetComponent ( entity , out TransformComponent ? transform ) && ! _mapManager . IsGrid ( _transformSystem . GetParentUid ( entity ) ) ) // Not a child of another entity
57- continue ;
58- if ( ! _spriteQuery . TryGetComponent ( entity , out DMISpriteComponent ? sprite ) ) // Has a sprite
59- continue ;
60- if ( sprite . Icon . Appearance ? . MouseOpacity == MouseOpacity . Transparent ) // Not transparent to mouse clicks
61- continue ;
62- if ( ! _spriteSystem . IsVisible ( sprite , transform , GetSeeInvisible ( ) , null ) ) // Not invisible
63- continue ;
64-
65- icon = sprite . Icon ;
66- break ;
67- }
68- case ClientObjectReference . RefType . Turf when turfId is not null :
69- icon = _appearanceSystem . GetTurfIcon ( turfId . Value ) ;
70- break ;
71- }
51+ var mapCoords = viewport . ScreenToMap ( pointerLocation . Position ) ;
52+ var entities = _lookupSystem . GetEntitiesInRange ( mapCoords , 0.01f , LookupFlags . Uncontained | LookupFlags . Approximate ) ;
7253
73- if ( icon is null )
54+ foreach ( var uid in entities ) {
55+ if ( _xformQuery . TryGetComponent ( uid , out var transform ) && ! _entityManager . HasComponent < MapGridComponent > ( transform . ParentUid ) ) // Not a child of another entity
56+ continue ;
57+ if ( ! _spriteQuery . TryGetComponent ( uid , out var sprite ) ) // Has a sprite
58+ continue ;
59+ if ( sprite . Icon . Appearance ? . MouseOpacity == MouseOpacity . Transparent ) // Not transparent to mouse clicks
7460 continue ;
61+ if ( ! _spriteSystem . IsVisible ( sprite , transform , GetSeeInvisible ( ) , null ) ) // Not invisible
62+ continue ;
63+
64+ var reference = new ClientObjectReference ( _entityManager . GetNetEntity ( uid ) ) ;
65+ var name = _appearanceSystem . GetName ( reference ) ;
66+ ContextMenu . AddChild ( new ContextMenuItem ( this , reference , name , sprite . Icon ) ) ;
67+ }
7568
76- ContextMenu . AddChild ( new ContextMenuItem ( this , objectReference , name , icon ) ) ;
69+ // Add the screen object directly under the mouse, if any
70+ var atomUnderMouse = _mouseInputSystem . GetAtomUnderMouse ( viewport , relativePos , pointerLocation ) ;
71+ if ( atomUnderMouse is { IsScreen : true } ) {
72+ var uid = _entityManager . GetEntity ( atomUnderMouse . Value . Atom . Entity ) ;
73+
74+ if ( _spriteQuery . TryGetComponent ( uid , out var sprite ) &&
75+ sprite . Icon . Appearance ? . MouseOpacity != MouseOpacity . Transparent ) {
76+ var reference = new ClientObjectReference ( _entityManager . GetNetEntity ( uid ) ) ;
77+ var name = _appearanceSystem . GetName ( reference ) ;
78+ ContextMenu . AddChild ( new ContextMenuItem ( this , reference , name , sprite . Icon ) ) ;
79+ }
80+ }
81+
82+ // Append the turf to the end of the context menu
83+ var turfUnderMouse = _mouseInputSystem . GetTurfUnderMouse ( mapCoords , out var turfId ) ? . Atom ;
84+ if ( turfUnderMouse is not null && turfId is not null ) {
85+ var name = _appearanceSystem . GetName ( turfUnderMouse . Value ) ;
86+ var icon = _appearanceSystem . GetTurfIcon ( turfId . Value ) ;
87+
88+ ContextMenu . AddChild ( new ContextMenuItem ( this , turfUnderMouse . Value , name , icon ) ) ;
7789 }
90+
91+ //TODO filter entities by the valid verbs that exist on them
92+ //they should only show up if there is a verb attached to usr which matches the filter in world syntax
93+ //ie, obj|turf in world
94+ //note that popup_menu = 0 overrides this behaviour, as does verb invisibility (urgh), and also hidden
95+ //because BYOND sure loves redundancy
7896 }
7997
8098 public void SetActiveItem ( ContextMenuItem item ) {
0 commit comments