Commit bb02a878 authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/ui/interactive' into 'main'

Feat/ui/interactive

See merge request mycard/Neos!43
parents d75636f9 b8194124
......@@ -20,6 +20,7 @@ import {
setCardModalIsOpenImpl,
setCardModalTextImpl,
setCardModalImgUrlImpl,
setCardModalInteractiviesImpl,
} from "./modal";
export interface DuelState {
......@@ -39,7 +40,7 @@ export interface DuelState {
const initialState: DuelState = {
modalState: {
cardModal: { isOpen: false },
cardModal: { isOpen: false, interactivies: [] },
},
};
......@@ -63,6 +64,7 @@ const duelSlice = createSlice({
setCardModalIsOpen: setCardModalIsOpenImpl,
setCardModalText: setCardModalTextImpl,
setCardModalImgUrl: setCardModalImgUrlImpl,
setCardModalInteractivies: setCardModalInteractiviesImpl,
},
extraReducers(builder) {
handsCase(builder);
......@@ -80,6 +82,7 @@ export const {
setCardModalIsOpen,
setCardModalText,
setCardModalImgUrl,
setCardModalInteractivies,
} = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null;
......
......@@ -9,6 +9,7 @@ export interface ModalState {
name?: string;
desc?: string;
imgUrl?: string;
interactivies: { desc: string; response: number }[];
};
}
......@@ -40,6 +41,14 @@ export const setCardModalImgUrlImpl: CaseReducer<
state.modalState.cardModal.imgUrl = action.payload;
};
// 更新卡牌弹窗互动选项
export const setCardModalInteractiviesImpl: CaseReducer<
DuelState,
PayloadAction<{ desc: string; response: number }[]>
> = (state, action) => {
state.modalState.cardModal.interactivies = action.payload;
};
export const selectCardModalIsOpen = (state: RootState) =>
state.duel.modalState.cardModal.isOpen;
export const selectCardModalName = (state: RootState) =>
......@@ -48,3 +57,5 @@ export const selectCardModalDesc = (state: RootState) =>
state.duel.modalState.cardModal.desc;
export const selectCardModalImgUrl = (state: RootState) =>
state.duel.modalState.cardModal.imgUrl;
export const selectCardModalInteractivies = (state: RootState) =>
state.duel.modalState.cardModal.interactivies;
......@@ -6,9 +6,11 @@ import {
selectCardModalName,
selectCardModalDesc,
selectCardModalImgUrl,
selectCardModalInteractivies,
} from "../../../reducers/duel/modal";
import { setCardModalIsOpen } from "../../../reducers/duel/mod";
import { Modal, Card } from "antd";
import { Modal, Card, Button } from "antd";
import { sendSelectIdleCmdResponse } from "../../../api/ocgcore/ocgHelper";
const { Meta } = Card;
const CARD_WIDTH = 240;
......@@ -19,6 +21,7 @@ const CardModal = () => {
const name = useAppSelector(selectCardModalName);
const desc = useAppSelector(selectCardModalDesc);
const imgUrl = useAppSelector(selectCardModalImgUrl);
const interactivies = useAppSelector(selectCardModalInteractivies);
const handleOkOrCancel = () => {
dispatch(setCardModalIsOpen(false));
......@@ -35,6 +38,18 @@ const CardModal = () => {
<Meta title={name} />
<p>{desc}</p>
</Card>
{interactivies.map((interactive) => {
return (
<Button
onClick={() => {
sendSelectIdleCmdResponse(interactive.response);
dispatch(setCardModalIsOpen(false));
}}
>
{interactive.desc}
</Button>
);
})}
</Modal>
</>
);
......
import * as BABYLON from "@babylonjs/core";
import * as BABYLON_GUI from "@babylonjs/gui";
import * as CONFIG from "../../../config/ui";
import { Card, InteractType } from "../../../reducers/duel/util";
import { sendSelectIdleCmdResponse } from "../../../api/ocgcore/ocgHelper";
import {
setCardModalImgUrl,
setCardModalIsOpen,
setCardModalText,
setCardModalInteractivies,
} from "../../../reducers/duel/mod";
import { store } from "../../../store";
......@@ -22,8 +21,6 @@ export default (hands: Card[], scene: BABYLON.Scene) => {
setupHandTransform(hand, item);
// 材质
setupHandMaterial(hand, item, scene);
// 互动选项
setupHandInteractivity(hand, item, idx, scene);
// 事件管理
setupHandAction(hand, item, idx, scene);
});
......@@ -59,51 +56,6 @@ function setupHandMaterial(
mesh.material = handMaterial;
}
function setupHandInteractivity(
mesh: BABYLON.Mesh,
state: Card,
handIdx: number,
scene: BABYLON.Scene
) {
const interactShape = CONFIG.HandInteractShape();
const interactivities = state.interactivities;
for (let i = 0; i < interactivities.length; i++) {
const interact = BABYLON.MeshBuilder.CreatePlane(
`handInteract_${handIdx}_${i}`,
interactShape,
scene
);
interact.parent = mesh;
// 调整位置
interact.translate(
new BABYLON.Vector3(0, 1, 0),
CONFIG.HandShape().height / 2 +
interactShape.height / 2 +
interactShape.height * i
);
const advancedTexture =
BABYLON_GUI.AdvancedDynamicTexture.CreateForMesh(interact);
const button = BABYLON_GUI.Button.CreateImageWithCenterTextButton(
`handInteractButtion_${handIdx}_${i}`,
interactTypeToString(interactivities[i].interactType),
"http://localhost:3030/images/interact_button.png"
);
button.fontSize = CONFIG.HandInteractFontSize;
button.color = "white";
button.onPointerClickObservable.add(() => {
console.log(`<Interact>hand ${handIdx}`);
sendSelectIdleCmdResponse(interactivities[i].response);
});
advancedTexture.addControl(button);
interact.visibility = 0.01;
// interact.setEnabled(false);
}
}
function setupHandAction(
mesh: BABYLON.Mesh,
state: Card,
......@@ -127,13 +79,21 @@ function setupHandAction(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${state.meta.id}.jpg`
)
);
dispatch(
setCardModalInteractivies(
state.interactivities.map((interactive) => {
return {
desc: interactTypeToString(interactive.interactType),
response: interactive.response,
};
})
)
);
dispatch(setCardModalIsOpen(true));
}
)
);
// 监听`Hover`事件
//
// TODO: 应该在`Hover`的时候开启子组件(按钮),`Hover`离开的时候禁用
mesh.actionManager.registerAction(
new BABYLON.CombineAction(
{ trigger: BABYLON.ActionManager.OnPointerOverTrigger },
......@@ -146,13 +106,6 @@ function setupHandAction(
"scaling",
CONFIG.HandHoverScaling()
),
new BABYLON.InterpolateValueAction(
BABYLON.ActionManager.OnPointerOverTrigger,
mesh.getChildMeshes(),
"visibility",
1.0,
10
),
]
)
);
......@@ -169,18 +122,33 @@ function setupHandAction(
"scaling",
CONFIG.HandHoverOutScaling()
),
new BABYLON.InterpolateValueAction(
BABYLON.ActionManager.OnPointerOverTrigger,
mesh.getChildMeshes(),
"visibility",
0.01,
10
),
]
)
);
}
function interactTypeToString(t: InteractType): string {
return InteractType[t];
switch (t) {
case InteractType.SUMMON: {
return "普通召唤";
}
case InteractType.SP_SUMMON: {
return "特殊召唤";
}
case InteractType.POS_CHANGE: {
return "改变表示形式";
}
case InteractType.MSET: {
return "前场放置";
}
case InteractType.SSET: {
return "后场放置";
}
case InteractType.ACTIVATE: {
return "发动效果";
}
default: {
return "未知选项";
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment