PhoneCallViewImpl.ts 10.4 KB
import { CCPureView, CCView } from "../../../../common/classbase/CCViewBase";
import { PhoneCallViewType, PhoneCallViewProps, PhoneCallView, PhoneCallItemProps, PhoneCallListAutoNextPlot } from "../type/PhoneCallView";
import { RegView } from "../../PresenterCCViewFactory";
import { DummyScrollView, DummyLayout, DummyNode, DummyLabel, DummySprite } from "../../../../common/CCDummyObjects";
import { SentenceType, richNodesToCocosString, ActionManager } from "../../../../avg/AVG";
import { ResUtils } from "simba-cc-resutils";
import { AudioManager } from "simba-cc-audio-manager";
import { GameTextData } from "../../../../common/gameplay/gamedata/GameTextData";
import { GameModelManager } from "../../../model/GameModelManager";
import Typewriter from "../../../../common/components/Typewriter";

const { ccclass, property } = cc._decorator;


@ccclass
@RegView(PhoneCallViewType, "prefab/ui/PhoneCallView")
export class PhoneCallViewImpl extends CCPureView<PhoneCallViewProps> implements PhoneCallView {
    //#region editor bindings
    @property(cc.ScrollView)
    private scrollView = DummyScrollView;
    @property(cc.Layout)
    private contentLayout = DummyLayout;
    @property(cc.Node)
    private callingNode = DummyNode;
    @property(cc.Node)
    private messageNode = DummyNode;
    @property(cc.Label)
    private nameLabel1 = DummyLabel;
    @property(cc.Label)
    private nameLabel2 = DummyLabel;
    @property(cc.Sprite)
    private headIcon1 = DummySprite;
    @property(cc.Sprite)
    private headIcon2 = DummySprite;

    @property(cc.Node)
    private rejectTipNode = DummyNode;
    @property(cc.Node)
    private nextPlotNode = DummyNode;

    @property(cc.Label)
    private statusLabel = DummyLabel;

    @property(Typewriter)
    private typewriter: Typewriter = undefined as unknown as Typewriter ;


    private _isPlayMusic: boolean = false;

    private _excuting: boolean = false;

    onRejectCall() {
        this.node.children[1].active = true;
        this.rejectTipNode.runAction(cc.sequence(cc.fadeIn(0.3), cc.delayTime(0.3), cc.callFunc(() => {
            this.rejectTipNode.opacity = 0;
            this.node.children[0].opacity = 0;
            this.stopPhoneMusic();
            this._isPlayMusic = false;
            this.scheduleOnce(async () => {
                this.node.children[0].opacity = 255;
                this.node.children[1].active = false;
                await this.playPhoneMusic();
                this._isPlayMusic = true;
            }, 0.8);
        })));
    }

    playPhoneMusic = async () => {
        const PhoneBgmCallSound = "/audio/bgm/iPhoneXSCallSound";
        await AudioManager.playMusic(PhoneBgmCallSound);
    }

    stopPhoneMusic = () => {
        AudioManager.stopMusic();
    }

    onAcceptCall() {
        this.callingNode.active = false;
        this.messageNode.active = true;
        this.stopPhoneMusic();
        this._isPlayMusic = false;
        GameModelManager.dotMainLinePlotStart();
        if (PhoneCallListAutoNextPlot) {
            this.scheduleOnce(() => {
                this._props.onCompletePlot();
            }, 0.6);
        }
    }

    onNextPlotBtnClick() {
        if(this.typewriter.getShowingString() == ""){
            if (!PhoneCallListAutoNextPlot) {
                if (!this._excuting) {
                    this._excuting = true;
                    this._props.onCompletePlot(this._selectIndex);
                    this._selectIndex = undefined;
                    this.scheduleOnce(() => {
                        this._excuting = false;
                    }, 0.3);
                }
            }
        }else {
            this.typewriter.stopTyperShowString();
        }
        
    }
    //#endregion

    private _newCall = true;
    private _selectIndex?: number;

    applicationChange(force: boolean) {

    }

    onLoad() {
        this.bindProp("name", this.nameLabel1, "string");
        this.bindProp("name", this.nameLabel2, "string");
        this.bindProp("icon", async (v) => {
            if (v) {
                let sf = await ResUtils.loadRes(v, cc.SpriteFrame, 2);
                // if (v === this._props.icon) { // 理论上这里没必要
                this.headIcon1.spriteFrame = sf;
                this.headIcon2.spriteFrame = sf;
                // }
            }
        });



        // this.bindProp("select", (value) => {
        //     if (value >= 0) {
        //         let item = this._props.items[this._props.items.length - 1];
        //         item.select = value;
        //         this.processItem(item);
        //     }
        // });

    }

    select(value: number) {
        if (value >= 0) {
            let item = this._props.items[this._props.items.length - 1];
            item.select = value;
            this.processItem(item);
        }
    }

    scrollToTop(): void {
        this.scrollView.scrollToTop();
    }

