@gamelearn/arcade-components 1.33.1 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -93,10 +93,8 @@ var ComicComponent = function ComicComponent(_ref) {
93
93
  setTransition('slide-animation');
94
94
  setCount(slideCount + 1);
95
95
  setStarted(true);
96
- } else {
97
- close();
98
96
  }
99
- }, [close, slideCount, slides === null || slides === void 0 ? void 0 : slides.length]);
97
+ }, [slideCount, slides === null || slides === void 0 ? void 0 : slides.length]);
100
98
  var goToPreviousSlide = (0, _react.useCallback)(function () {
101
99
  setStarted(false);
102
100
  setAudioFailed(false);
@@ -27,6 +27,8 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
27
27
 
28
28
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
29
 
30
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
31
+
30
32
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
31
33
 
32
34
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -86,6 +88,11 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
86
88
  currentLine = _useState10[0],
87
89
  setCurrentLine = _useState10[1];
88
90
 
91
+ var _useState11 = (0, _react.useState)(false),
92
+ _useState12 = _slicedToArray(_useState11, 2),
93
+ ttsStarted = _useState12[0],
94
+ setTTsStart = _useState12[1];
95
+
89
96
  var _soundActions = _slicedToArray(soundActions, 1),
90
97
  playSound = _soundActions[0];
91
98
 
@@ -100,10 +107,10 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
100
107
  decision = currentLineData.decision;
101
108
  var isBranched = !!edges;
102
109
 
103
- var _useState11 = (0, _react.useState)(false),
104
- _useState12 = _slicedToArray(_useState11, 2),
105
- previousLineWasDecision = _useState12[0],
106
- setPreviousLineWasDecision = _useState12[1];
110
+ var _useState13 = (0, _react.useState)(false),
111
+ _useState14 = _slicedToArray(_useState13, 2),
112
+ previousLineWasDecision = _useState14[0],
113
+ setPreviousLineWasDecision = _useState14[1];
107
114
 
108
115
  var isVoiceOver = voiceOver || currentLineData.type === 'conversationalNarration';
109
116
  var isDecision = decision || currentLineData.type === 'conversationalDecision';
@@ -248,21 +255,22 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
248
255
  });
249
256
 
250
257
  if (!(foundEdge !== null && foundEdge !== void 0 && foundEdge[keys[0]])) {
251
- finishConversation();
252
- } else {
253
- var destination = lines.findIndex(function (line) {
254
- return line.id === foundEdge[keys[1]];
255
- });
258
+ return;
259
+ }
256
260
 
257
- if (destination >= 0) {
258
- setCurrentLine(destination);
259
- } else {
260
- finishConversation();
261
- }
261
+ var destination = lines.findIndex(function (line) {
262
+ return line.id === foundEdge[keys[1]];
263
+ });
264
+
265
+ if (destination >= 0) {
266
+ setCurrentLine(destination);
267
+ } else {
268
+ finishConversation();
262
269
  }
263
270
  }, [currentLineData.id, edges, finishConversation, lines]);
264
271
  var handleClickNext = (0, _react.useCallback)(function (choice, reset) {
265
272
  var isLast = false;
273
+ setTTsStart(false);
266
274
  setPreviousLineWasDecision(currentLineData.decision);
267
275
  setStarted(false);
268
276
  setAudioFailed(false);
@@ -279,19 +287,21 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
279
287
 
280
288
  if (line + 1 <= maxLine) {
281
289
  setCurrentLine(line + 1);
290
+ } else if (currentLineData.decision) {
291
+ finishConversation();
282
292
  } else {
283
293
  isLast = true;
284
- finishConversation();
285
294
  }
286
295
  }
287
296
 
288
297
  if (!isLast) {
289
298
  setStarted(true);
290
299
  }
291
- }, [currentLine, currentLineData === null || currentLineData === void 0 ? void 0 : currentLineData.decision, finishConversation, handleBranchDirection, handleDecisionBranch, isBranched, lines.length]);
300
+ }, [currentLine, currentLineData.decision, finishConversation, handleBranchDirection, handleDecisionBranch, isBranched, lines.length]);
292
301
 
