mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 14:24:53 +08:00
Add alert modal when manually inserting animations or skins.
This commit is contained in:
parent
5e33132153
commit
7f092113d8
@ -27,7 +27,6 @@
|
|||||||
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
// Common theme type
|
|
||||||
interface ModalTheme {
|
interface ModalTheme {
|
||||||
overlayBg: string;
|
overlayBg: string;
|
||||||
captionBg: string;
|
captionBg: string;
|
||||||
@ -43,38 +42,36 @@ interface ModalTheme {
|
|||||||
itemSelectedBg: string;
|
itemSelectedBg: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Create theme
|
|
||||||
function getTheme (darkMode: boolean): ModalTheme {
|
function getTheme (darkMode: boolean): ModalTheme {
|
||||||
return darkMode ? {
|
return darkMode ? {
|
||||||
overlayBg: 'rgba(0, 0, 0, 0.5)',
|
overlayBg: 'rgba(0, 0, 0, 0.5)',
|
||||||
captionBg: 'rgb(71, 71, 71)', // gray9
|
captionBg: 'rgb(71, 71, 71)',
|
||||||
captionText: 'rgb(214, 214, 214)', // gray27
|
captionText: 'rgb(214, 214, 214)',
|
||||||
contentBg: 'rgb(87, 87, 87)', // gray11
|
contentBg: 'rgb(87, 87, 87)',
|
||||||
contentText: 'rgb(214, 214, 214)', // gray27
|
contentText: 'rgb(214, 214, 214)',
|
||||||
buttonBg: 'rgb(71, 71, 71)', // gray9
|
buttonBg: 'rgb(71, 71, 71)',
|
||||||
buttonText: 'rgb(214, 214, 214)', // gray27
|
buttonText: 'rgb(214, 214, 214)',
|
||||||
buttonBorder: 'rgb(56, 56, 56)', // gray7
|
buttonBorder: 'rgb(56, 56, 56)',
|
||||||
buttonHoverBg: 'rgb(79, 79, 79)', // gray10
|
buttonHoverBg: 'rgb(79, 79, 79)',
|
||||||
closeColor: 'rgb(168, 168, 168)', // gray21
|
closeColor: 'rgb(168, 168, 168)',
|
||||||
itemHoverBg: 'rgb(79, 79, 79)', // gray10
|
itemHoverBg: 'rgb(79, 79, 79)',
|
||||||
itemSelectedBg: 'rgb(56, 56, 56)', // gray7
|
itemSelectedBg: 'rgb(56, 56, 56)',
|
||||||
} : {
|
} : {
|
||||||
overlayBg: 'rgba(0, 0, 0, 0.3)',
|
overlayBg: 'rgba(0, 0, 0, 0.3)',
|
||||||
captionBg: 'rgb(247, 247, 247)', // gray31
|
captionBg: 'rgb(247, 247, 247)',
|
||||||
captionText: 'rgb(94, 94, 94)', // gray12
|
captionText: 'rgb(94, 94, 94)',
|
||||||
contentBg: 'rgb(232, 232, 232)', // gray29
|
contentBg: 'rgb(232, 232, 232)',
|
||||||
contentText: 'rgb(94, 94, 94)', // gray12
|
contentText: 'rgb(94, 94, 94)',
|
||||||
buttonBg: 'rgb(222, 222, 222)', // gray28
|
buttonBg: 'rgb(222, 222, 222)',
|
||||||
buttonText: 'rgb(94, 94, 94)', // gray12
|
buttonText: 'rgb(94, 94, 94)',
|
||||||
buttonBorder: 'rgb(199, 199, 199)', // gray25
|
buttonBorder: 'rgb(199, 199, 199)',
|
||||||
buttonHoverBg: 'rgb(214, 214, 214)', // gray27
|
buttonHoverBg: 'rgb(214, 214, 214)',
|
||||||
closeColor: 'rgb(94, 94, 94)', // gray12
|
closeColor: 'rgb(94, 94, 94)',
|
||||||
itemHoverBg: 'rgb(214, 214, 214)', // gray27
|
itemHoverBg: 'rgb(214, 214, 214)',
|
||||||
itemSelectedBg: 'rgb(199, 199, 199)', // gray25
|
itemSelectedBg: 'rgb(199, 199, 199)',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Create overlay
|
|
||||||
function createOverlay (theme: ModalTheme): HTMLDivElement {
|
function createOverlay (theme: ModalTheme): HTMLDivElement {
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
overlay.style.cssText = `
|
overlay.style.cssText = `
|
||||||
@ -94,7 +91,6 @@ function createOverlay (theme: ModalTheme): HTMLDivElement {
|
|||||||
return overlay;
|
return overlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Create dialog
|
|
||||||
function createDialog (theme: ModalTheme, minWidth: number): HTMLDivElement {
|
function createDialog (theme: ModalTheme, minWidth: number): HTMLDivElement {
|
||||||
const dialog = document.createElement('div');
|
const dialog = document.createElement('div');
|
||||||
dialog.style.cssText = `
|
dialog.style.cssText = `
|
||||||
@ -109,7 +105,6 @@ function createDialog (theme: ModalTheme, minWidth: number): HTMLDivElement {
|
|||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Create caption with close button
|
|
||||||
function createCaption (title: string, theme: ModalTheme, onClose: () => void): HTMLDivElement {
|
function createCaption (title: string, theme: ModalTheme, onClose: () => void): HTMLDivElement {
|
||||||
const caption = document.createElement('div');
|
const caption = document.createElement('div');
|
||||||
caption.style.cssText = `
|
caption.style.cssText = `
|
||||||
@ -149,7 +144,6 @@ function createCaption (title: string, theme: ModalTheme, onClose: () => void):
|
|||||||
return caption;
|
return caption;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Create footer
|
|
||||||
function createFooter (): HTMLDivElement {
|
function createFooter (): HTMLDivElement {
|
||||||
const footer = document.createElement('div');
|
const footer = document.createElement('div');
|
||||||
footer.style.cssText = `
|
footer.style.cssText = `
|
||||||
@ -161,7 +155,6 @@ function createFooter (): HTMLDivElement {
|
|||||||
return footer;
|
return footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Create button
|
|
||||||
function createButton (text: string, theme: ModalTheme, onClick: () => void): HTMLButtonElement {
|
function createButton (text: string, theme: ModalTheme, onClick: () => void): HTMLButtonElement {
|
||||||
const btn = document.createElement('button');
|
const btn = document.createElement('button');
|
||||||
btn.textContent = text;
|
btn.textContent = text;
|
||||||
@ -181,7 +174,6 @@ function createButton (text: string, theme: ModalTheme, onClick: () => void): HT
|
|||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper: Setup modal event handlers
|
|
||||||
function setupModalHandlers (overlay: HTMLDivElement, onCancel: () => void, extraKeyHandler?: (e: KeyboardEvent) => boolean) {
|
function setupModalHandlers (overlay: HTMLDivElement, onCancel: () => void, extraKeyHandler?: (e: KeyboardEvent) => boolean) {
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Escape') {
|
if (e.key === 'Escape') {
|
||||||
@ -193,7 +185,9 @@ function setupModalHandlers (overlay: HTMLDivElement, onCancel: () => void, extr
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
document.addEventListener('keydown', handleKeyDown);
|
document.addEventListener('keydown', handleKeyDown);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
overlay.addEventListener('click', (e) => {
|
overlay.addEventListener('click', (e) => {
|
||||||
if (e.target === overlay) {
|
if (e.target === overlay) {
|
||||||
@ -207,7 +201,6 @@ function setupModalHandlers (overlay: HTMLDivElement, onCancel: () => void, extr
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Original interfaces
|
|
||||||
interface ModalButton<T> {
|
interface ModalButton<T> {
|
||||||
text: string;
|
text: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
@ -324,11 +317,9 @@ export function showListSelectionModal (options: ListSelectionOptions): Promise<
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
itemDiv.addEventListener('click', () => {
|
itemDiv.addEventListener('click', () => {
|
||||||
// Deselect all items
|
|
||||||
contents.querySelectorAll('div').forEach(div => {
|
contents.querySelectorAll('div').forEach(div => {
|
||||||
div.style.background = 'transparent';
|
div.style.background = 'transparent';
|
||||||
});
|
});
|
||||||
// Select this item
|
|
||||||
itemDiv.style.background = theme.itemSelectedBg;
|
itemDiv.style.background = theme.itemSelectedBg;
|
||||||
selectedItem = item;
|
selectedItem = item;
|
||||||
});
|
});
|
||||||
@ -486,7 +477,6 @@ export function showMultiListSelectionModal (options: MultiListSelectionOptions)
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// Create checkbox
|
|
||||||
const checkbox = document.createElement('input');
|
const checkbox = document.createElement('input');
|
||||||
checkbox.type = 'checkbox';
|
checkbox.type = 'checkbox';
|
||||||
checkbox.checked = selectedSet.has(item);
|
checkbox.checked = selectedSet.has(item);
|
||||||
@ -515,7 +505,6 @@ export function showMultiListSelectionModal (options: MultiListSelectionOptions)
|
|||||||
};
|
};
|
||||||
|
|
||||||
itemDiv.addEventListener('click', (e) => {
|
itemDiv.addEventListener('click', (e) => {
|
||||||
// Don't toggle if clicking directly on checkbox (it handles itself)
|
|
||||||
if (e.target !== checkbox) {
|
if (e.target !== checkbox) {
|
||||||
toggleSelection();
|
toggleSelection();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,8 +126,9 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
if (id === PLUGIN_CLASS.PROP_SKIN) {
|
if (id === PLUGIN_CLASS.PROP_SKIN) {
|
||||||
this.skins = [];
|
this.skins = [];
|
||||||
|
|
||||||
const validatedString = this.validateSkinString();
|
const skinString = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKIN) as string;
|
||||||
if (validatedString) {
|
const validatedString = await this.validateSkinString(skinString);
|
||||||
|
if (validatedString !== undefined && validatedString !== skinString) {
|
||||||
this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_SKIN, validatedString);
|
this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_SKIN, validatedString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -138,6 +139,14 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id === PLUGIN_CLASS.PROP_ANIMATION) {
|
if (id === PLUGIN_CLASS.PROP_ANIMATION) {
|
||||||
|
|
||||||
|
const animationString = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_ANIMATION) as string;
|
||||||
|
const validatedString = await this.validateAnimationString(animationString);
|
||||||
|
if (validatedString !== undefined && validatedString !== this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_ANIMATION)) {
|
||||||
|
this._inst.SetPropertyValue(PLUGIN_CLASS.PROP_ANIMATION, validatedString);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setAnimation();
|
this.setAnimation();
|
||||||
this.layoutView?.Refresh();
|
this.layoutView?.Refresh();
|
||||||
return;
|
return;
|
||||||
@ -259,7 +268,6 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return zoom === -1 ? 1 : zoom;
|
return zoom === -1 ? 1 : zoom;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private setAnimation () {
|
private setAnimation () {
|
||||||
@ -267,14 +275,47 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
this.animation = propValue === "" ? undefined : propValue;
|
this.animation = propValue === "" ? undefined : propValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private validateSkinString () {
|
private async validateSkinString (skins: string) {
|
||||||
const skins = this._inst.GetPropertyValue(PLUGIN_CLASS.PROP_SKIN) as string;
|
if (skins === "" || !this.skeleton) return;
|
||||||
if (skins === "") return;
|
|
||||||
const split = skins.split(",");
|
|
||||||
|
|
||||||
if (!split.includes("")) return;
|
const split = skins.split(",").filter(s => s !== "");
|
||||||
|
if (split.length === 0) return;
|
||||||
|
|
||||||
return split.filter(s => s !== "").join(",");
|
const availableSkins = this.skeleton.data.skins.map(skin => skin.name).filter(s => s !== "default");
|
||||||
|
|
||||||
|
const invalidSkins = split.filter(skinName => !availableSkins.includes(skinName));
|
||||||
|
|
||||||
|
if (invalidSkins.length > 0) {
|
||||||
|
await spine.showAlertModal({
|
||||||
|
darkMode: false,
|
||||||
|
title: this.lang('invalid-skins.title'),
|
||||||
|
message: this.lang('invalid-skins.message', [invalidSkins.join(", ")])
|
||||||
|
});
|
||||||
|
|
||||||
|
const validSkins = split.filter(skinName => availableSkins.includes(skinName));
|
||||||
|
console.log(validSkins);
|
||||||
|
return validSkins.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
return split.join(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateAnimationString (animation: string) {
|
||||||
|
if (animation === "" || !this.skeleton) return;
|
||||||
|
|
||||||
|
const availableAnimations = this.skeleton.data.animations.map(anim => anim.name);
|
||||||
|
|
||||||
|
if (!availableAnimations.includes(animation)) {
|
||||||
|
await spine.showAlertModal({
|
||||||
|
darkMode: false,
|
||||||
|
title: this.lang('invalid-animation.title'),
|
||||||
|
message: this.lang('invalid-animation.message', [animation])
|
||||||
|
});
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setSkin () {
|
private setSkin () {
|
||||||
@ -483,10 +524,10 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
|
|
||||||
const errorTextC3 = iRenderer.CreateRendererText()
|
const errorTextC3 = iRenderer.CreateRendererText()
|
||||||
this.errorTextC3 = errorTextC3;
|
this.errorTextC3 = errorTextC3;
|
||||||
this.errorTextC3.SetFontSize(12);
|
errorTextC3.SetFontSize(12);
|
||||||
this.errorTextC3.SetColorRgb(1, 0, 0);
|
errorTextC3.SetColorRgb(1, 0, 0);
|
||||||
this.errorTextC3.SetTextureUpdateCallback(() => iLayoutView.Refresh());
|
errorTextC3.SetTextureUpdateCallback(() => iLayoutView.Refresh());
|
||||||
return this.errorTextC3;
|
return errorTextC3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private update (delta: number) {
|
private update (delta: number) {
|
||||||
@ -566,15 +607,15 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
const action = await spine.showModal({
|
const action = await spine.showModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
maxWidth: 500,
|
maxWidth: 500,
|
||||||
title: this.lang(`showModal.${type}.title`),
|
title: this.lang(`${type}.title`),
|
||||||
text: this.lang(`showModal.${type}.text`, [collisionSpriteName]),
|
text: this.lang(`${type}.message`, [collisionSpriteName]),
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
text: this.lang(`showModal.${type}.buttons.${0}`),
|
text: this.lang(`${type}.buttons.${0}`),
|
||||||
value: 'disable'
|
value: 'disable'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: this.lang(`showModal.${type}.buttons.${1}`, [collisionSpriteName]),
|
text: this.lang(`${type}.buttons.${1}`, [collisionSpriteName]),
|
||||||
color: '#d9534f',
|
color: '#d9534f',
|
||||||
value: 'delete'
|
value: 'delete'
|
||||||
}
|
}
|
||||||
@ -597,8 +638,8 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
if (!this.skeleton) {
|
if (!this.skeleton) {
|
||||||
await spine.showAlertModal({
|
await spine.showAlertModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
title: 'Error',
|
title: this.lang('skeleton-not-loaded.title'),
|
||||||
message: 'Skeleton not loaded. Please ensure atlas and skeleton files are set.',
|
message: this.lang('skeleton-not-loaded.message'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -607,15 +648,15 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
if (animations.length === 0) {
|
if (animations.length === 0) {
|
||||||
await spine.showAlertModal({
|
await spine.showAlertModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
title: 'No Animations',
|
title: this.lang('no-animations.title'),
|
||||||
message: 'No animations found in the skeleton.',
|
message: this.lang('no-animations.message'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedAnimation = await spine.showListSelectionModal({
|
const selectedAnimation = await spine.showListSelectionModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
title: 'Select Animation',
|
title: this.lang('select-animation.title'),
|
||||||
items: animations,
|
items: animations,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -628,8 +669,8 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
if (!this.skeleton) {
|
if (!this.skeleton) {
|
||||||
await spine.showAlertModal({
|
await spine.showAlertModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
title: 'Error',
|
title: this.lang('skeleton-not-loaded.title'),
|
||||||
message: 'Skeleton not loaded. Please ensure atlas and skeleton files are set.',
|
message: this.lang('skeleton-not-loaded.message'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -638,15 +679,15 @@ class SpineC3PluginInstance extends SDK.IWorldInstanceBase {
|
|||||||
if (skins.length === 0) {
|
if (skins.length === 0) {
|
||||||
await spine.showAlertModal({
|
await spine.showAlertModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
title: 'No Skins',
|
title: this.lang('no-skins.title'),
|
||||||
message: 'No skins found in the skeleton.',
|
message: this.lang('no-skins.message'),
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedSkins = await spine.showMultiListSelectionModal({
|
const selectedSkins = await spine.showMultiListSelectionModal({
|
||||||
darkMode: false,
|
darkMode: false,
|
||||||
title: 'Select Skins',
|
title: this.lang('select-skins.title'),
|
||||||
items: skins,
|
items: skins,
|
||||||
selectedItems: this.skins,
|
selectedItems: this.skins,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -689,15 +689,39 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"custom_ui": {
|
"custom_ui": {
|
||||||
"showModal": {
|
|
||||||
"spine-enable-collision": {
|
"spine-enable-collision": {
|
||||||
"title": "Delete Sprite Object Type",
|
"title": "Delete Sprite Object Type",
|
||||||
"text": "This is the last instance of {0}. You can delete the {0} or just disable the Sprite collision body. Deleting the Sprite collision body will remove all related ACEs in the event sheet, if there's any. How do you want to proceed?",
|
"message": "This is the last instance of {0}. You can delete the {0} or just disable the Sprite collision body. Deleting the Sprite collision body will remove all related ACEs in the event sheet, if there's any. How do you want to proceed?",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"0": "Just disable",
|
"0": "Just disable",
|
||||||
"1": "Disable and delete {0}"
|
"1": "Disable and delete {0}"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"skeleton-not-loaded": {
|
||||||
|
"title": "Error",
|
||||||
|
"message": "Skeleton not loaded. Please ensure atlas and skeleton files are set."
|
||||||
|
},
|
||||||
|
"no-animations": {
|
||||||
|
"title": "No Animations",
|
||||||
|
"message": "No animations found in the skeleton."
|
||||||
|
},
|
||||||
|
"no-skins": {
|
||||||
|
"title": "No Skins",
|
||||||
|
"message": "No skins found in the skeleton."
|
||||||
|
},
|
||||||
|
"select-animation": {
|
||||||
|
"title": "Select Animation"
|
||||||
|
},
|
||||||
|
"select-skins": {
|
||||||
|
"title": "Select Skins"
|
||||||
|
},
|
||||||
|
"invalid-skins": {
|
||||||
|
"title": "Invalid Skins",
|
||||||
|
"message": "The following skins do not exist in the skeleton: {0}.\n\nThey have been removed. Please use the \"Select skin\" button to choose from existing skins."
|
||||||
|
},
|
||||||
|
"invalid-animation": {
|
||||||
|
"title": "Invalid Animation",
|
||||||
|
"message": "The animation \"{0}\" does not exist in the skeleton.\n\nIt has been removed. Please use the \"Select animation\" button to choose from existing animations."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -689,15 +689,39 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"custom_ui": {
|
"custom_ui": {
|
||||||
"showModal": {
|
|
||||||
"spine-enable-collision": {
|
"spine-enable-collision": {
|
||||||
"title": "删除精灵对象类型",
|
"title": "删除精灵对象类型",
|
||||||
"text": "这是{0}的最后一个实例。您可以删除{0}或仅禁用精灵碰撞体。删除精灵碰撞体将移除事件表中所有相关的ACE(如果有)。您想如何继续?",
|
"message": "这是{0}的最后一个实例。您可以删除{0}或仅禁用精灵碰撞体。删除精灵碰撞体将移除事件表中所有相关的ACE(如果有)。您想如何继续?",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"0": "仅禁用",
|
"0": "仅禁用",
|
||||||
"1": "禁用并删除{0}"
|
"1": "禁用并删除{0}"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"skeleton-not-loaded": {
|
||||||
|
"title": "错误",
|
||||||
|
"message": "骨架未加载。请确保已设置图集和骨架文件。"
|
||||||
|
},
|
||||||
|
"no-animations": {
|
||||||
|
"title": "无动画",
|
||||||
|
"message": "在骨架中未找到动画。"
|
||||||
|
},
|
||||||
|
"no-skins": {
|
||||||
|
"title": "无皮肤",
|
||||||
|
"message": "在骨架中未找到皮肤。"
|
||||||
|
},
|
||||||
|
"select-animation": {
|
||||||
|
"title": "选择动画"
|
||||||
|
},
|
||||||
|
"select-skins": {
|
||||||
|
"title": "选择皮肤"
|
||||||
|
},
|
||||||
|
"invalid-skins": {
|
||||||
|
"title": "无效皮肤",
|
||||||
|
"message": "以下皮肤在骨架中不存在:{0}。\n\n它们已被删除。请使用\"选择皮肤\"按钮从现有皮肤中选择。"
|
||||||
|
},
|
||||||
|
"invalid-animation": {
|
||||||
|
"title": "无效动画",
|
||||||
|
"message": "动画\"{0}\"在骨架中不存在。\n\n它已被删除。请使用\"选择动画\"按钮从现有动画中选择。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user