Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 36 additions & 61 deletions lib/widgets/draggable_widgets/agents/agent_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ import 'package:icarus/providers/map_provider.dart';
import 'package:icarus/providers/screen_zoom_provider.dart';
import 'package:icarus/providers/screenshot_provider.dart';
import 'package:icarus/providers/strategy_settings_provider.dart';
import 'package:icarus/providers/view_cone_debug_provider.dart';
import 'package:icarus/providers/view_cone_geometry_provider.dart';
import 'package:icarus/widgets/draggable_widgets/adjacent_page_copy_menu.dart';
import 'package:icarus/widgets/draggable_widgets/zoom_transform.dart';
import 'package:icarus/widgets/draggable_widgets/utilities/view_cone_elevation_menu.dart';
import 'package:icarus/widgets/mouse_watch.dart';
import 'package:shadcn_ui/shadcn_ui.dart';

Expand Down Expand Up @@ -76,6 +73,8 @@ const Color _mutedEnemyBGColor = Color.fromARGB(255, 70, 50, 50);
/// Muted outline colors for dead agents
const Color _mutedAllyOutlineColor = Color.fromARGB(100, 100, 100, 100);
const Color _mutedEnemyOutlineColor = Color.fromARGB(100, 120, 80, 80);
const double _agentQuickActionSize = 36;
const double _agentQuickActionGap = 4;

