fix: 更新提交
This commit is contained in:
9
assets/games/scripts/pets.meta
Normal file
9
assets/games/scripts/pets.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "d098e1e4-9d54-4ad0-88f0-f13bf7c77e51",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
232
assets/games/scripts/pets/BasePart.ts
Normal file
232
assets/games/scripts/pets/BasePart.ts
Normal file
@@ -0,0 +1,232 @@
|
||||
import { instantiate, Node, sp, Sprite, SpriteFrame, Texture2D } from "cc";
|
||||
import { DRESS_PART, DRESS_SOURCE_TYPE, IDressInfo, SPINE_SLOT, SPINE_SOCKET } from "./Types";
|
||||
import ResManager from "@max-studio/core/res/ResManager";
|
||||
import { loadDressSocketNode } from "./PetUtils";
|
||||
import { StringUtils } from "@max-studio/core/utils/StringUtils";
|
||||
|
||||
export class BasePart {
|
||||
protected skeleton: sp.Skeleton = null;
|
||||
protected info: IDressInfo = null;
|
||||
protected socketName: string = null;
|
||||
protected part: DRESS_PART = null;
|
||||
protected faceSkeleton: sp.Skeleton = null;
|
||||
protected socketMountNode: Node = null;
|
||||
protected socketCache: Map<string, sp.SpineSocket> = new Map();
|
||||
protected socketNode: Node = null;
|
||||
|
||||
constructor(ske: sp.Skeleton, part: DRESS_PART) {
|
||||
this.skeleton = ske;
|
||||
this.part = part;
|
||||
this.socketName = SPINE_SOCKET[part];
|
||||
this.faceSkeleton = ske.node.getChildByName("face")?.getComponent(sp.Skeleton);
|
||||
}
|
||||
|
||||
public async putOn(info: IDressInfo) {
|
||||
this.takeOff();
|
||||
this.info = info;
|
||||
if (info.sourceLocationType == DRESS_SOURCE_TYPE.SLOT) {
|
||||
await this.putOnBySlot(info);
|
||||
} else {
|
||||
await this.putOnBySocket(info);
|
||||
}
|
||||
}
|
||||
public takeOff() {
|
||||
if (this.info == null) {
|
||||
return;
|
||||
}
|
||||
const partSkeleton = this.getPartSkeleton();
|
||||
if (this.info.sourceLocationType == DRESS_SOURCE_TYPE.SLOT) {
|
||||
const slotName = SPINE_SLOT[this.part];
|
||||
if (StringUtils.isEmpty(slotName) || partSkeleton == null) {
|
||||
console.error("宠物_槽位_空", slotName);
|
||||
return;
|
||||
}
|
||||
const slot = partSkeleton.findSlot(slotName);
|
||||
if (!slot) {
|
||||
console.error("宠物_槽位_不存在", slotName);
|
||||
return;
|
||||
}
|
||||
if (slot.texture) {
|
||||
ResManager.getInstance().releaseAsset(slot.texture);
|
||||
slot.texture = null;
|
||||
}
|
||||
partSkeleton.setSlotTexture(slotName, null, true);
|
||||
} else {
|
||||
if (!this.socketNode) {
|
||||
return;
|
||||
}
|
||||
const socketSprite = this.socketNode.getOrAddComponent(Sprite, "Texture");
|
||||
if (socketSprite && socketSprite.spriteFrame) {
|
||||
ResManager.getInstance().releaseAsset(socketSprite.spriteFrame);
|
||||
socketSprite.spriteFrame = null;
|
||||
}
|
||||
const spine = this.socketNode.getOrAddComponent(sp.Skeleton, "Spine");
|
||||
if (spine && spine.skeletonData) {
|
||||
ResManager.getInstance().releaseAsset(spine.skeletonData);
|
||||
spine.skeletonData = undefined;
|
||||
spine.animation = undefined;
|
||||
}
|
||||
}
|
||||
this.info = null;
|
||||
}
|
||||
|
||||
private getPartSkeleton() {
|
||||
if (
|
||||
this.part == DRESS_PART.GLASSES ||
|
||||
this.part == DRESS_PART.ACCESS ||
|
||||
this.info.sourceLocationType == DRESS_SOURCE_TYPE.SOCKET_TEX_FACE ||
|
||||
this.info.sourceLocationType == DRESS_SOURCE_TYPE.SOCKET_SPINE_FACE
|
||||
) {
|
||||
return this.faceSkeleton;
|
||||
}
|
||||
return this.skeleton;
|
||||
}
|
||||
|
||||
private getPartBonePath(skeleton: sp.Skeleton, name: string) {
|
||||
let path = "";
|
||||
console.log("获取宠物_骨骼_路径:", name);
|
||||
let bone = skeleton.findBone(name);
|
||||
if (bone) {
|
||||
path = bone.data.name;
|
||||
while (bone.parent) {
|
||||
bone = bone.parent;
|
||||
path = `${bone.data.name}/${path}`;
|
||||
if ("root" == bone.data.name) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private getSocketNode(ske: sp.Skeleton, path: string): sp.SpineSocket {
|
||||
let socket = this.socketCache.get(path);
|
||||
if (socket == null) {
|
||||
const sockets = ske.sockets as sp.SpineSocket[];
|
||||
socket = sockets.find((s) => s.path == path);
|
||||
if (!socket) {
|
||||
console.error("宠物_挂点_不存在 创建挂点:", path);
|
||||
socket = new sp.SpineSocket(path);
|
||||
sockets.push(socket);
|
||||
ske.sockets = sockets;
|
||||
}
|
||||
this.socketCache.set(path, socket);
|
||||
}
|
||||
return socket;
|
||||
}
|
||||
|
||||
private async putOnBySlot(info: IDressInfo) {
|
||||
const partSkeleton = this.getPartSkeleton();
|
||||
const slotName = SPINE_SLOT[this.part];
|
||||
if (StringUtils.isEmpty(slotName) || partSkeleton == null) {
|
||||
console.error("宠物_槽位_空", slotName);
|
||||
return;
|
||||
}
|
||||
const slot = partSkeleton.findSlot(slotName);
|
||||
if (!slot) {
|
||||
console.error("宠物_槽位_不存在", slotName);
|
||||
return;
|
||||
}
|
||||
if (!info) {
|
||||
if (slot.texture) {
|
||||
ResManager.getInstance().releaseAsset(slot.texture);
|
||||
slot.texture = null;
|
||||
}
|
||||
partSkeleton.setSlotTexture(slotName, null, true);
|
||||
return;
|
||||
}
|
||||
const { err, asset } = await ResManager.getInstance().loadAsset({
|
||||
bundle: "dress-spine",
|
||||
path: `DressTexture/${info.sourceName}`,
|
||||
type: Texture2D,
|
||||
});
|
||||
if (err) {
|
||||
console.error("加载宠物_槽位_失败", err);
|
||||
return;
|
||||
}
|
||||
if (this.info != info) {
|
||||
ResManager.getInstance().releaseAsset(asset);
|
||||
return;
|
||||
}
|
||||
if (slot.texture != null) {
|
||||
ResManager.getInstance().releaseAsset(slot.texture);
|
||||
slot.texture = null;
|
||||
}
|
||||
|
||||
slot.texture = asset;
|
||||
partSkeleton.setSlotTexture(slotName, asset, true);
|
||||
}
|
||||
|
||||
private async putOnBySocket(info: IDressInfo) {
|
||||
const partSkeleton = this.getPartSkeleton();
|
||||
const bonePath = this.getPartBonePath(partSkeleton, this.socketName);
|
||||
if (this.socketNode == null) {
|
||||
const socketPrefab = await loadDressSocketNode();
|
||||
if (socketPrefab == null) {
|
||||
return;
|
||||
}
|
||||
this.socketNode = instantiate(socketPrefab);
|
||||
}
|
||||
|
||||
if (
|
||||
info.sourceLocationType == DRESS_SOURCE_TYPE.SOCKET_TEX_FACE ||
|
||||
info.sourceLocationType == DRESS_SOURCE_TYPE.SOCKET_TEX
|
||||
) {
|
||||
const loadInfo = await ResManager.getInstance().loadAsset({
|
||||
bundle: "dress-spine",
|
||||
path: `DressTexture/${info.sourceName}`,
|
||||
type: SpriteFrame,
|
||||
});
|
||||
if (loadInfo.err) {
|
||||
console.error("加载宠物_socket_tex失败", loadInfo.err);
|
||||
} else {
|
||||
if (this.info == info) {
|
||||
const socketSprite = this.socketNode.getOrAddComponent(Sprite, "Texture");
|
||||
socketSprite.spriteFrame = loadInfo.asset as SpriteFrame;
|
||||
} else {
|
||||
console.warn("加载宠物_socket_tex失败,但是不是当前宠物");
|
||||
ResManager.getInstance().releaseAsset(loadInfo.asset);
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
info.sourceLocationType == DRESS_SOURCE_TYPE.SOCKET_SPINE ||
|
||||
info.sourceLocationType == DRESS_SOURCE_TYPE.SOCKET_SPINE_FACE
|
||||
) {
|
||||
const loadInfo = await ResManager.getInstance().loadAsset({
|
||||
bundle: "dress-spine",
|
||||
path: `DressSpine/${info.sourceName}/${info.sourceName}`,
|
||||
type: sp.SkeletonData,
|
||||
});
|
||||
if (loadInfo.err) {
|
||||
console.error("加载宠物_socket_spine失败", loadInfo.err);
|
||||
} else {
|
||||
if (this.info == info) {
|
||||
const spine = this.socketNode.getOrAddComponent(sp.Skeleton, "Spine");
|
||||
spine.animation = undefined;
|
||||
spine.skeletonData = loadInfo.asset as sp.SkeletonData;
|
||||
spine.setAnimation(0, "idle", true);
|
||||
} else {
|
||||
console.warn("加载宠物_socket_spine失败,但是不是当前宠物");
|
||||
ResManager.getInstance().releaseAsset(loadInfo.asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.socketNode.setParent(partSkeleton.node);
|
||||
const socket = this.getSocketNode(partSkeleton, bonePath);
|
||||
this.socketNode.layer = partSkeleton.node.layer;
|
||||
socket.target = this.socketNode;
|
||||
const socketSpine = this.socketNode.getOrAddComponent(sp.Skeleton);
|
||||
if (socketSpine && socketSpine.skeletonData) {
|
||||
socketSpine.setAnimation(0, "idle", true);
|
||||
}
|
||||
// eslint-disable-next-line no-self-assign
|
||||
partSkeleton.sockets = partSkeleton.sockets;
|
||||
this.setSocketZIndex();
|
||||
}
|
||||
protected setSocketZIndex() {
|
||||
if (this.socketNode) {
|
||||
this.socketNode.setSiblingIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
assets/games/scripts/pets/BasePart.ts.meta
Normal file
9
assets/games/scripts/pets/BasePart.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e07784d9-9898-4cde-b467-3deaba247a36",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
82
assets/games/scripts/pets/BasePet.ts
Normal file
82
assets/games/scripts/pets/BasePet.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Component, _decorator, sp } from "cc";
|
||||
import { COMMON_FACE_ANIM, DRESS_PART, IDressInfo, PET_ANIM_NAME, PET_BODY_FACE_ANIM_MAP, PetInfo } from "./Types";
|
||||
import { autoBind } from "@max-studio/core/ui/UIDecorator";
|
||||
import { BasePart } from "./BasePart";
|
||||
import { GlarePart } from "./GlarePart";
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
@ccclass("BasePet")
|
||||
export class BasePet extends Component {
|
||||
private petInfo: PetInfo;
|
||||
|
||||
@autoBind("RootNode/PetAni", sp.Skeleton)
|
||||
private petBodySkeleton: sp.Skeleton = null;
|
||||
|
||||
@autoBind("RootNode/PetAni/face", sp.Skeleton)
|
||||
private petFace: sp.Skeleton = null;
|
||||
|
||||
private parts: Map<DRESS_PART, BasePart> = new Map();
|
||||
|
||||
protected onLoad(): void {
|
||||
this.parts.set(DRESS_PART.GLARE, new GlarePart(this.petBodySkeleton, DRESS_PART.GLARE));
|
||||
this.parts.set(DRESS_PART.BAG, new BasePart(this.petBodySkeleton, DRESS_PART.BAG));
|
||||
this.parts.set(DRESS_PART.GLASSES, new BasePart(this.petBodySkeleton, DRESS_PART.GLASSES));
|
||||
this.parts.set(DRESS_PART.HAT, new BasePart(this.petBodySkeleton, DRESS_PART.HAT));
|
||||
this.parts.set(DRESS_PART.ACCESS, new BasePart(this.petBodySkeleton, DRESS_PART.ACCESS));
|
||||
}
|
||||
|
||||
public setInfo(info: PetInfo) {
|
||||
this.petInfo = info;
|
||||
}
|
||||
|
||||
public getInfo(): PetInfo {
|
||||
return this.petInfo;
|
||||
}
|
||||
|
||||
public async putOn(info: IDressInfo) {
|
||||
const { type, sourceLocationType, sourceName } = info;
|
||||
if (type == DRESS_PART.SUIT) {
|
||||
if (info.dressMap) {
|
||||
info.dressMap.forEach(async (dressInfo) => {
|
||||
await this.parts.get(dressInfo.type)?.putOn(dressInfo);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
await this.parts.get(type)?.putOn(info);
|
||||
}
|
||||
|
||||
public takeOff(type: DRESS_PART = DRESS_PART.ALL) {
|
||||
if (type == DRESS_PART.ALL) {
|
||||
this.parts.forEach((part) => {
|
||||
part.takeOff();
|
||||
});
|
||||
} else {
|
||||
this.parts.get(type)?.takeOff();
|
||||
}
|
||||
}
|
||||
|
||||
public playAnim(anim: PET_ANIM_NAME) {
|
||||
this.petBodySkeleton.setAnimation(0, anim, true);
|
||||
const faceAnim = PET_BODY_FACE_ANIM_MAP[anim] ?? PET_ANIM_NAME.IDLE;
|
||||
this.petFace.setAnimation(0, faceAnim, true);
|
||||
this.setFaceSkinFromAnim(faceAnim);
|
||||
}
|
||||
|
||||
protected setFaceSkinFromAnim(faceAnim: PET_ANIM_NAME) {
|
||||
let faceSkin: string = faceAnim;
|
||||
if (!COMMON_FACE_ANIM.includes(faceAnim)) {
|
||||
faceSkin = `eye/${this.petInfo.name}`;
|
||||
}
|
||||
this.petFace.setSkin(faceSkin);
|
||||
this.petFace._skeleton?.slots.forEach((slot) => {
|
||||
const slotName = slot.data.name.toLowerCase();
|
||||
if (slotName.endsWith("_hui")) {
|
||||
slot.color.a = slotName == `${this.petInfo.name}_hui`.toLowerCase() ? 1 : 0;
|
||||
}
|
||||
if (slotName.startsWith("dk")) {
|
||||
console.log("slotName:", slotName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
9
assets/games/scripts/pets/BasePet.ts.meta
Normal file
9
assets/games/scripts/pets/BasePet.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "5df90b9c-7a32-4e70-b46f-1510986c73d4",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
3
assets/games/scripts/pets/FacePart.ts
Normal file
3
assets/games/scripts/pets/FacePart.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { BasePart } from "./BasePart";
|
||||
|
||||
export class FacePart extends BasePart {}
|
||||
9
assets/games/scripts/pets/FacePart.ts.meta
Normal file
9
assets/games/scripts/pets/FacePart.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "dbc0d9b3-b0a1-4121-8e48-9c991101a10b",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
90
assets/games/scripts/pets/GlarePart.ts
Normal file
90
assets/games/scripts/pets/GlarePart.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { easing, instantiate, Node, Prefab, sp, tween, Tween, Vec3 } from "cc";
|
||||
import { BasePart } from "./BasePart";
|
||||
import { DRESS_PART, DRESS_SOURCE_TYPE, IDressInfo } from "./Types";
|
||||
import ResManager from "@max-studio/core/res/ResManager";
|
||||
|
||||
const GLARE_NODE_NAME = "glare";
|
||||
const GLARE_DEFAULT_POSITION = new Vec3(-170, 0, 0);
|
||||
|
||||
export class GlarePart extends BasePart {
|
||||
private glareNode: Node = null;
|
||||
private glareSpine: sp.Skeleton = null;
|
||||
private glarePrefab: Prefab = null;
|
||||
|
||||
constructor(ske: sp.Skeleton, part: DRESS_PART) {
|
||||
super(ske, part);
|
||||
this.getGlareNode();
|
||||
}
|
||||
|
||||
public async putOn(info: IDressInfo) {
|
||||
this.takeOff();
|
||||
this.info = info;
|
||||
const loadInfo = await ResManager.getInstance().loadAsset({
|
||||
bundle: "dress-spine",
|
||||
path: `DressGlare/${info.sourceName}`,
|
||||
type: Prefab,
|
||||
});
|
||||
if (loadInfo.err) {
|
||||
console.error("加载宠物_槽位_失败", loadInfo.err);
|
||||
return;
|
||||
}
|
||||
this.glarePrefab = loadInfo.asset;
|
||||
const node = instantiate(loadInfo.asset);
|
||||
node.name = "sp";
|
||||
node.setParent(this.glareNode);
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
this.glareSpine = node.getComponent(sp.Skeleton);
|
||||
this.glareSpine.setAnimation(0, "animation", false);
|
||||
this.glareNode.setScale(this.skeleton.node.scale);
|
||||
Tween.stopAllByTarget(this.glareNode);
|
||||
const dir = this.glareNode.scale.x;
|
||||
GLARE_DEFAULT_POSITION.x = dir > 0 ? -170 : 170;
|
||||
|
||||
tween(this.glareNode).to(0.35, { position: GLARE_DEFAULT_POSITION }, { easing: easing.sineOut }).start();
|
||||
|
||||
if (this.info.sourceLocationType == DRESS_SOURCE_TYPE.NONE) {
|
||||
this.glareNode.setSiblingIndex(0);
|
||||
} else {
|
||||
this.glareNode.setSiblingIndex(this.glareNode.parent.children.length - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public takeOff() {
|
||||
if (this.glareSpine == null) {
|
||||
return;
|
||||
}
|
||||
if (this.glareSpine) {
|
||||
this.glareSpine.node.destroy();
|
||||
this.glareSpine = null;
|
||||
}
|
||||
|
||||
if (this.glarePrefab) {
|
||||
ResManager.getInstance().releaseAsset(this.glarePrefab);
|
||||
this.glarePrefab = null;
|
||||
}
|
||||
|
||||
if (this.glareNode) {
|
||||
Tween.stopAllByTarget(this.glareNode);
|
||||
}
|
||||
|
||||
this.info = null;
|
||||
}
|
||||
|
||||
private getGlareNode() {
|
||||
if (this.glareNode) {
|
||||
return this.glareNode;
|
||||
}
|
||||
const root = this.skeleton.node.parent;
|
||||
if (!root) {
|
||||
console.error("没有找到根节点");
|
||||
return null;
|
||||
}
|
||||
this.glareNode = new Node(GLARE_NODE_NAME);
|
||||
this.glareNode.setParent(root);
|
||||
this.glareNode.setPosition(GLARE_DEFAULT_POSITION);
|
||||
this.glareNode.setSiblingIndex(0);
|
||||
return this.glareNode;
|
||||
}
|
||||
}
|
||||
9
assets/games/scripts/pets/GlarePart.ts.meta
Normal file
9
assets/games/scripts/pets/GlarePart.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "f5f29e43-e981-42ee-96c5-b993931e25e4",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/games/scripts/pets/GlassesPart.ts
Normal file
9
assets/games/scripts/pets/GlassesPart.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { BasePart } from "./BasePart";
|
||||
|
||||
export class GlassesPart extends BasePart {
|
||||
protected setSocketZIndex(): void {
|
||||
if (this.socketNode) {
|
||||
this.socketNode.setSiblingIndex(this.socketNode.parent.children.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
assets/games/scripts/pets/GlassesPart.ts.meta
Normal file
9
assets/games/scripts/pets/GlassesPart.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "86abc774-d404-4392-b642-463b5e5470dc",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
55
assets/games/scripts/pets/PetManager.ts
Normal file
55
assets/games/scripts/pets/PetManager.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import ResManager from "@max-studio/core/res/ResManager";
|
||||
import { Singleton } from "@max-studio/core/Singleton";
|
||||
import { instantiate, Prefab } from "cc";
|
||||
import { BasePet } from "./BasePet";
|
||||
import { releaseDressSocketNode } from "./PetUtils";
|
||||
|
||||
export class PetManager extends Singleton {
|
||||
private petPrefabCache: Map<string, Prefab> = new Map();
|
||||
|
||||
public async getPet(name: string): Promise<BasePet> {
|
||||
let asset: Prefab = null;
|
||||
if (this.petPrefabCache.has(name)) {
|
||||
asset = this.petPrefabCache.get(name);
|
||||
if (asset == null) {
|
||||
console.error(`宠物预制体缓存为空 ${name}`);
|
||||
return null;
|
||||
}
|
||||
asset.addRef();
|
||||
} else {
|
||||
const loadInfo = await ResManager.getInstance().loadAsset({
|
||||
bundle: "pet-spine",
|
||||
path: name,
|
||||
type: Prefab,
|
||||
});
|
||||
if (loadInfo.err) {
|
||||
console.error(`加载宠物预制体失败 ${name}`, loadInfo.err);
|
||||
return null;
|
||||
}
|
||||
asset = loadInfo.asset;
|
||||
this.petPrefabCache.set(name, asset);
|
||||
}
|
||||
const basePet = instantiate(asset).getOrAddComponent(BasePet);
|
||||
basePet.setInfo({ name: name });
|
||||
return basePet;
|
||||
}
|
||||
|
||||
public releasePet(pet: BasePet) {
|
||||
const petName = pet.getInfo().name;
|
||||
pet.takeOff();
|
||||
pet.node.removeFromParent();
|
||||
pet.node.destroy();
|
||||
if (this.petPrefabCache.has(petName)) {
|
||||
const prefab = this.petPrefabCache.get(petName);
|
||||
ResManager.getInstance().releaseAsset(prefab);
|
||||
if (prefab.refCount == 0) {
|
||||
this.petPrefabCache.delete(petName);
|
||||
console.log(`释放宠物预制体成功 ${petName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected onRelease(): void {
|
||||
releaseDressSocketNode();
|
||||
}
|
||||
}
|
||||
9
assets/games/scripts/pets/PetManager.ts.meta
Normal file
9
assets/games/scripts/pets/PetManager.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e9aeecff-fbae-4e76-8620-bb0f5664ad62",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
29
assets/games/scripts/pets/PetUtils.ts
Normal file
29
assets/games/scripts/pets/PetUtils.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import ResManager from "@max-studio/core/res/ResManager";
|
||||
import { Prefab } from "cc";
|
||||
|
||||
const DRESS_SOCKET_NODE_PATH = "prefabs/pet/DressSocketNode";
|
||||
let socketPrefab: Prefab = null;
|
||||
|
||||
export async function loadDressSocketNode(): Promise<Prefab> {
|
||||
if (socketPrefab != null) {
|
||||
return socketPrefab;
|
||||
}
|
||||
const loadInfo = await ResManager.getInstance().loadAsset({
|
||||
bundle: "games",
|
||||
path: DRESS_SOCKET_NODE_PATH,
|
||||
type: Prefab,
|
||||
});
|
||||
if (loadInfo.err) {
|
||||
console.error(`加载 DressSocketNode 失败: ${loadInfo.err}`);
|
||||
return null;
|
||||
}
|
||||
socketPrefab = loadInfo.asset;
|
||||
return socketPrefab;
|
||||
}
|
||||
|
||||
export function releaseDressSocketNode() {
|
||||
if (socketPrefab != null) {
|
||||
ResManager.getInstance().releaseAsset(socketPrefab);
|
||||
socketPrefab = null;
|
||||
}
|
||||
}
|
||||
9
assets/games/scripts/pets/PetUtils.ts.meta
Normal file
9
assets/games/scripts/pets/PetUtils.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "ccf9a987-4dc8-4993-856e-b9ea38c19731",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
125
assets/games/scripts/pets/Types.ts
Normal file
125
assets/games/scripts/pets/Types.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
export interface PetInfo {
|
||||
name: string;
|
||||
petId?: string;
|
||||
}
|
||||
|
||||
export interface IDressInfo {
|
||||
/**
|
||||
* 装扮部位
|
||||
*/
|
||||
type: DRESS_PART;
|
||||
sourceLocationType: DRESS_SOURCE_TYPE;
|
||||
sourceName: string;
|
||||
/**
|
||||
* 套装信息
|
||||
*/
|
||||
dressMap?: Map<number, IDressInfo>;
|
||||
}
|
||||
|
||||
export enum DRESS_PART {
|
||||
/**
|
||||
* 套装
|
||||
*/
|
||||
SUIT = 0,
|
||||
|
||||
/**
|
||||
* 背包
|
||||
*/
|
||||
BAG = 1,
|
||||
|
||||
/**
|
||||
* 帽子
|
||||
*/
|
||||
HAT = 2,
|
||||
|
||||
/**
|
||||
* 眼镜
|
||||
*/
|
||||
GLASSES = 3,
|
||||
|
||||
/**
|
||||
* 附件
|
||||
*/
|
||||
ACCESS = 4,
|
||||
|
||||
/**
|
||||
* 炫光
|
||||
*/
|
||||
GLARE = 5,
|
||||
|
||||
/**
|
||||
* 所有
|
||||
*/
|
||||
ALL = 6,
|
||||
}
|
||||
|
||||
export enum DRESS_SOURCE_TYPE {
|
||||
NONE = 0,
|
||||
|
||||
/**
|
||||
* 槽位
|
||||
*/
|
||||
SLOT = 1,
|
||||
|
||||
/**
|
||||
* 挂点静态图
|
||||
*/
|
||||
SOCKET_TEX = 2,
|
||||
|
||||
/**
|
||||
* 挂点动画
|
||||
*/
|
||||
SOCKET_SPINE = 3,
|
||||
|
||||
/**
|
||||
* 挂点静态图-脸
|
||||
*/
|
||||
SOCKET_TEX_FACE = 4,
|
||||
|
||||
/**
|
||||
* 挂点动画-脸
|
||||
*/
|
||||
SOCKET_SPINE_FACE = 5,
|
||||
}
|
||||
|
||||
export const SPINE_SLOT: Record<number, string> = {
|
||||
[DRESS_PART.BAG]: "glasses/bag",
|
||||
[DRESS_PART.HAT]: "glasses/zs_hat_01",
|
||||
[DRESS_PART.GLASSES]: "glasses/zs_glass_01",
|
||||
[DRESS_PART.ACCESS]: "glasses/zs_hdi_01",
|
||||
};
|
||||
|
||||
export const SPINE_SOCKET: Record<number, string> = {
|
||||
[DRESS_PART.BAG]: "Bag",
|
||||
[DRESS_PART.HAT]: "Hat",
|
||||
[DRESS_PART.GLASSES]: "Glasses",
|
||||
[DRESS_PART.ACCESS]: "ZS",
|
||||
};
|
||||
|
||||
export enum PET_ANIM_NAME {
|
||||
IDLE = "idle",
|
||||
HAPPY = "happy",
|
||||
SLEEP = "sleep",
|
||||
VERTIGO = "vertigo",
|
||||
EAT = "eat",
|
||||
MOTOU = "motou",
|
||||
RUN = "run",
|
||||
WALK = "walk",
|
||||
PLAY = "hudong_hudie",
|
||||
ANGRY = "angry",
|
||||
}
|
||||
|
||||
export const PET_BODY_FACE_ANIM_MAP: Record<PET_ANIM_NAME, PET_ANIM_NAME> = {
|
||||
[PET_ANIM_NAME.IDLE]: PET_ANIM_NAME.IDLE,
|
||||
[PET_ANIM_NAME.HAPPY]: PET_ANIM_NAME.HAPPY,
|
||||
[PET_ANIM_NAME.SLEEP]: PET_ANIM_NAME.SLEEP,
|
||||
[PET_ANIM_NAME.VERTIGO]: PET_ANIM_NAME.VERTIGO,
|
||||
[PET_ANIM_NAME.EAT]: PET_ANIM_NAME.HAPPY,
|
||||
[PET_ANIM_NAME.MOTOU]: PET_ANIM_NAME.MOTOU,
|
||||
[PET_ANIM_NAME.RUN]: PET_ANIM_NAME.IDLE,
|
||||
[PET_ANIM_NAME.WALK]: PET_ANIM_NAME.IDLE,
|
||||
[PET_ANIM_NAME.PLAY]: PET_ANIM_NAME.HAPPY,
|
||||
[PET_ANIM_NAME.ANGRY]: PET_ANIM_NAME.ANGRY,
|
||||
};
|
||||
|
||||
export const COMMON_FACE_ANIM = [PET_ANIM_NAME.SLEEP, PET_ANIM_NAME.ANGRY, PET_ANIM_NAME.VERTIGO, PET_ANIM_NAME.HAPPY];
|
||||
9
assets/games/scripts/pets/Types.ts.meta
Normal file
9
assets/games/scripts/pets/Types.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "25f7a591-83b6-4490-9f3f-bc18d0dfbf76",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
3
assets/games/scripts/pets/index.ts
Normal file
3
assets/games/scripts/pets/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// import BasePet from "./BasePet";
|
||||
export { PetManager } from "./PetManager";
|
||||
export { BasePet } from "./BasePet";
|
||||
9
assets/games/scripts/pets/index.ts.meta
Normal file
9
assets/games/scripts/pets/index.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "d269dbc8-fcc2-48c2-8f83-4c35dcb4a760",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import BaseToast from "@max-studio/core/ui/BaseToast";
|
||||
import { uiConfig, UIType } from "@max-studio/core/ui/UIDecorator";
|
||||
import UIManager from "@max-studio/core/ui/UIManager";
|
||||
import { SpriteAtlas, tween, Vec3, UITransform } from "cc";
|
||||
import { SpriteAtlas, tween, Vec3 } from "cc";
|
||||
import { RichText } from "cc";
|
||||
import { _decorator, Component, Node } from "cc";
|
||||
import { _decorator, Node } from "cc";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@uiConfig({
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { _decorator } from "cc";
|
||||
import { _decorator, SpriteFrame } from "cc";
|
||||
|
||||
import BaseLayer from "@max-studio/core/ui/BaseLayer";
|
||||
import { uiConfig, UIType } from "@max-studio/core/ui/UIDecorator";
|
||||
import UIManager from "@max-studio/core/ui/UIManager";
|
||||
import { CommonDialogBox } from "./CommonDialogBox";
|
||||
import { CommonToast } from "./CommonToast";
|
||||
import { ResManager } from "@max-studio/core/res/ResManager";
|
||||
import { SpriteAtlas } from "cc";
|
||||
import { uiConfig } from "@max-studio/core/ui/UIDecorator";
|
||||
|
||||
const { ccclass, property, menu } = _decorator;
|
||||
const globalSpriteFrame: SpriteFrame | null = null; // 全局变量
|
||||
|
||||
@ccclass("MainUI")
|
||||
@uiConfig({
|
||||
@@ -17,6 +13,4 @@ const { ccclass, property, menu } = _decorator;
|
||||
isCache: false,
|
||||
})
|
||||
@menu("max/ui/MainUI")
|
||||
export class MainUI extends BaseLayer {
|
||||
async onShow(...args: any[]) {}
|
||||
}
|
||||
export class MainUI extends BaseLayer {}
|
||||
|
||||
@@ -17,7 +17,7 @@ const { ccclass, property, menu } = _decorator;
|
||||
export class ShopUI extends BaseLayer {
|
||||
protected onLoad(): void {
|
||||
// ProtoDefinitions.pkg1.User
|
||||
let user = new ProtoDefinitions.pkg1.User();
|
||||
const user = new ProtoDefinitions.pkg1.User();
|
||||
console.log(user, ProtoDefinitions.pkg1.User.encode(user));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user