293
302
  var handleClickBack = function handleClickBack() {
294
303
  setStarted(false);
304
+ setTTsStart(false);
295
305
  setAudioFailed(false);
296
306
 
297
307
  if (isBranched) {
@@ -305,8 +315,13 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
305
315
 
306
316
  var manualClickNext = function manualClickNext() {
307
317
  playSound('click-ui');
308
- setAutomatic(false);
309
- handleClickNext();
318
+
319
+ if (currentLine === lines.length - 1) {
320
+ finishConversation();
321
+ } else {
322
+ setAutomatic(false);
323
+ handleClickNext();
324
+ }
310
325
  };
311
326
 
312
327
  var manualClickBack = function manualClickBack() {
@@ -326,10 +341,16 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
326
341
  audio: currentLineData === null || currentLineData === void 0 ? void 0 : currentLineData.audio,
327
342
  soundActions: soundActions,
328
343
  emitEvent: emitEvent,
344
+ onStart: function onStart() {
345
+ if (currentMessage.emotion.includes('think')) return;
346
+ setTTsStart(true);
347
+ },
329
348
  onError: function onError() {
330
349
  setAudioFailed(true);
331
350
  },
332
351
  onFinish: function onFinish() {
352
+ setTTsStart(false);
353
+
333
354
  if (autoplayCond) {
334
355
  handleClickNext();
335
356
  }
@@ -394,7 +415,9 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
394
415
  style: backgroundImage ? {
395
416
  backgroundImage: "url(\"".concat(backgroundImage, "\")")
396
417
  } : null
397
- }, /*#__PURE__*/_react.default.createElement(_SlotList.default, listProps), /*#__PURE__*/_react.default.createElement("div", {
418
+ }, /*#__PURE__*/_react.default.createElement(_SlotList.default, _extends({}, listProps, {
419
+ ttsStarted: ttsStarted
420
+ })), /*#__PURE__*/_react.default.createElement("div", {
398
421
  className: "conversation--body",
399
422
  dir: "auto"
400
423
  }, currentMessage ? /*#__PURE__*/_react.default.createElement(_Message.default, {
@@ -410,7 +433,7 @@ var ConversationProViewer = function ConversationProViewer(_ref) {
410
433
  }, /*#__PURE__*/_react.default.createElement("span", {
411
434
  className: (0, _LangIsRtl.default)() ? 'icon-next' : 'icon-back'
412
435
  })), /*#__PURE__*/_react.default.createElement("button", {
413
- className: "gat--btn__round",
436
+ className: "gat--btn__round ".concat(automatic && currentLine === lines.length - 1 ? 'glowing-animation' : ''),
414
437
  type: "button",
415
438
  onClick: manualClickNext
416
439
  }, /*#__PURE__*/_react.default.createElement("span", {
@@ -25,6 +25,7 @@ var SlotList = function SlotList(_ref) {
25
25
  var characters = _ref.characters,
26
26
  actors = _ref.actors,
27
27
  lodSettings = _ref.lodSettings,
28
+ ttsStarted = _ref.ttsStarted,
28
29
  currentMessage = _ref.currentMessage,
29
30
  flex = _ref.flex,
30
31
  slots = _ref.slots,
@@ -142,7 +143,8 @@ var SlotList = function SlotList(_ref) {
142
143
  slots: slots,
143
144
  flex: flex,
144
145
  currentMessage: currentMessage,
145
- lodSettings: lodSettings
146
+ lodSettings: lodSettings,
147
+ ttsStarted: ttsStarted
146
148
  }), children || /*#__PURE__*/_react.default.createElement(Slots, null));
147
149
  };
148
150
 
@@ -23,6 +23,8 @@ var _LightSet = _interopRequireDefault(require("../../../../helpers/LightSet"));
23
23
 
24
24
  var _deviceDetection = require("../../../../helpers/deviceDetection");
25
25
 
26
+ var _useMouthMixer = _interopRequireDefault(require("../../../../helpers/useMouthMixer"));
27
+
26
28
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
29
 
28
30
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -33,13 +35,16 @@ var isMobile = (0, _deviceDetection.DeviceDetection)();
33
35
  var defaultCamPos = [0, 14.63, 16];
34
36
 
35
37
  function Panel(_ref) {
36
- var _character$resource4, _character$resource5;
38
+ var _character$resource4, _character$resource5, _character$resource5$, _character$resource5$2, _character$resource6;
37
39
 
38
40
  var character = _ref.character,
41
+ ttsStarted = _ref.ttsStarted,
39
42
  active = _ref.active;
40
43
  var cameraRef = (0, _react.useRef)(null);
41
44
  var sceneRef = (0, _react.useRef)(null);
42
45
  var isCharacter = character.type === 'character';
46
+ var model = (0, _react.useRef)();
47
+ var defaultClip = (0, _react.useRef)();
43
48
  var emotion = (0, _react.useMemo)(function () {
44
49
  if (isCharacter) {
45
50
  var _character$resource, _character$resource$a, _character$resource$a2, _character$resource3, _character$resource3$;
@@ -55,19 +60,26 @@ function Panel(_ref) {
55
60
 
56
61
  return {};
57
62
  }, [character.emotion, character === null || character === void 0 ? void 0 : (_character$resource4 = character.resource) === null || _character$resource4 === void 0 ? void 0 : _character$resource4.animations, isCharacter]);
58
- var onLoadElement = (0, _react.useCallback)(function (model) {
63
+ var startMouthMixer = (0, _useMouthMixer.default)(model.current, character === null || character === void 0 ? void 0 : (_character$resource5 = character.resource) === null || _character$resource5 === void 0 ? void 0 : (_character$resource5$ = _character$resource5.animations) === null || _character$resource5$ === void 0 ? void 0 : (_character$resource5$2 = _character$resource5$.talking) === null || _character$resource5$2 === void 0 ? void 0 : _character$resource5$2.url, active);
64
+ (0, _react.useEffect)(function () {
65
+ startMouthMixer(ttsStarted);
66
+ }, [ttsStarted, startMouthMixer]);
67
+ var onLoadElement = (0, _react.useCallback)(function (object) {
59
68
  if (cameraRef.current) {
60
69
  var boundingBox = new _three.Box3();
61
- boundingBox.setFromObject(model);
70
+ boundingBox.setFromObject(object);
62
71
  var size = boundingBox.getSize(new _three.Vector3());
63
72
  cameraRef.current.position.fromArray(defaultCamPos);
64
73
  cameraRef.current.rotation.set(0, 0, 0);
65
74
  cameraRef.current.updateProjectionMatrix();
66
75
 
67
76
  if (character.type === 'character') {
77
+ var defaultAnim = object.userData.defaultAnim;
78
+ model.current = object;
79
+ defaultClip.current = defaultAnim.clone();
68
80
  cameraRef.current.position.setY(size.y - 1.5 * 1.3); // Retro compatible with resources without eye bone
69
81
 
70
- model.traverse(function (obj) {
82
+ object.traverse(function (obj) {
71
83
  if (obj.type === 'Bone' && (obj.name.toLowerCase() === 'l_eye' || obj.name.toLowerCase() === 'eye_l')) {
72
84
  var leftEyeVector = new _three.Vector3().setFromMatrixPosition(obj.matrixWorld);
73
85
  cameraRef.current.position.setY(leftEyeVector.y - 0.5);
@@ -75,13 +87,13 @@ function Panel(_ref) {
75
87
  });
76
88
  cameraRef.current.zoom = 1.85;
77
89
  } else if (character.type === 'object') {
78
- (0, _helpers.cameraFitAnyObject)(model, cameraRef.current);
90
+ (0, _helpers.cameraFitAnyObject)(object, cameraRef.current);
79
91
  cameraRef.current.zoom = 1;
80
92
  }
81
93
 
82
94
  cameraRef.current.updateProjectionMatrix();
83
95
  }
84
- }, [character]);
96
+ }, [character.type]);
85
97
  (0, _fiber.useFrame)(function (_ref2) {
86
98
  var gl = _ref2.gl;
87
99
 
@@ -111,9 +123,8 @@ function Panel(_ref) {
111
123
  }, 100);
112
124
  return character.type === 'image' ? null : /*#__PURE__*/_react.default.createElement("scene", {
113
125
  ref: sceneRef
114
- }, (_character$resource5 = character.resource) !== null && _character$resource5 !== void 0 && _character$resource5.url ? /*#__PURE__*/_react.default.createElement(_arcadeThreeCore.LodWrapper, {
115
- progressive: true,
116
- individualProgress: true
126
+ }, (_character$resource6 = character.resource) !== null && _character$resource6 !== void 0 && _character$resource6.url ? /*#__PURE__*/_react.default.createElement(_arcadeThreeCore.LodWrapper, {
127
+ progressive: true
117
128
  }, /*#__PURE__*/_react.default.createElement(_arcadeThreeCore.TriggerWrapper, {
118
129
  name: "char_".concat(character.uid),
119
130
  url: character.resource.url,
@@ -20,6 +20,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
20
20
  var Panels = function Panels(_ref) {
21
21
  var characters = _ref.characters,
22
22
  slots = _ref.slots,
23
+ ttsStarted = _ref.ttsStarted,
23
24
  activeIndex = _ref.activeIndex,
24
25
  flex = _ref.flex,
25
26
  lodSettings = _ref.lodSettings;
@@ -37,7 +38,8 @@ var Panels = function Panels(_ref) {
37
38
  key: "".concat("".concat(currentCharacter.uid, "_").concat(slotPosition), "_", characterPos),
38
39
  character: currentCharacter,
39
40
  active: activeIndex === currentPosition,
40
- lodSettings: lodSettings
41
+ lodSettings: lodSettings,
42
+ ttsStarted: ttsStarted
41
43
  });
42
44
  }
43
45
 
@@ -36,6 +36,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
36
36
  var PanelsWrapper = function PanelsWrapper(_ref) {
37
37
  var characters = _ref.characters,
38
38
  slots = _ref.slots,
39
+ ttsStarted = _ref.ttsStarted,
39
40
  slotRefs = _ref.slotRefs,
40
41
  flex = _ref.flex,
41
42
  currentMessage = _ref.currentMessage;
@@ -56,6 +57,7 @@ var PanelsWrapper = function PanelsWrapper(_ref) {
56
57
  finishBuild(true);
57
58
  }, []);
58
59
  return built ? /*#__PURE__*/_react.default.createElement(_Panels.default, {
60
+ ttsStarted: ttsStarted,
59
61
  characters: characters,
60
62
  slots: slots,
61
63
  slotRefs: slotRefs,
@@ -33,6 +33,8 @@ var _LangIsRtl = _interopRequireDefault(require("../../../helpers/LangIsRtl"));
33
33
 
34
34
  var _BubbleWrapper = _interopRequireDefault(require("./BubbleWrapper"));
35
35
 
36
+ var _useMouthMixer = _interopRequireDefault(require("../../../helpers/useMouthMixer"));
37
+
36
38
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
37
39
 
38
40
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -69,7 +71,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
69
71
 
70
72
  // Global
71
73
  var isMobile = (0, _deviceDetection.DeviceDetection)();
72
- var crossFadeDuration = 0.5;
74
+ var crossFadeDuration = 0.2;
73
75
  var characterMs = 75;
74
76
  var minMs = 1400;
75
77
  var headSize = 2; // Mobile always zoom in?
@@ -79,6 +81,8 @@ var maxCharacterToSwitch = 70;
79
81
  raycast.firstHitOnly = true;
80
82
 
81
83
  var DialogComponent = function DialogComponent(_ref) {
84
+ var _talkingCharacter$cha, _talkingCharacter$cha2, _talkingCharacter$cha3, _talkingCharacter$cha4;
85
+
82
86
  var emitEvent = _ref.emitEvent,
83
87
  lines = _ref.lines,
84
88
  actors = _ref.actors,
@@ -163,6 +167,9 @@ var DialogComponent = function DialogComponent(_ref) {
163
167
  voiceOver = _ref2.voiceOver,
164
168
  decision = _ref2.decision;
165
169
 
170
+ var talkingCharacter = currentLine === null || currentLine === void 0 ? void 0 : currentLine.slots.find(function (slot) {
171
+ return slot.talking;
172
+ });
166
173
  var charactersInvolved = (0, _react.useMemo)(function () {
167
174
  return lines.reduce(function (acc, current) {
168
175
  if (current.slots) {
@@ -240,14 +247,17 @@ var DialogComponent = function DialogComponent(_ref) {
240
247
  }, [loader]); // Force default animation without transition
241
248
 
242
249
  var executeDefaultAnimation = function executeDefaultAnimation(element) {
250
+ if (element.uid === talkingCharacter.uid) return;
251
+
243
252
  if (element.userData.mixer && element.userData.defaultAnim) {
244
253
  var mixer = element.userData.mixer;
245
254
  var defaultAction = mixer.clipAction(element.userData.defaultAnim, element);
246
255
  mixer.stopAllAction();
247
256
  defaultAction.play();
248
257
  }
249
- }; // Reset currentEmotion to defaultAnim
258
+ };
250
259
 
260
+ var startMixer = (0, _useMouthMixer.default)(getCurrentVisible(talkingCharacter.uid), talkingCharacter === null || talkingCharacter === void 0 ? void 0 : (_talkingCharacter$cha = talkingCharacter.character) === null || _talkingCharacter$cha === void 0 ? void 0 : (_talkingCharacter$cha2 = _talkingCharacter$cha.resource) === null || _talkingCharacter$cha2 === void 0 ? void 0 : (_talkingCharacter$cha3 = _talkingCharacter$cha2.animations) === null || _talkingCharacter$cha3 === void 0 ? void 0 : (_talkingCharacter$cha4 = _talkingCharacter$cha3.talking) === null || _talkingCharacter$cha4 === void 0 ? void 0 : _talkingCharacter$cha4.url, true); // Reset currentEmotion to defaultAnim
251
261
 
252
262
  var resetAnims = (0, _react.useCallback)(function () {
253
263
  scene.traverseVisible(function (node) {
@@ -280,20 +290,20 @@ var DialogComponent = function DialogComponent(_ref) {
280
290
  });
281
291
 
282
292
  if (!(foundEdge !== null && foundEdge !== void 0 && foundEdge[keys[0]])) {
283
- finishConversation();
284
- } else {
285
- var destination = lines.findIndex(function (l) {
286
- return l.id === foundEdge[keys[1]];
287
- });
293
+ return;
294
+ }
288
295
 
289
- if (destination >= 0) {
290
- setCurrentMessage({
291
- show: false
292
- });
293
- changeLine(destination);
294
- } else {
295
- finishConversation();
296
- }
296
+ var destination = lines.findIndex(function (l) {
297
+ return l.id === foundEdge[keys[1]];
298
+ });
299
+
300
+ if (destination >= 0) {
301
+ setCurrentMessage({
302
+ show: false
303
+ });
304
+ changeLine(destination);
305
+ } else {
306
+ finishConversation();
297
307
  }
298
308
  }, [currentLine === null || currentLine === void 0 ? void 0 : currentLine.id, edges, finishConversation, lines]);
299
309
  var handleDecisionBranch = (0, _react.useCallback)(function (choice, reset) {
@@ -322,6 +332,7 @@ var DialogComponent = function DialogComponent(_ref) {
322
332
  }
323
333
  }, [currentLine === null || currentLine === void 0 ? void 0 : currentLine.id, edges, finishConversation, lines]);
324
334
  var backLine = (0, _react.useCallback)(function () {
335
+ startMixer(false);
325
336
  setAudioFailed(false);
326
337
 
327
338
  if (isBranched) {
@@ -334,6 +345,7 @@ var DialogComponent = function DialogComponent(_ref) {
334
345
  }
335
346
  }, [handleBranchDirection, isBranched, lastLine, line]);
336
347
  var nextLine = (0, _react.useCallback)(function (choice, reset) {
348
+ startMixer(false);
337
349
  setPreviousLineWasDecision(currentLine.decision);
338
350
  setAudioFailed(false);
339
351
 
@@ -348,7 +360,7 @@ var DialogComponent = function DialogComponent(_ref) {
348
360
  show: false
349
361
  });
350
362
  changeLine(line + 1);
351
- } else {
363
+ } else if (currentLine.decision) {
352
364
  finishConversation();
353
365
  }
354
366
  }, [currentLine === null || currentLine === void 0 ? void 0 : currentLine.decision, isBranched, line, lines.length, handleDecisionBranch, handleBranchDirection, finishConversation]);
@@ -359,8 +371,12 @@ var DialogComponent = function DialogComponent(_ref) {
359
371
  };
360
372
 
361
373
  var manualNextLine = function manualNextLine() {
362
- setAutomatic(false);
363
- nextLine();
374
+ if (line === lines.length - 1) {
375
+ finishConversation();
376
+ } else {
377
+ setAutomatic(false);
378
+ nextLine();
379
+ }
364
380
  }; // Calculate start node
365
381
 
366
382
 
@@ -432,9 +448,6 @@ var DialogComponent = function DialogComponent(_ref) {
432
448
  show: true
433
449
  });
434
450
  } else if (!lastSet.current) {
435
- var talkingCharacter = currentLine === null || currentLine === void 0 ? void 0 : currentLine.slots.find(function (slot) {
436
- return slot.talking;
437
- });
438
451
  var slottedCharacters = currentLine === null || currentLine === void 0 ? void 0 : currentLine.slots.filter(function (slot) {
439
452
  return slot.uid && !slot.talking;
440
453
  });
@@ -476,6 +489,7 @@ var DialogComponent = function DialogComponent(_ref) {
476
489
  if (startAction && action && startAction !== action) {
477
490
  mixer.stopAllAction();
478
491
  (0, _helpers.executeCrossFade)(startAction, action, crossFadeDuration);
492
+ element.userData.defaultAnim = action.getClip();
479
493
  }
480
494
 
481
495
  if (talkingCharacter.uid === element.uid) {
@@ -487,14 +501,14 @@ var DialogComponent = function DialogComponent(_ref) {
487
501
  }
488
502
 
489
503
  setTimeout(function () {
490
- var _talkingCharacter$cha;
504
+ var _talkingCharacter$cha5;
491
505
 
492
506
  var _moveBubble = moveBubble(element, showArrowTop),
493
507
  distance = _moveBubble.distance;
494
508
 
495
509
  setCurrentMessage({
496
510
  text: talkingCharacter.text,
497
- name: talkingCharacter.alias || ((_talkingCharacter$cha = talkingCharacter.character) === null || _talkingCharacter$cha === void 0 ? void 0 : _talkingCharacter$cha.name),
511
+ name: talkingCharacter.alias || ((_talkingCharacter$cha5 = talkingCharacter.character) === null || _talkingCharacter$cha5 === void 0 ? void 0 : _talkingCharacter$cha5.name),
498
512
  left: true,
499
513
  top: showArrowTop || distance > 70,
500
514
  inScene: true,
@@ -506,12 +520,12 @@ var DialogComponent = function DialogComponent(_ref) {
506
520
  }
507
521
  });
508
522
  } else {
509
- var _talkingCharacter$cha2;
523
+ var _talkingCharacter$cha6;
510
524
 
511
525
  resetCameraView();
512
526
  setCurrentMessage({
513
527
  text: talkingCharacter.text,
514
- name: talkingCharacter.alias || ((_talkingCharacter$cha2 = talkingCharacter.character) === null || _talkingCharacter$cha2 === void 0 ? void 0 : _talkingCharacter$cha2.name) || (object === null || object === void 0 ? void 0 : object.name),
528
+ name: talkingCharacter.alias || ((_talkingCharacter$cha6 = talkingCharacter.character) === null || _talkingCharacter$cha6 === void 0 ? void 0 : _talkingCharacter$cha6.name) || (object === null || object === void 0 ? void 0 : object.name),
515
529
  left: false,
516
530
  top: talkingCharacter.text.length > maxCharacterToSwitch,
517
531
  inScene: false,
@@ -541,10 +555,16 @@ var DialogComponent = function DialogComponent(_ref) {
541
555
  audio: currentLine === null || currentLine === void 0 ? void 0 : currentLine.audio,
542
556
  soundActions: soundActions,
543
557
  emitEvent: emitEvent,
558
+ onStart: function onStart() {
559
+ if (talkingCharacter.emotion.includes('think')) return;
560
+ startMixer(true);
561
+ },
544
562
  onError: function onError() {
545
563
  setAudioFailed(true);
546
564
  },
547
565
  onFinish: function onFinish() {
566
+ startMixer(false);
567
+
548
568
  if (autoPlayCond) {
549
569
  nextLine();
550
570
  }
@@ -575,9 +595,6 @@ var DialogComponent = function DialogComponent(_ref) {
575
595
  bubbleRef.current = bubble === null || bubble === void 0 ? void 0 : bubble.current;
576
596
 
577
597
  if (currentLine !== null && currentLine !== void 0 && currentLine.slots && currentMessage.show && bubble !== null && bubble !== void 0 && bubble.current) {
578
- var talkingCharacter = currentLine === null || currentLine === void 0 ? void 0 : currentLine.slots.find(function (slot) {
579
- return slot.talking;
580
- });
581
598
  var bubbleRect = bubble.current.getBoundingClientRect();
582
599
  var x = bubbleRect.x + bubbleRect.width;
583
600
  var y = bubbleRect.y - bubbleRect.height;
@@ -749,7 +766,7 @@ var DialogComponent = function DialogComponent(_ref) {
749
766
  type: "button",
750
767
  onClick: manualNextLine,
751
768
  disabled: animationRunning,
752
- className: "gat--btn__round ".concat(animationRunning ? 'disabled' : '')
769
+ className: "gat--btn__round \n ".concat(animationRunning ? 'disabled' : '', "\n ").concat(automatic && line === lines.length - 1 ? 'glowing-animation' : '')
753
770
  }, /*#__PURE__*/_react.default.createElement("span", {
754
771
  className: (0, _LangIsRtl.default)() ? 'icon-back' : 'icon-next'
755
772
  })))));
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.zAxis = exports.yAxis = exports.xAxis = exports.vectorTranslateZ = exports.vectorTranslateY = exports.vectorTranslateX = exports.vectorTranslateOnAxis = exports.vectorToScreen = exports.usePrevious = exports.screenToVector = exports.roundFloat = exports.getObjectPosition = exports.formatMessage = exports.executeCrossFade = exports.cameraFitAnyObject = void 0;
6
+ exports.zAxis = exports.yAxis = exports.xAxis = exports.vectorTranslateZ = exports.vectorTranslateY = exports.vectorTranslateX = exports.vectorTranslateOnAxis = exports.vectorToScreen = exports.usePrevious = exports.screenToVector = exports.roundFloat = exports.getRandomIndex = exports.getObjectPosition = exports.formatMessage = exports.executeCrossFade = exports.cameraFitAnyObject = void 0;
7
7
 
8
8
  var _react = require("react");
9
9
 
@@ -27,6 +27,12 @@ var formatMessage = function formatMessage(text) {
27
27
 
28
28
  exports.formatMessage = formatMessage;
29
29
 
30
+ var getRandomIndex = function getRandomIndex(length) {
31
+ return Math.floor(Math.random() * length);
32
+ };
33
+
34
+ exports.getRandomIndex = getRandomIndex;
35
+
30
36
  var usePrevious = function usePrevious(value) {
31
37
  var ref = (0, _react.useRef)();
32
38
  (0, _react.useEffect)(function () {
@@ -90,6 +90,11 @@ var useEkho = function useEkho(_ref) {
90
90
  }, [translate]);
91
91
  var setCurrentPlaying = (0, _react.useCallback)(function (url) {
92
92
  var cc = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'tts';
93
+
94
+ if (currentPlaying.current.url === url) {
95
+ return;
96
+ }
97
+
93
98
  currentPlaying.current = {
94
99
  url: url,
95
100
  cc: cc
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ var _three = require("three");
11
+
12
+ var _GLTFLoader = require("three/examples/jsm/loaders/GLTFLoader");
13
+
14
+ var _ = require(".");
15
+
16
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
17
+
18
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
19
+
20
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
21
+
22
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
23
+
24
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
25
+
26
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
27
+
28
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
29
+
30
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
31
+
32
+ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
33
+
34
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
35
+
36
+ var crossFadeDuration = 0.2;
37
+ var bones = ['Jaw_M', 'Head_M', 'L_lip_jnt', 'R_lip_jnt', 'joint4', 'transform1', 'lowerTeeths', 'upperTeeths'];
38
+
39
+ var useMouthMixer = function useMouthMixer(target, talkingURL) {
40
+ var isActive = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
41
+
42
+ var _useState = (0, _react.useState)(false),
43
+ _useState2 = _slicedToArray(_useState, 2),
44
+ started = _useState2[0],
45
+ start = _useState2[1];
46
+
47
+ var loader = (0, _react.useMemo)(function () {
48
+ return new _GLTFLoader.GLTFLoader();
49
+ }, []);
50
+ var tracks = (0, _react.useRef)([]);
51
+ (0, _react.useEffect)(function () {
52
+ if (target && isActive) {
53
+ var _target$userData = target.userData,
54
+ mixer = _target$userData.mixer,
55
+ defaultAnim = _target$userData.defaultAnim,
56
+ emotionClip = _target$userData.emotionClip;
57
+
58
+ if (!started && emotionClip) {
59
+ var emotionAction = mixer.clipAction(emotionClip, target);
60
+ var defaultAction = mixer.clipAction(defaultAnim, target);
61
+ mixer.stopAllAction();
62
+ (0, _.executeCrossFade)(emotionAction, defaultAction, crossFadeDuration);
63
+ } else if (started && talkingURL) {
64
+ var cloned = defaultAnim.clone();
65
+
66
+ var onLoad = function onLoad(anim) {
67
+ var _cloned$tracks;
68
+
69
+ if (anim) {
70
+ var _tracks$current;
71
+
72
+ (_tracks$current = tracks.current).push.apply(_tracks$current, _toConsumableArray(anim.animations[0].tracks.filter(function (track) {
73
+ return bones.find(function (bone) {
74
+ return track.name.includes(bone);
75
+ });
76
+ })));
77
+ }
78
+
79
+ cloned.tracks = defaultAnim.tracks.filter(function (track) {
80
+ return !bones.find(function (bone) {
81
+ return track.name.includes(bone);
82
+ });
83
+ });
84
+
85
+ (_cloned$tracks = cloned.tracks).push.apply(_cloned$tracks, _toConsumableArray(tracks.current));
86
+
87
+ target.userData.emotionClip = cloned;
88
+ var defaultAction = mixer.clipAction(defaultAnim, target);
89
+ var emotionAction = mixer.clipAction(cloned, target);
90
+ emotionAction.loop = _three.LoopPingPong;
91
+ mixer.stopAllAction();
92
+ (0, _.executeCrossFade)(defaultAction, emotionAction, crossFadeDuration);
93
+ };
94
+
95
+ if (!tracks.current.length) {
96
+ loader.load(talkingURL, function (anim) {
97
+ onLoad(anim);
98
+ });
99
+ } else {
100
+ onLoad();
101
+ }
102
+ }
103
+ }
104
+ }, [isActive, talkingURL, loader, started, target]);
105
+ return start;
106
+ };
107
+
108
+ var _default = useMouthMixer;
109
+ exports.default = _default;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@gamelearn/arcade-components",
3
3
  "author": "Gamelearn",
4
4
  "license": "unlicense",
5
- "version": "1.33.1",
5
+ "version": "1.35.0",
6
6
  "main": "dist/index.js",
7
7
  "files": [
8
8
  "dist",
@@ -14,8 +14,8 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@babel/runtime": "^7.18.6",
17
- "@gamelearn/arcade-styles": "0.15.7",
18
- "@gamelearn/arcade-three-core": "1.14.5",
17
+ "@gamelearn/arcade-styles": "0.15.8",
18
+ "@gamelearn/arcade-three-core": "1.17.1",
19
19
  "@react-three/drei": "9.4.3",
20
20
  "@react-three/fiber": "8.0.17",
21
21
  "@testing-library/jest-dom": "^5.16.4",