class AgentWidget extends ConsumerWidget {
const AgentWidget({
Expand Down Expand Up @@ -210,25 +209,24 @@ class AgentWidget extends ConsumerWidget {
)
: null;
final plainAgent = placedAgentNode is PlacedAgent ? placedAgentNode : null;
final viewConeAgent =
placedAgentNode is PlacedViewConeAgent ? placedAgentNode : null;
final visionGeometry = viewConeAgent == null || mapState == null
? null
: ref
.watch(viewConeGeometryProvider(mapState.currentMap))
.asData
?.value;
final viewConeDebugEnabled =
viewConeAgent == null ? false : ref.watch(viewConeDebugProvider);

final adjacentPageCopyItems =
canInteract && lineUpId == null && placedAgentNode != null
? buildAdjacentPageCopyMenuItems(ref, placedAgentNode.id)
: const <ShadContextMenuItem>[];
final hasContextMenuItemsBelow = canInteract &&
(lineUpId != null ||
(plainAgent != null && plainAgent.id.isNotEmpty) ||
adjacentPageCopyItems.isNotEmpty);
final contextMenuItems = <ShadContextMenuItem>[
if (canInteract)
ShadContextMenuItem.raw(
variant: ShadContextMenuItemVariant.primary,
height: 36,
height: _agentQuickActionSize,
closeOnTap: false,
padding: const EdgeInsets.only(bottom: 4),
insetPadding: const EdgeInsets.only(left: 4, right: 4),
padding: hasContextMenuItemsBelow
? const EdgeInsets.only(bottom: _agentQuickActionGap)
: EdgeInsets.zero,
insetPadding: EdgeInsets.zero,
backgroundColor: Colors.transparent,
selectedBackgroundColor: Colors.transparent,
child: _AgentAbilityContextMenuRow(
Expand All @@ -237,32 +235,6 @@ class AgentWidget extends ConsumerWidget {
mapScale: mapScale,
),
),
if (canInteract && viewConeAgent != null && visionGeometry != null)
buildViewConeElevationMenuItem(
geometry: visionGeometry,
selectedElevation: viewConeAgent.visionElevation,
automaticElevation: visionGeometry
.layerForPosition(
isAttack: mapState!.isAttack,
position: viewConeAgent.position +
coordinateSystem.virtualOffsetToWorld(
Offset(agentSize / 2, agentSize / 2),
),
)
.elevation,
onChanged: (elevation) {
ref.read(agentProvider.notifier).updateViewConeElevation(
id: viewConeAgent.id,
elevation: elevation,
);
},
),
if (canInteract && viewConeAgent != null && visionGeometry != null)
buildViewConeDebugMenuItem(
enabled: viewConeDebugEnabled,
onChanged: (enabled) =>
ref.read(viewConeDebugProvider.notifier).state = enabled,
),
if (canInteract && lineUpId != null)
ShadContextMenuItem(
leading: const Icon(LucideIcons.plus),
Expand Down Expand Up @@ -305,8 +277,7 @@ class AgentWidget extends ConsumerWidget {
ref.read(lineUpProvider.notifier).startNewGroup(plainAgent);
},
),
if (canInteract && lineUpId == null && placedAgentNode != null)
...buildAdjacentPageCopyMenuItems(ref, placedAgentNode.id),
...adjacentPageCopyItems,
];

Widget agentCard;
Expand Down Expand Up @@ -368,20 +339,24 @@ class _AgentAbilityContextMenuRow extends ConsumerWidget {

@override
Widget build(BuildContext context, WidgetRef ref) {
return Row(
spacing: 4,
// crossAxisAlignment: CrossAxisAlignment.start,
//
mainAxisSize: MainAxisSize.max,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
for (final ability in agent.abilities)
_AgentAbilityContextMenuButton(
ability: ability,
isAlly: isAlly,
mapScale: mapScale,
),
],
return ConstrainedBox(
constraints: BoxConstraints(
minWidth: (agent.abilities.length * _agentQuickActionSize) +
((agent.abilities.length + 1) * _agentQuickActionGap),
),
child: Row(
spacing: _agentQuickActionGap,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (final ability in agent.abilities)
_AgentAbilityContextMenuButton(
ability: ability,
isAlly: isAlly,
mapScale: mapScale,
),
],
),
);
}
}
Expand Down Expand Up @@ -471,8 +446,8 @@ class _AgentAbilityContextMenuButtonState
child: AnimatedContainer(
duration: const Duration(milliseconds: 120),
curve: Curves.easeOutCubic,
width: 36,
height: 36,
width: _agentQuickActionSize,
height: _agentQuickActionSize,
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: background,
Expand Down
26 changes: 2 additions & 24 deletions lib/widgets/draggable_widgets/utilities/view_cone_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -214,31 +214,9 @@ class ViewConeWidget extends ConsumerWidget {
}
}

final elevationMenuItems = placedUtility == null
final contextMenuItems = placedUtility == null
? null
: [
if (geometry != null)
buildViewConeElevationMenuItem(
geometry: geometry,
selectedElevation: placedUtility.visionElevation,
automaticElevation: geometry
.layerForPosition(
isAttack: ref.read(mapProvider).isAttack,
position: resolvedWorldOrigin!,
)
.elevation,
onChanged: (elevation) {
ref
.read(utilityProvider.notifier)
.updateViewConeElevation(placedUtility!.id, elevation);
},
),
if (geometry != null)
buildViewConeDebugMenuItem(
enabled: debugEnabled,
onChanged: (enabled) =>
ref.read(viewConeDebugProvider.notifier).state = enabled,
),
...buildAdjacentPageCopyMenuItems(ref, placedUtility.id),
];

Expand Down Expand Up @@ -279,7 +257,7 @@ class ViewConeWidget extends ConsumerWidget {
deleteTarget: (id?.isNotEmpty ?? false)
? HoveredDeleteTarget.utility(id: id!, ownerToken: Object())
: null,
contextMenuItems: elevationMenuItems,
contextMenuItems: contextMenuItems,
cursor: SystemMouseCursors.click,
child: Container(
decoration: BoxDecoration(
Expand Down
56 changes: 56 additions & 0 deletions test/lineup_add_item_interaction_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,62 @@ void main() {
);
});

testWidgets('agent quick actions span the width of longer menu rows',
(tester) async {
final container = _createContainer();
final group = _breachGroup();
container.read(lineUpProvider.notifier).addGroup(group);

await _pumpHarness(
tester,
container: container,
child: Center(
child: AgentWidget(
lineUpId: group.id,
id: group.agent.id,
isAlly: group.agent.isAlly,
agent: AgentData.agents[group.agent.type]!,
),
),
);

await tester.tapAt(
tester.getCenter(find.byType(AgentWidget)),
buttons: kSecondaryButton,
kind: PointerDeviceKind.mouse,
);
await tester.pumpAndSettle();

final menuItemRect = tester.getRect(
find.byType(ShadContextMenuItem).first,
);
final abilityButtons = find.byWidgetPredicate(
(widget) => widget is Draggable<DraggedAbilityData>,
);
expect(
abilityButtons,
findsNWidgets(AgentData.agents[group.agent.type]!.abilities.length),
);

final buttonRects = [
for (final element in abilityButtons.evaluate())
tester.getRect(
find.byElementPredicate((candidate) => candidate == element),
),
];
final leadingSpace = buttonRects.first.left - menuItemRect.left;
final trailingSpace = menuItemRect.right - buttonRects.last.right;
for (var index = 1; index < buttonRects.length; index++) {
final gap = buttonRects[index].left - buttonRects[index - 1].right;
expect(gap, closeTo(4, 0.1));
}
expect(trailingSpace, closeTo(leadingSpace, 0.1));
for (final buttonRect in buttonRects) {
expect(buttonRect.width, 36);
expect(buttonRect.height, 36);
}
});

testWidgets('locked add-item mode renders a non-draggable preview agent',
(tester) async {
final container = _createContainer();
Expand Down
Loading
Loading