优化哄睡模式的表情逻辑
authorxue <2144439972@qq.com>
Thu, 4 Dec 2025 12:03:19 +0000 (20:03 +0800)
committerxue <2144439972@qq.com>
Thu, 4 Dec 2025 12:03:19 +0000 (20:03 +0800)
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/include/ThunderBirdModel.h
code/sdk/application/wearable/ln/nativeapp/nativeui/thunderbird/src/ThunderBirdModel.cpp

index 04df4d8..49e4b8d 100644 (file)
@@ -273,6 +273,12 @@ namespace OHOS
         
         // 退出对话模式时恢复表情
         void OnExitDialogueMode();
+
+        // 进入哄睡模式时记录当前表情
+        void OnEnterLullabyMode();
+        
+        // 退出哄睡模式时恢复表情
+        void OnExitLullabyMode();
         
         // 音频文本队列操作函数
         void EnqueueAudioText(const std::string& text);
@@ -378,6 +384,7 @@ namespace OHOS
         std::string m_currentExpression;    // 当前表情状态
         std::string m_currentStatusText;    // 当前状态文本
         std::string m_dialogueExpression;   // 对话界面表情状态
+        std::string m_lullabyExpression;   // 哄睡模式进入前的表情状态
 
         bool close_battery_flag = false;    // 电量过低即将关机标志位
 
index a9f90a1..ab3964a 100644 (file)
@@ -2604,6 +2604,8 @@ extern "C" {
               WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleSleepModeStart: 非意图识别结果,跳转到4");
                 // 重置故事模式finished标志,确保每次进入故事模式时标志位是干净的
                 m_storyModeFinished = false;
+                // 进入哄睡模式时切换为眨眼表情
+                OnEnterLullabyMode();
                 ThunderBirdMainView::GetInstance()->ChangeView(currentView, THUNDERBIRD_LULLABYVIEW, ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_4);
                 //清空文本队列
                 ClearAudioTextQueue();
@@ -2645,6 +2647,11 @@ extern "C" {
         
         if (ThunderBirdMainView::GetInstance()) {
             int currentView = ThunderBirdMainView::GetInstance()->GetCurrentView(); //获取当前视图
+            // 退出哄睡模式时恢复时间线表情
+            OnExitLullabyMode();
+            if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
+                ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(false);
+            }
             ln_ws_audio_deinit();//功耗优化
             //直接退出到状态显示界面
             AI_ForceInterrupt();
@@ -2897,6 +2904,10 @@ extern "C" {
             // 停止动效
             ThunderBirdDialogueView::GetInstance()->AudioPlaybackEnd();
             ThunderBirdDialogueView::GetInstance()->IsNormalEnd = true;
+            //可以开始说话了,显示小绿点
+            if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
+                ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(true);
+            }
             // 启动8秒定时器,时间到就退出对话
             StartCountUpTimer(10);
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioPlaybackEnd: 启动10秒定时器,时间到就退出对话");
@@ -2910,6 +2921,9 @@ extern "C" {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioPlaybackEnd: THUNDERBIRD_LULLABYVIEW_3界面,角色询问完毕,重新启动音频聊天");
             // 重置标志
             m_lullabyView3InquiryStarted = false;
+            if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
+                ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(true);
+            }
             int ret = ln_ws_start_audio_chat(LN_AUDIO_CHAT_CHOOSE_STORY_REQUEST);
             if (ret == 0) {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "THUNDERBIRD_LULLABYVIEW_3: 音频聊天已重新启动");
@@ -2964,7 +2978,7 @@ extern "C" {
             {
                 // isLullabyRecording = true;
                 ThunderBirdLullabyView::GetInstance()->listenAnimator->Start();
-                ThunderBirdDialogueView::GetInstance()->listenIcon->SetVisible(true);
+                // ThunderBirdDialogueView::GetInstance()->listenIcon->SetVisible(true);
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::HandleAudioRecordingStart: 在哄睡界面(故事模式),忽略录音开始事件");
                 return;
             }
@@ -2973,7 +2987,6 @@ extern "C" {
                 || ThunderBirdDialogueView::GetInstance()->DialogueFirst == false) {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "录音开始,跳转到聆听状态");
                 view->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING);
-                ThunderBirdDialogueView::GetInstance()->listenIcon->SetVisible(true);
                 ThunderBirdDialogueView::GetInstance()->IsNormalEnd = false;
                 // ThunderBirdDialogueView::GetInstance()->UpdateDialogueText("超认真聆听中");
             }
@@ -3005,13 +3018,19 @@ extern "C" {
                 currentSubView == ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_LISTENING) {
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "录音结束,跳转到播放界面");
                 view->ChangeView(currentView, THUNDERBIRD_DIALOGUEVIEW, ThunderBirdDialogueView::THUNDERBIRD_DIALOGUEVIEW_SPEAKING);
-                ThunderBirdDialogueView::GetInstance()->listenIcon->SetVisible(false);
+                if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
+                    ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(false);
+                }
             }
             else if (currentView == THUNDERBIRD_LULLABYVIEW && 
                 currentSubView == ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_3 ) {
                     ThunderBirdLullabyView::GetInstance()->listenAnimator->Stop();
-                    ThunderBirdDialogueView::GetInstance()->listenIcon->SetVisible(false);
+                    if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
+                        ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(false);
+                    }
                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "录音结束,跳转到故事界面");
