美术更新

- detail页面修改
- ui布局修改
This commit is contained in:
2025-08-25 20:15:42 +08:00
parent 2ae00f5c23
commit d6c3c775b5
183 changed files with 22192 additions and 12914 deletions
@@ -0,0 +1,52 @@
import { _decorator, Button, Component, Node, NodeEventType, Sprite } from "cc";
const { ccclass, property } = _decorator;
@ccclass("SimpleToggle")
export class SimpleToggle extends Component {
@property(Sprite)
selectedSprite: Sprite = null;
@property(Sprite)
unSelectedSprite: Sprite = null;
callback: () => {};
toggleGroupCallBack: Function;
btn: Button;
protected onLoad(): void {
this.node.on(NodeEventType.TOUCH_START, this.onClickThis, this);
this.btn = this.getComponent(Button);
}
init(isSelected: boolean, callBack: () => {}) {
this.selectedSprite.enabled = isSelected;
this.unSelectedSprite.enabled = !isSelected;
if (this.callback) {
this.onDestroy();
}
this.callback = callBack;
this.node.on(NodeEventType.TOUCH_START, this.onClickThis, this);
}
refresh(isSelected: boolean) {
this.selectedSprite.enabled = isSelected;
this.unSelectedSprite.enabled = !isSelected;
}
onClickThis() {
if (this.callback) {
this.callback();
}
if (this.toggleGroupCallBack) {
this.toggleGroupCallBack(this.node);
}
this.btn.interactable = false;
}
protected onDestroy(): void {
this.node.off(NodeEventType.TOUCH_START, this.onClickThis, this);
this.callback = null;
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "74d7e427-0f9b-414a-90a1-e75bef954d99",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,38 @@
import { _decorator, Component, Node, tween, Vec3 } from "cc";
import { SimpleToggle } from "./SimpleToggle";
const { ccclass, property } = _decorator;
@ccclass("SimpleToggleGroup")
export class SimpleToggleGroup extends Component {
toggles: SimpleToggle[];
@property(Node)
slider: Node;
protected onLoad(): void {
this.toggles = this.getComponentsInChildren(SimpleToggle);
for (let i = 0; i < this.toggles.length; i++) {
const element = this.toggles[i];
element.toggleGroupCallBack = this.toggleSelected.bind(this);
}
}
toggleSelected(selectedNode: Node) {
const pos = this.slider.getWorldPosition();
const targetPos = new Vec3(selectedNode.worldPosition.x, pos.y, pos.z);
tween(this.slider)
.to(0.3, { worldPosition: targetPos }, { easing: "sineInOut" })
.start();
for (let i = 0; i < this.toggles.length; i++) {
const element = this.toggles[i];
if (element.node === selectedNode) {
element.refresh(true);
} else {
element.refresh(false);
element.btn.interactable = true;
}
}
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "bf84c159-6fa3-4211-97f6-2c9618bd9bac",
"files": [],
"subMetas": {},
"userData": {}
}
+20 -2
View File
@@ -23,6 +23,7 @@ import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
import { VideoRoleType } from "db://assets/Scripts/Main/Common/GlobalValue";
import ConfigManager from "../../manager/ConfigManager";
import LanguageUtils from "../../../Main/Common/LanguageUtils";
import { UITransitionHelper } from "../../utils/UITransitionHelper";
const { ccclass, property } = _decorator;
@ccclass("ChatPanel")
@@ -55,9 +56,26 @@ export class ChatPanel extends li_BaseView {
};
openUIDataCT(data) {
this.id = data;
// 处理新的数据格式,支持过渡动画参数
if (typeof data === 'object' && data.roleId !== undefined) {
this.id = data.roleId;
// 如果标记了需要滑入动画,则执行动画
if (data.withSlideTransition && this.node && this.node.isValid) {
// 延迟一帧执行动画,确保节点已正确加载到场景中
this.scheduleOnce(() => {
UITransitionHelper.slideInFromRight(this.node, 0.3);
}, 0);
}
} else {
// 兼容原来的数字格式
this.id = data;
}
// 设置当前聊天的角色ID
ChatAIService.Instance.setCurrentRole(this.id);
if (this.id && this.id > 0) {
ChatAIService.Instance.setCurrentRole(this.id);
}
}
onLoadCT() {
@@ -15,6 +15,8 @@ import ConfigManager from "../../manager/ConfigManager";
import LanguageUtils from "../../../Main/Common/LanguageUtils";
import Utils from "../../../Main/Common/Utils";
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
import { SimpleToggle } from "../components/SimpleToggle";
import { GirlDetail } from "../../../schema/schema";
const { ccclass, property } = _decorator;
@@ -27,6 +29,11 @@ export class GirlDetailPanel extends li_BaseView {
@property(Label)
girlName: Label;
@property(SimpleToggle)
imgToggle: SimpleToggle = null;
@property(SimpleToggle)
videoToggle: SimpleToggle = null;
@property(Node)
starParent: Node;
@@ -67,6 +74,18 @@ export class GirlDetailPanel extends li_BaseView {
}
this.tags.string = desc;
});
this.imgToggle.callback = this.bindImgToggle.bind(this);
this.videoToggle.callback = this.bindVideoToggle.bind(this);
// 添加视频加载完成回调
this.avatarVideo.node.on(
VideoPlayer.EventType.READY_TO_PLAY,
() => {
this.adjustVideoScale();
},
this
);
}
setVideEnable(enable: boolean) {
@@ -86,8 +105,8 @@ export class GirlDetailPanel extends li_BaseView {
this.avatarVideo.node.parent.getComponent(UITransform);
const videoTransform = this.avatarVideo.node.getComponent(UITransform);
if (parentTransform && videoTransform && videoTransform.height > 0) {
const scale = parentTransform.height / videoTransform.height;
if (parentTransform && videoTransform && videoTransform.width > 0) {
const scale = parentTransform.width / videoTransform.width;
this.avatarVideo.node.setScale(scale, scale, 1);
console.log(
`Video scaled to: ${scale}, parent height: ${parentTransform.height}, video height: ${videoTransform.height}`
@@ -114,47 +133,14 @@ export class GirlDetailPanel extends li_BaseView {
tagKey: string;
category;
refresh(index: number) {
console.log(index);
const dataDetail = ConfigManager.tables.TbGirlsDetail.get(this.id);
console.log(dataDetail);
const data = ConfigManager.tables.TbGirls.get(this.id);
this.category = data.category;
this.nameKey = data.nameKey;
this.girlName.string = LanguageUtils.getText(data.nameKey);
if (dataDetail.pics[0].endsWith("video")) {
ResManager.I.changeBundleVideo(
this.avatarVideo,
dataDetail.pics[0],
"Chat18x"
);
// 添加视频加载完成回调
this.avatarVideo.node.on(
VideoPlayer.EventType.READY_TO_PLAY,
() => {
this.adjustVideoScale();
},
this
);
// 也立即尝试调整(以防已经加载完成)
this.adjustVideoScale();
}
if (dataDetail.pics.length > 1) {
for (let i = this.imgsLayout.children.length - 1; i >= 0; i--) {
this.imgsLayout.children[i].destroy();
}
for (let i = 1; i < dataDetail.pics.length; i++) {
const path = dataDetail.pics[i];
let newNode = instantiate(this.imgItemInst.node);
let item = newNode.getComponent(DetailImageItem);
item.refresh(path, this);
newNode.active = true;
this.imgsLayout.addChild(newNode);
}
}
this.desc.string = dataDetail.detailDesc;
let desc = "";
this.tagKey = data.tagKey;
@@ -170,11 +156,47 @@ export class GirlDetailPanel extends li_BaseView {
this.descAge.string = data.age.toString();
this.desc.string = dataDetail.detailDesc;
this.id = data.id;
ResManager.I.changeBundleVideo(
this.avatarVideo,
dataDetail.vids[0],
"Chat18x"
);
// 也立即尝试调整(以防已经加载完成)
this.adjustVideoScale();
this.vids = dataDetail.vids.slice(0);
this.refreshImgs(dataDetail.pics, true);
}
vids: string[];
bindImgToggle() {
const dataDetail = ConfigManager.tables.TbGirlsDetail.get(this.id);
this.refreshImgs(dataDetail.pics, true);
}
bindVideoToggle() {
this.refreshImgs(this.vids, false);
}
refreshImgs(paths: string[], isImg: boolean) {
for (let i = this.imgsLayout.children.length - 1; i >= 0; i--) {
this.imgsLayout.children[i].destroy();
}
for (let i = 1; i < paths.length; i++) {
const path = paths[i];
let newNode = instantiate(this.imgItemInst.node);
let item = newNode.getComponent(DetailImageItem);
item.refresh(path, this, isImg);
newNode.active = true;
this.imgsLayout.addChild(newNode);
}
}
OnClickChatBtn() {
NavigationManager.Instance.navigateToChat(this.id);
this.onClose();
// 使用带过渡动画的导航方法
NavigationManager.Instance.navigateToChatWithTransition(this.id, this);
// 注意:不在这里直接调用onClose,而是在动画完成后由NavigationManager调用
}
returnBtn() {
@@ -0,0 +1,32 @@
import { _decorator, Component, Label, Node } from "cc";
const { ccclass, property } = _decorator;
@ccclass("PayToTalkSubpanel")
export class PayToTalkSubpanel extends Component {
@property(Label)
timeLabel: Label = null;
@property(Label)
timeBtnLabel: Label = null;
@property(Label)
vipLabel: Label = null;
@property(Label)
vipBtnLabel: Label = null;
show() {}
refresh() {}
onClick_BuyTime() {
//购买次数
console.log("购买聊天次数,未实现功能");
}
onClick_BuyVip() {
//购买VIP
console.log("购买vip,未实现功能");
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "06f47bba-7287-4f26-876e-9e9ea87dac74",
"files": [],
"subMetas": {},
"userData": {}
}
+93 -40
View File
@@ -1,58 +1,111 @@
import { _decorator, Component, Node,Sprite ,UITransform} from 'cc';
import {
_decorator,
Component,
Node,
Sprite,
UITransform,
VideoPlayer,
view,
} from "cc";
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
import Utils from "db://assets/Scripts/Main/Common/Utils";
import {ViewManager} from "db://assets/Scripts/Main/Manager/ViewManager";
import {GButton} from "db://assets/Scripts/Main/Common/GButton";
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
import { GButton } from "db://assets/Scripts/Main/Common/GButton";
const { ccclass, property } = _decorator;
interface ShowPanelData
{
url: string;
closeFunc:Function;
interface ShowPanelData {
url: string;
isImg: boolean;
closeFunc: Function;
}
@ccclass('ShowPanel')
@ccclass("ShowPanel")
export class ShowPanel extends li_BaseView {
@property(Sprite)
image:Sprite;
@property(Sprite)
splash:Sprite;
@property(Sprite)
image: Sprite;
@property(Sprite)
splash: Sprite;
@property(VideoPlayer)
videoPlayer: VideoPlayer;
url:string;
func:Function;
openUIDataCT(data:ShowPanelData) {
super.openUIDataCT(data);
this.url = data.url;
this.func = data.closeFunc;
url: string;
func: Function;
isImg: boolean;
openUIDataCT(data: ShowPanelData) {
super.openUIDataCT(data);
this.url = data.url;
this.isImg = data.isImg;
this.func = data.closeFunc;
}
onLoadCT() {
this.show(this.url);
// 添加视频加载完成回调
this.videoPlayer.node.on(
VideoPlayer.EventType.READY_TO_PLAY,
() => {
this.adjustVideoScale();
},
this
);
}
start() {
//this.splash.node.on(Node.EventType.TOUCH_START,this.onclickback);
GButton.BandClick(this.splash.node, this.onClose, this);
}
protected onClose() {
if (this.func) {
this.func();
}
super.onClose();
}
show(path: string) {
if (this.isImg) {
ResManager.I.changeBundleSpriteFrame(this.image, path, "Chat18x", () => {
Utils.adjustBgPixelRatio(this.image.node, 3);
});
} else {
ResManager.I.changeBundleVideo(this.videoPlayer, path, "Chat18x", () => {
this.adjustVideoScale();
});
}
}
adjustVideoScale() {
if (!this.videoPlayer) {
return;
}
onLoadCT() {
this.show(this.url);
const tryAdjustScale = () => {
const screenSize = view.getVisibleSize();
}
const videoTransform = this.videoPlayer.node.getComponent(UITransform);
start()
{
//this.splash.node.on(Node.EventType.TOUCH_START,this.onclickback);
GButton.BandClick(this.splash.node,this.onClose,this);
}
if (videoTransform && videoTransform.height > 0) {
let scale = screenSize.width / videoTransform.width;
this.videoPlayer.node.setScale(scale, scale, 1);
return true;
}
return false;
};
protected onClose() {
if(this.func)
{
this.func();
// 立即尝试一次
if (!tryAdjustScale()) {
// 如果失败,延迟尝试
this.scheduleOnce(() => {
if (!tryAdjustScale()) {
// 再次延迟尝试
this.scheduleOnce(() => {
tryAdjustScale();
}, 0.5);
}
super.onClose();
}
show(path:string)
{
ResManager.I.changeBundleSpriteFrame(this.image,path,"Chat18x",()=>{
Utils.adjustBgPixelRatio(this.image.node,3);
});
}, 0.1);
}
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "0142e264-5c4f-407b-bb0c-57dd721980e3",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,126 @@
import {
_decorator,
Component,
Sprite,
UITransform,
Size,
isValid,
Node,
} from "cc";
const { ccclass } = _decorator;
/**
* 父物体自适应调整组件
* 功能:使精灵保持原始宽高比并覆盖整个父物体区域
* 触发时机:GameObject 激活时、父物体尺寸变化时
*/
@ccclass("ParentResize")
export class ParentResize extends Component {
private sprite: Sprite = null;
private uiTransform: UITransform = null;
private parentTransform: UITransform = null;
private lastParentSize: Size = new Size();
onLoad() {
// 获取必要组件
this.sprite = this.getComponent(Sprite);
this.uiTransform = this.getComponent(UITransform);
if (!this.sprite) {
console.warn("ParentResize: 未找到 Sprite 组件");
return;
}
if (!this.uiTransform) {
console.warn("ParentResize: 未找到 UITransform 组件");
return;
}
// 获取父物体的 UITransform
if (this.node.parent) {
this.parentTransform = this.node.parent.getComponent(UITransform);
if (!this.parentTransform) {
console.warn("ParentResize: 父物体未找到 UITransform 组件");
return;
}
} else {
console.warn("ParentResize: 未找到父物体");
return;
}
}
onEnable() {
// 激活时立即调整尺寸
this.adjustToParent();
}
/**
* 调整精灵尺寸以覆盖整个父物体区域
* 保持原始宽高比,使用 cover 策略
*/
private adjustToParent() {
if (
!isValid(this.sprite) ||
!isValid(this.uiTransform) ||
!isValid(this.parentTransform)
) {
return;
}
const spriteFrame = this.sprite.spriteFrame;
if (!spriteFrame) {
return;
}
// 获取父物体尺寸
const parentSize = this.parentTransform.contentSize;
// 获取精灵原始尺寸
const originalSize = spriteFrame.originalSize;
if (!originalSize || originalSize.width <= 0 || originalSize.height <= 0) {
return;
}
// 如果父物体尺寸无效,则不进行调整
if (parentSize.width <= 0 || parentSize.height <= 0) {
return;
}
// 计算缩放比例(使用较大值以确保覆盖整个父物体区域)
const scaleX = parentSize.width / originalSize.width;
const scaleY = parentSize.height / originalSize.height;
const scale = Math.max(scaleX, scaleY);
// 计算新的尺寸
const newWidth = originalSize.width * scale;
const newHeight = originalSize.height * scale;
// 应用新尺寸
this.uiTransform.setContentSize(newWidth, newHeight);
}
/**
* 手动触发尺寸调整
* 可在外部调用,例如当 SpriteFrame 改变时或父物体尺寸手动改变时
*/
public forceResize() {
this.adjustToParent();
}
/**
* 设置新的父物体
* 当需要动态改变参考父物体时调用
*/
public setParent(parentNode: Node) {
if (parentNode) {
this.parentTransform = parentNode.getComponent(UITransform);
if (this.parentTransform) {
this.lastParentSize.set(0, 0); // 重置上次记录的尺寸
this.adjustToParent();
} else {
console.warn("ParentResize: 新父物体未找到 UITransform 组件");
}
}
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "5ce148f6-6db7-4f09-a11d-3753b3e27771",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,88 @@
import {
_decorator,
Component,
Sprite,
UITransform,
view,
Size,
isValid,
} from "cc";
const { ccclass } = _decorator;
/**
* 精灵自动调整组件
* 功能:使精灵保持原始宽高比并覆盖整个屏幕
* 触发时机:GameObject 激活时、屏幕尺寸变化时
*/
@ccclass("SpriteResize")
export class SpriteResize extends Component {
private sprite: Sprite = null;
private uiTransform: UITransform = null;
private lastScreenSize: Size = new Size();
onLoad() {
// 获取必要组件
this.sprite = this.getComponent(Sprite);
this.uiTransform = this.getComponent(UITransform);
if (!this.sprite) {
console.warn("SpriteResize: 未找到 Sprite 组件");
return;
}
if (!this.uiTransform) {
console.warn("SpriteResize: 未找到 UITransform 组件");
return;
}
}
onEnable() {
// 激活时立即调整尺寸
this.adjustSize();
}
/**
* 调整精灵尺寸以覆盖整个屏幕
* 保持原始宽高比,使用 cover 策略
*/
private adjustSize() {
if (!isValid(this.sprite) || !isValid(this.uiTransform)) {
return;
}
const spriteFrame = this.sprite.spriteFrame;
if (!spriteFrame) {
return;
}
// 获取屏幕尺寸
const screenSize = view.getVisibleSize();
// 获取精灵原始尺寸
const originalSize = spriteFrame.originalSize;
if (!originalSize || originalSize.width <= 0 || originalSize.height <= 0) {
return;
}
// 计算缩放比例(使用较大值以确保覆盖全屏)
const scaleX = screenSize.width / originalSize.width;
const scaleY = screenSize.height / originalSize.height;
const scale = Math.max(scaleX, scaleY);
// 计算新的尺寸
const newWidth = originalSize.width * scale;
const newHeight = originalSize.height * scale;
// 应用新尺寸
this.uiTransform.setContentSize(newWidth, newHeight);
}
/**
* 手动触发尺寸调整
* 可在外部调用,例如当 SpriteFrame 改变时
*/
public forceResize() {
this.adjustSize();
}
}
@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "820fd6d5-5820-4dfa-aa21-333ad57e1876",
"files": [],
"subMetas": {},
"userData": {}
}