    scrollToBottom(animate = true): void {
        if (this.contentLayout.node.height > this.scrollView.node.height) {
            this.scrollView.scrollToBottom(animate ? 0.3 : undefined);
        }
    }

    async open(parent: CCView) {
        super.open(parent);

        this.node.children[0].opacity = 0;
        this.node.children[1].active = true;
        this.callingNode.active = true;
        this.messageNode.active = false;
        this.stopPhoneMusic();
        this._isPlayMusic = false;
        await this.playPhoneMusic();
        this._isPlayMusic = true;
        this.node.children[0].runAction(cc.sequence(cc.delayTime(0.2), cc.fadeIn(0.1), cc.callFunc(() => {
            this.node.children[0].opacity = 255;
            this.node.children[1].active = false;
        })));
        this.updateCallingStatusLabel(GameModelManager.getLanguageTxt(GameTextData.GAME_TEXT_CALLING_VALUE));
    }

    close(clean?: boolean) {
        this.nextPlotNode.active = false;
        this.updateCallingStatusLabel(GameModelManager.getLanguageTxt(GameTextData.GAME_TEXT_CALLENDED_VALUE));
        this.node.stopAllActions();
        this.node.runAction(cc.sequence(cc.delayTime(1.2), cc.callFunc(() => {
            super.close(clean);
            // 清除内容,防止下次打开的时候先显示上次的内容
            this.contentLayout.node.removeAllChildren();
            this.headIcon1.spriteFrame = undefined as any;
            this.nameLabel1.string = "";
            if (this.node.active && this._isPlayMusic) {
                this.stopPhoneMusic();
                this._isPlayMusic = false;
            }
            delete (this as any)._props;
        })));
    }

    onPropsLoad(props: PhoneCallViewProps) {
        super.onPropsLoad(props);
        for (let item of this._props.items) { // 应该只有一条
            this.processItem(item);
        }
    }

    onPropChange(propName: keyof PhoneCallViewProps) {
        super.onPropChange(propName);
        if (propName === "items") {
            for (let i = this.contentLayout.node.children.length; i < this._props.items.length; i++) {
                this.processItem(this._props.items[i]);
            }
        }
    }

    async processItem(item: PhoneCallItemProps) {
        let content = item.sentence.content!;
        if (item.isSelf && content.type === SentenceType.SELECT && item.select === undefined) { // show selector
            this._props.onSetContent(content);
            this.nextPlotNode.active = false;
        } else {
            this.nextPlotNode.active = true;
            if (content.type === SentenceType.SELECT && item.select === undefined) {
                console.error("Something went wrong. ", item.sentence);
                return;
            }
            let node = new cc.Node;
            let richLabel = node.addComponent(cc.RichText);
            richLabel.fontSize = 32;
            richLabel.maxWidth = 585;
            if (item.isSelf) {
                node.anchorX = 1;
                node.x = 300;
                node.color = cc.color(44, 50, 98);
                richLabel.horizontalAlign = cc.macro.TextAlignment.RIGHT;
            } else {
                node.anchorX = 0;
                node.x = -300;
                richLabel.horizontalAlign = cc.macro.TextAlignment.LEFT;
            }
            let text = "";
            if (content.type === SentenceType.SELECT) {
                let option = content.value[item.select!];
                if (option.content) {
                    if (option.content.type === SentenceType.TEXT) {
                        // richLabel.string = richNodesToCocosString(option.content.value);
                        text = richNodesToCocosString(option.content.value);

                    } else {
                        // richLabel.string = `SentenceType(${option.content.type}) not supported in phone call.`;
                        text = `SentenceType(${option.content.type}) not supported in phone call.`;

                    }
                } else {
                    // richLabel.string = option.summary;
                    text = option.summary;
                }
            } else if (content.type === SentenceType.TEXT) {
                // richLabel.string = richNodesToCocosString(content.value);
                text = richNodesToCocosString(content.value);
            } else {
                // richLabel.string = `SentenceType(${content.type}) not supported in phone call.`;
                text = `SentenceType(${content.type}) not supported in phone call.`;
            }
            if (item.isSelf) {
                richLabel.string = text;
            } else {
                this.typewriter.showRichTextTyper(richLabel, text, () => {
                    this.contentLayout.updateLayout();
                    this.scrollToBottom();
                }, () => {
                    this.contentLayout.updateLayout();
                    this.scrollToBottom();
                });
            }
            node.parent = this.contentLayout.node;

        }
        if (item.sentence && item.sentence.actions) {
            await ActionManager.executeActions(item.sentence.actions);
        }

        if (PhoneCallListAutoNextPlot && this.messageNode.active && !this._props.isSentenceSelectVisible()) {
            this.scheduleOnce(() => {
                this._props.onCompletePlot(item.select);
            }, 1);
        } else {
            this._selectIndex = item.select;
        }
        this.contentLayout.updateLayout();
        this.scrollToBottom();
    }

    updateCallingStatusLabel(statusStr: string) {
        this.statusLabel.string = statusStr;
    }
}