+                // 进入哄睡模式时切换为眨眼表情
+                OnEnterLullabyMode();
                 view->ChangeView(currentView, THUNDERBIRD_LULLABYVIEW, ThunderBirdLullabyView::THUNDERBIRD_LULLABYVIEW_4);
                 return;
             }
@@ -3175,7 +3194,7 @@ extern "C" {
         // 重置对话模式finished标志
         m_dialogueModeFinished = false;
         //如果本来就是眨眼的表情直接返回
-        if (m_currentExpression == "winking") {
+        if (m_currentExpression == "winking" || m_currentExpression.empty() == true) {
             return;
         }
         // 记录进入对话模式前的时间线表情(用于退出时恢复)
@@ -3198,6 +3217,9 @@ extern "C" {
     // 退出对话模式时恢复表情
     void ThunderBirdModel::OnExitDialogueMode()
     {
+        if (ThunderBirdMainView::GetInstance() && ThunderBirdMainView::GetInstance()->listenIcon) {
+            ThunderBirdMainView::GetInstance()->listenIcon->SetVisible(false);
+        }
         // 重置对话模式finished标志
         m_dialogueModeFinished = false;
         
@@ -3248,6 +3270,83 @@ extern "C" {
         }
     }
     
+    // 进入哄睡模式时记录当前表情(进入THUNDERBIRD_LULLABYVIEW_4时调用)
+    void ThunderBirdModel::OnEnterLullabyMode()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnEnterLullabyMode");
+        //如果本来就是眨眼的表情直接返回
+        if (m_currentExpression == "winking" || m_currentExpression.empty() == true) {
+            return;
+        }
+        // 记录进入哄睡模式前的时间线表情(用于退出时恢复)
+        m_lullabyExpression = m_currentExpression;
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnEnterLullabyMode: 记录时间线表情: %s", m_currentExpression.c_str());
+        
+        // 切换到眨眼表情(winking)
+        std::string winkingExpressionPath = "/user/res/video/CloseEyes/" + eyesShape_ + "/" + eyesColor_ + ".mp4";
+        
+        // 检查文件是否存在
+        if (access(winkingExpressionPath.c_str(), F_OK) == 0) {
+            // 切换到眨眼表情(但不更新m_currentExpression,因为退出时要恢复时间线表情)
+            SwitchExpressionVideo(winkingExpressionPath.c_str());
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnEnterLullabyMode: 切换到眨眼表情: %s", winkingExpressionPath.c_str());
+        } else {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnEnterLullabyMode: 眨眼表情文件不存在: %s", winkingExpressionPath.c_str());
+        }
+    }
+    
+    // 退出哄睡模式时恢复表情(退出THUNDERBIRD_LULLABYVIEW_4时调用)
+    void ThunderBirdModel::OnExitLullabyMode()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitLullabyMode");
+        
+        // 恢复到进入哄睡模式前记录的时间线表情
+        if (!m_lullabyExpression.empty()) {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitLullabyMode: 恢复时间线表情: %s", m_lullabyExpression.c_str());
+            //如果相同直接返回
+            if(m_lullabyExpression == m_currentExpression)     
+            {
+                return;
+            }
+            // 恢复表情状态
+            // 构建表情文件路径并切换表情
+            std::string expressionPath;
+            if (screenImageAsEmoji_ == false) {
+                // 不为屏保模式,根据角色配置构建表情路径
+                if (eyesColor_.empty() || eyesShape_.empty() || 
+                    (eyesShape_ == "calm-eyes" && eyesColor_ == "amber")) {
+                    // 默认表情
+                    std::string emotionFileName = MapEmotionToFileName(m_lullabyExpression.c_str());
+                    expressionPath = "/user/res/video/Default/" + emotionFileName + ".mp4";
+                } else {
+                    // 非默认表情
+                    if (m_lullabyExpression == "winking") {
+                        // 眨眼表情
+                        expressionPath = "/user/res/video/CloseEyes/" + eyesShape_ + "/" + eyesColor_ + ".mp4";
+                    } else if (m_lullabyExpression == "sleeping") {
+                        // 睡眠表情
+                        expressionPath = "/user/res/video/Default/sleeping.mp4";
+                    } else {
+                        // 其他表情
+                        expressionPath = "/user/userdata/leiniao/emoji/" + eyesShape_ + "/" + eyesColor_ + "/" + m_lullabyExpression + ".mp4";
+                    }
+                }
+                
+                // 检查文件是否存在并切换表情
+                if (access(expressionPath.c_str(), F_OK) == 0) {
+                    SwitchExpressionVideo(expressionPath.c_str());
+                    HandleHairIconChange(m_lullabyExpression);
+                    SetCurrentExpression(m_lullabyExpression);
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitLullabyMode: 恢复表情成功: %s", expressionPath.c_str());
+                } else {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitLullabyMode: 表情文件不存在: %s", expressionPath.c_str());
+                }
+            }
+        } else {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ThunderBirdModel::OnExitLullabyMode: 没有记录的表情,无法恢复");
+        }
+    }
+    
     // 设置当前表情状态
     void ThunderBirdModel::SetCurrentExpression(const std::string& expression)
     {