ai_patint.dart 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. import 'package:fis_measure/interfaces/date_types/int_size.dart';
  2. import 'package:fis_measure/interfaces/process/player/play_controller.dart';
  3. import 'package:fis_measure/interfaces/process/workspace/application.dart';
  4. import 'package:fis_measure/view/paint/ai_patint_controller.dart';
  5. import 'package:fis_measure/view/paint/parts/dash_line.dart';
  6. import 'package:fis_measure/view/paint/parts/dots.dart';
  7. import 'package:fis_measure/view/paint/parts/rectangle.dart';
  8. import 'package:fis_measure/view/player/controller.dart';
  9. import 'package:fis_measure/view/player/enums.dart';
  10. import 'package:fis_measure/view/player/events.dart';
  11. import 'package:flutter/material.dart';
  12. import 'package:get/get.dart';
  13. class AIPaintInfo extends StatefulWidget {
  14. /// 播放器控制器
  15. final VidPlayerController controller;
  16. final double? width;
  17. final double? height;
  18. const AIPaintInfo(
  19. this.controller, {
  20. Key? key,
  21. this.width,
  22. this.height,
  23. }) : super(key: key);
  24. @override
  25. State<AIPaintInfo> createState() => _AIPaintInfoState();
  26. }
  27. class _AIPaintInfoState extends State<AIPaintInfo> {
  28. late final aiPatintController = Get.put(
  29. AiPatintController(
  30. widget.controller,
  31. ),
  32. );
  33. late bool isShowAiResult;
  34. /// 播放控制器
  35. final playerController = Get.find<IPlayerController>();
  36. @override
  37. void initState() {
  38. //监听Widget是否绘制完毕
  39. super.initState();
  40. widget.controller.eventHandler.addListener(onControllerEvent);
  41. }
  42. @override
  43. void dispose() {
  44. super.dispose();
  45. widget.controller.eventHandler.removeListener(onControllerEvent);
  46. // _removeListenrs();
  47. }
  48. void onControllerEvent(Object sender, VidPlayerEvent e) {
  49. if (e is VidPlayerStatusChangeEvent) {
  50. updateFrame();
  51. aiPatintController.state.vidStatus = e.status;
  52. }
  53. if (e is VidPlayerFrameIndexChangeEvent) {
  54. onFrameChanged(e);
  55. }
  56. if (e is VidPlayerBrightnessChangeEvent) {
  57. updateFrame();
  58. }
  59. if (e is VidPlayerContrastChangeEvent) {
  60. updateFrame();
  61. }
  62. }
  63. void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
  64. setState(() {
  65. aiPatintController.state.frameIndex = e.index;
  66. });
  67. }
  68. void updateFrame() {
  69. setState(() {});
  70. }
  71. @override
  72. void didUpdateWidget(covariant AIPaintInfo oldWidget) {
  73. if (oldWidget.controller != widget.controller) {
  74. throw UnsupportedError("[VidTestPlayer] unsupport replace controller.");
  75. }
  76. super.didUpdateWidget(oldWidget);
  77. }
  78. @override
  79. Widget build(BuildContext context) {
  80. return Obx(
  81. () {
  82. Widget? child;
  83. switch (aiPatintController.state.vidStatus) {
  84. case VidPlayStatus.init:
  85. child = Container();
  86. break;
  87. case VidPlayStatus.ready:
  88. child = Container();
  89. break;
  90. case VidPlayStatus.loadFail:
  91. child = Container();
  92. break;
  93. case VidPlayStatus.play:
  94. child = LayoutBuilder(builder: (context, constraints) {
  95. final canvasWidth = constraints.maxWidth;
  96. late final frameDataWidth =
  97. aiPatintController.application.frameData?.width;
  98. late final widthScale = (canvasWidth / frameDataWidth!);
  99. try {
  100. isShowAiResult =
  101. aiPatintController.onGetAIResultsInfo(widthScale);
  102. } catch (e) {
  103. isShowAiResult = true;
  104. }
  105. if (!isShowAiResult) {
  106. return const SizedBox();
  107. } else {
  108. return CustomMultiChildLayout(
  109. delegate: _LayerLayoutDelegate(),
  110. children: [
  111. LayoutId(
  112. id: _LayerLayoutIds.rectangle,
  113. child: CustomPaint(
  114. painter: PaintAIRectangle(
  115. aiPatintController.left,
  116. aiPatintController.top,
  117. aiPatintController.width,
  118. aiPatintController.height,
  119. ),
  120. ),
  121. )
  122. ],
  123. );
  124. }
  125. });
  126. break;
  127. case VidPlayStatus.pause:
  128. child = LayoutBuilder(builder: (context, constraints) {
  129. final canvasWidth = constraints.maxWidth;
  130. late final frameDataWidth =
  131. aiPatintController.application.frameData?.width;
  132. late final widthScale = (canvasWidth / frameDataWidth!);
  133. if (!aiPatintController.onGetAIResultsInfo(widthScale)) {
  134. return const SizedBox();
  135. } else {
  136. return CustomMultiChildLayout(
  137. delegate: _LayerLayoutDelegate(),
  138. children: [
  139. LayoutId(
  140. id: _LayerLayoutIds.dots,
  141. child: Stack(
  142. children: aiPatintController.aiDotsResultsList
  143. .map(
  144. (e) => Obx(
  145. () {
  146. return CustomPaint(
  147. painter: PaintAIDots(
  148. e,
  149. aiPatintController.state.aiResultIndex,
  150. ),
  151. );
  152. },
  153. ),
  154. )
  155. .toList(),
  156. ),
  157. ),
  158. LayoutId(
  159. id: _LayerLayoutIds.dashLine,
  160. child: Stack(
  161. children: aiPatintController.aiDotsResultsList
  162. .map(
  163. (e) => CustomPaint(
  164. painter: PaintAIDashLine(
  165. e,
  166. ),
  167. ),
  168. )
  169. .toList(),
  170. ),
  171. ),
  172. ],
  173. );
  174. }
  175. });
  176. break;
  177. case VidPlayStatus.stop:
  178. case VidPlayStatus.dispose:
  179. child = Container(child: const Text("Closed"));
  180. break;
  181. }
  182. return buildBox(context, child);
  183. },
  184. );
  185. }
  186. Widget buildBox(BuildContext context, Widget child) {
  187. if (aiPatintController.state.isShowAi) {
  188. return Container(
  189. alignment: Alignment.center,
  190. child: child,
  191. );
  192. } else {
  193. return const SizedBox();
  194. }
  195. }
  196. }
  197. class _LayerLayoutDelegate extends MultiChildLayoutDelegate {
  198. Offset? layoutOffset;
  199. Size? layoutSize;
  200. _LayerLayoutDelegate();
  201. @override
  202. void performLayout(Size size) {
  203. final application = Get.find<IApplication>();
  204. final vidFrame = application.frameData;
  205. final imageSize = IntSize.fill(vidFrame?.width ?? 0, vidFrame?.height ?? 0);
  206. /// 以Contain方式填充布局,计算定位偏移量
  207. calcSize(size, imageSize);
  208. final offset = layoutOffset!;
  209. final renderSize = layoutSize!;
  210. /// 同步图像显示尺寸
  211. application.displaySize = renderSize;
  212. /// 其他层按播放器尺寸位置层叠布局
  213. layoutLayer(_LayerLayoutIds.dots, offset, renderSize);
  214. layoutLayer(_LayerLayoutIds.dashLine, offset, renderSize);
  215. layoutLayer(_LayerLayoutIds.rectangle, offset, renderSize);
  216. layoutLayer(_LayerLayoutIds.aiResult, offset, renderSize);
  217. }
  218. void layoutLayer(_LayerLayoutIds layoutId, Offset offset, Size size) {
  219. if (hasChild(layoutId)) {
  220. layoutChild(
  221. layoutId,
  222. BoxConstraints.loose(size),
  223. );
  224. positionChild(layoutId, offset);
  225. }
  226. }
  227. void calcSize(Size size, IntSize imageSize) {
  228. final parentWHRatio = size.width / size.height;
  229. final imageWHRatio = imageSize.width / imageSize.height;
  230. if (imageWHRatio < parentWHRatio) {
  231. // 高度撑满
  232. final layoutWidth = size.height * imageWHRatio;
  233. final layoutHeight = size.height;
  234. final offsetX = (size.width - layoutWidth) / 2;
  235. layoutOffset = Offset(offsetX, 0);
  236. layoutSize = Size(layoutWidth, layoutHeight);
  237. } else if (imageWHRatio > parentWHRatio) {
  238. // 宽度撑满
  239. final layoutWidth = size.width;
  240. final layoutHeight = size.width / imageWHRatio;
  241. final offsetY = (size.height - layoutHeight) / 2;
  242. layoutOffset = Offset(0, offsetY);
  243. layoutSize = Size(layoutWidth, layoutHeight);
  244. } else {
  245. layoutOffset = Offset.zero;
  246. layoutSize = size;
  247. }
  248. }
  249. @override
  250. bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
  251. return false;
  252. }
  253. }
  254. enum _LayerLayoutIds {
  255. /// 点
  256. dots,
  257. /// 虚线
  258. dashLine,
  259. /// 矩形
  260. rectangle,
  261. /// ai结果
  262. aiResult
  263. }