yumi-flutter/lib/modules/room_game/utils/room_game_viewport.dart
2026-04-29 09:56:01 +08:00

177 lines
4.8 KiB
Dart

import 'package:flutter/material.dart';
const double roomGameDesignWidth = 750;
double resolveRoomGameAvailableHeight(
BuildContext context, {
double reservedTop = 12,
}) {
final mediaQuery = MediaQuery.maybeOf(context);
if (mediaQuery == null) {
return 0;
}
final bottomInset =
mediaQuery.viewInsets.bottom > mediaQuery.padding.bottom
? mediaQuery.viewInsets.bottom
: mediaQuery.padding.bottom;
final availableHeight =
mediaQuery.size.height -
mediaQuery.padding.top -
bottomInset -
reservedTop;
if (!availableHeight.isFinite || availableHeight <= 0) {
return mediaQuery.size.height;
}
return availableHeight.clamp(0.0, mediaQuery.size.height).toDouble();
}
double clampRoomGameHeight(
double value,
double maxHeight, {
double minHeight = 0,
}) {
if (!value.isFinite || value <= 0) {
return maxHeight > 0 ? maxHeight : 0;
}
if (!maxHeight.isFinite || maxHeight <= 0) {
return value;
}
if (minHeight > maxHeight) {
return maxHeight;
}
return value.clamp(minHeight, maxHeight).toDouble();
}
String resolveRoomGameScreenMode(
Map<String, dynamic> launchParams, {
required bool fullScreen,
}) {
final candidates = <String>[
launchParams['screenMode']?.toString() ?? '',
launchParams['screen_mode']?.toString() ?? '',
launchParams['displayMode']?.toString() ?? '',
launchParams['gameScreenMode']?.toString() ?? '',
];
for (final candidate in candidates) {
final trimmed = candidate.trim();
if (trimmed.isNotEmpty) {
return trimmed.toLowerCase();
}
}
return fullScreen ? 'full' : 'half';
}
double resolveRoomGameCompatibilityBottomHeight(BuildContext context) {
final mediaQuery = MediaQuery.maybeOf(context);
if (mediaQuery == null) {
return 0;
}
final isClassicScreen = mediaQuery.padding.bottom <= 0.5;
if (!isClassicScreen) {
return 0;
}
return (mediaQuery.size.width * 0.19).clamp(56.0, 88.0).toDouble();
}
class RoomGameCompatibilityBottomFrame extends StatelessWidget {
const RoomGameCompatibilityBottomFrame({super.key, required this.height});
final double height;
@override
Widget build(BuildContext context) {
if (height <= 0) {
return const SizedBox.shrink();
}
return SizedBox(
height: height,
width: double.infinity,
child: CustomPaint(painter: _RoomGameBottomFramePainter()),
);
}
}
class _RoomGameBottomFramePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final radius = Radius.circular(size.height * 0.18);
final frameRect = RRect.fromRectAndCorners(
Offset.zero & size,
topLeft: radius,
topRight: radius,
);
final backgroundPaint =
Paint()
..shader = const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[Color(0xFF0E392E), Color(0xFF082A23)],
).createShader(Offset.zero & size);
canvas.drawRRect(frameRect, backgroundPaint);
canvas.save();
canvas.clipRRect(frameRect);
final patternPaint =
Paint()
..color = const Color(0xFF2C5B4A).withValues(alpha: 0.20)
..style = PaintingStyle.stroke
..strokeWidth = 1.5;
final motifWidth = size.width / 8;
final motifHeight = size.height / 2.4;
for (double x = -motifWidth; x < size.width + motifWidth; x += motifWidth) {
for (
double y = -motifHeight * 0.2;
y < size.height + motifHeight;
y += motifHeight * 0.72
) {
final rect = Rect.fromCenter(
center: Offset(x + motifWidth * 0.52, y + motifHeight * 0.55),
width: motifWidth * 0.9,
height: motifHeight,
);
canvas.drawArc(rect, -0.35, 4.5, false, patternPaint);
canvas.drawArc(
rect.translate(motifWidth * 0.34, 0),
2.75,
3.6,
false,
patternPaint,
);
}
}
canvas.restore();
final borderPaint =
Paint()
..color = const Color(0xFFE9D58A)
..style = PaintingStyle.stroke
..strokeWidth = 3;
final innerBorderPaint =
Paint()
..color = const Color(0xFF8F7136).withValues(alpha: 0.75)
..style = PaintingStyle.stroke
..strokeWidth = 1;
canvas.drawRRect(frameRect.deflate(1.5), borderPaint);
canvas.drawRRect(frameRect.deflate(5), innerBorderPaint);
final highlightPaint =
Paint()
..shader = const LinearGradient(
colors: <Color>[
Color(0x00F6E8A7),
Color(0x99F6E8A7),
Color(0x00F6E8A7),
],
).createShader(Rect.fromLTWH(0, 0, size.width, 3));
canvas.drawRect(Rect.fromLTWH(0, 0, size.width, 3), highlightPaint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}