Compare commits

..

4 Commits

Author SHA1 Message Date
206bed7dc0 feat: 工具栏整合成一个组件 2025-09-28 16:31:16 +08:00
7276380482 fix: 多行文本高度问题 2025-09-28 16:08:22 +08:00
5bdd41159b fix: 文本框的配置问题 2025-09-28 16:01:09 +08:00
71c88369e1 refactor: 文本相关事件的适配 2025-09-28 14:53:33 +08:00
16 changed files with 543 additions and 379 deletions

View File

@ -31,6 +31,7 @@ import {
TextAlign
} from './textboxTyper';
import { SetupComponentOptions } from '@motajs/system-ui';
import { texture } from '../elements';
//#region TextContent
@ -173,6 +174,8 @@ export const TextContent = defineComponent<
const renderContent = (canvas: MotaOffscreenCanvas2D) => {
const ctx = canvas.ctx;
ctx.textBaseline = 'top';
ctx.lineWidth = props.strokeWidth ?? 2;
ctx.lineJoin = 'round';
for (const data of renderable) {
if (data.cut) break;
switch (data.type) {
@ -181,14 +184,15 @@ export const TextContent = defineComponent<
ctx.fillStyle = data.fillStyle;
ctx.strokeStyle = data.strokeStyle;
ctx.font = data.font;
const text = data.text.slice(0, data.pointer);
if (props.fill ?? true) {
ctx.fillText(text, data.x, data.y);
}
if (props.stroke) {
ctx.strokeText(text, data.x, data.y);
}
if (props.fill ?? true) {
ctx.fillText(text, data.x, data.y);
}
break;
}
case TextContentType.Icon: {
@ -248,6 +252,8 @@ export interface TextboxProps extends TextContentProps, DefaultProps {
titleStroke?: CanvasStyle;
/** 标题文字与边框间的距离默认为4 */
titlePadding?: number;
/** 图标 */
icon?: AllIdsWithNone;
/** 最大宽度 */
width: number;
}
@ -307,30 +313,10 @@ export const Textbox = defineComponent<
keyof TextboxEmits,
TextboxSlots
>((props, { slots, expose, emit }) => {
const contentData = shallowReactive<TextContentProps>({ width: 200 });
const data = shallowReactive<TextboxProps>({ width: 200 });
const setContentData = () => {
contentData.breakChars = props.breakChars ?? '';
contentData.font = props.font ?? new Font();
contentData.ignoreLineEnd = props.ignoreLineEnd ?? '';
contentData.ignoreLineStart = props.ignoreLineStart ?? '';
contentData.interval = props.interval ?? 0;
contentData.keepLast = props.keepLast ?? false;
contentData.lineHeight = props.lineHeight ?? 0;
contentData.text = props.text ?? '';
contentData.textAlign = props.textAlign ?? TextAlign.Left;
contentData.wordBreak = props.wordBreak ?? WordBreak.Space;
contentData.fill = props.fill ?? true;
contentData.stroke = props.stroke ?? false;
contentData.fillStyle = props.fillStyle ?? '#fff';
contentData.strokeStyle = props.strokeStyle ?? '#000';
contentData.strokeWidth = props.strokeWidth ?? 2;
contentData.loc = props.loc;
contentData.width = props.width;
};
const setTextboxData = () => {
// Textbox
data.backColor = props.backColor ?? '#222';
data.winskin = props.winskin;
data.padding = props.padding ?? 8;
@ -341,9 +327,28 @@ export const Textbox = defineComponent<
data.width = props.width ?? props.loc?.[2] ?? 200;
data.height = props.height ?? props.loc?.[3] ?? 200;
data.title = props.title ?? '';
data.icon = props.icon;
// TextContent
data.breakChars = props.breakChars ?? '';
data.font = props.font ?? new Font();
data.ignoreLineEnd = props.ignoreLineEnd ?? '';
data.ignoreLineStart = props.ignoreLineStart ?? '';
data.interval = props.interval ?? 0;
data.keepLast = props.keepLast ?? false;
data.lineHeight = props.lineHeight ?? 0;
data.text = props.text ?? '';
data.textAlign = props.textAlign ?? TextAlign.Left;
data.wordBreak = props.wordBreak ?? WordBreak.Space;
data.fill = props.fill ?? true;
data.stroke = props.stroke ?? false;
data.fillStyle = props.fillStyle ?? '#fff';
data.strokeStyle = props.strokeStyle ?? '#000';
data.strokeWidth = props.strokeWidth ?? 2;
data.loc = props.loc;
data.width = props.width;
};
setContentData();
setTextboxData();
watch(props, () => {
@ -361,23 +366,53 @@ export const Textbox = defineComponent<
const tw = ref(data.titlePadding! * 2);
/** 标题高度 */
const th = ref(data.titlePadding! * 2);
const contentX = computed(() => {
if (hasIcon.value) {
return data.padding! + 40;
} else {
return data.padding!;
}
});
const contentY = computed(() => {
const height = th.value;
return data.title ? height : 0;
});
const backHeight = computed(() => data.height! - contentY.value);
const contentWidth = computed(() => data.width! - data.padding! * 2);
const contentWidth = computed(() => {
if (hasIcon.value) {
return data.width! - data.padding! * 2 - 40;
} else {
return data.width! - data.padding! * 2;
}
});
const contentHeight = computed(
() => data.height! - data.padding! * 2 - contentY.value
);
const iconLoc = computed<ElementLocator>(() => {
const y = contentY.value;
const pad = data.padding!;
const icon = data.icon;
if (isNil(icon) || icon === 'none') {
return [];
} else {
const num = texture.idNumberMap[icon];
const renderable = texture.getRenderable(num);
if (!renderable) return [];
const [, , w, h] = renderable.render[0];
return [pad, pad + y, w, h];
}
});
const hasIcon = computed(() => {
return !isNil(data.icon) && data.icon !== 'none';
});
const onSetText = () => {
nextTick(() => {
titleElement.value?.requestBeforeFrame(() => {
if (titleElement.value) {
const { width, height } = titleElement.value;
tw.value = width + data.padding! * 2;
th.value = height + data.padding! * 2;
tw.value = width + data.titlePadding! * 2;
th.value = height + data.titlePadding! * 2;
}
});
});
@ -385,6 +420,8 @@ export const Textbox = defineComponent<
//#region store
let lastTitle = data.title;
/** 结束打字机 */
const storeEmits: TextboxStoreEmits = {
endType() {
@ -397,23 +434,23 @@ export const Textbox = defineComponent<
hidden.value = false;
},
update(value) {
if (data.title !== value.title) {
data.title = value.title;
if (value.title !== lastTitle) {
onSetText();
lastTitle = value.title;
}
},
setText(text) {
if (contentData.text === text) {
if (data.text === text) {
content.value?.retype();
} else {
contentData.text = text;
data.text = text;
}
}
};
const store = TextboxStore.use(
props.id ?? getNextTextboxId(),
contentData,
data,
storeEmits
);
@ -447,7 +484,7 @@ export const Textbox = defineComponent<
id={props.id}
hidden={hidden.value}
alpha={data.alpha}
loc={props.loc}
loc={data.loc}
>
{data.title && (
<container zIndex={10} loc={[0, 0, tw.value, th.value]}>
@ -468,6 +505,7 @@ export const Textbox = defineComponent<
fillStyle={data.titleFill}
strokeStyle={data.titleStroke}
font={data.titleFont}
strokeWidth={2}
></text>
</container>
)}
@ -485,10 +523,23 @@ export const Textbox = defineComponent<
fillStyle={data.backColor}
></g-rect>
)}
{hasIcon.value && (
<icon icon={data.icon as AllIds} loc={iconLoc.value} animate />
)}
{hasIcon.value && (
<g-rect
loc={iconLoc.value}
strokeStyle="gold"
fillStyle="#222"
lineWidth={2}
fill
stroke
/>
)}
<TextContent
{...contentData}
{...data}
ref={content}
x={data.padding!}
x={contentX.value}
y={contentY.value + data.padding!}
width={contentWidth.value}
height={contentHeight.value}
@ -531,7 +582,7 @@ export class TextboxStore extends EventEmitter<TextboxStoreEvent> {
typing: boolean = false;
private constructor(
private readonly data: TextboxProps,
public readonly data: TextboxProps,
private readonly emits: TextboxStoreEmits
) {
super();

View File

@ -336,6 +336,12 @@ export class TextContentTyper extends EventEmitter<TextContentTyperEvent> {
this.config[key] = value;
}
}
if (config.font) {
this.config.fontFamily = config.font.family;
this.config.fontSize = config.font.size;
this.config.fontItalic = config.font.italic;
this.config.fontWeight = config.font.weight;
}
this.parser.setStatus({
fillStyle: this.config.fillStyle,
fontFamily: this.config.fontFamily,
@ -528,7 +534,8 @@ export class TextContentTyper extends EventEmitter<TextContentTyperEvent> {
return;
}
this.emit('typeStart');
this.lastTypeTime = Date.now();
// 减去间隔是为了第一个字可以立刻打出来,不然看起来有延迟
this.lastTypeTime = Date.now() - this.config.interval - 1;
this.typing = true;
}
@ -628,11 +635,11 @@ export class TextContentParser {
* @param st
*/
setStatus(st: Partial<ParserStatus>) {
if (!isNil(st.fillStyle)) this.status.fillStyle = st.fillStyle;
if (!isNil(st.fontSize)) this.status.fontSize = st.fontSize;
if (!isNil(st.fontFamily)) this.status.fontFamily = st.fontFamily;
if (!isNil(st.fontItalic)) this.status.fontItalic = st.fontItalic;
if (!isNil(st.fontWeight)) this.status.fontWeight = st.fontWeight;
if (!isNil(st.fillStyle)) this.initStatus.fillStyle = st.fillStyle;
if (!isNil(st.fontSize)) this.initStatus.fontSize = st.fontSize;
if (!isNil(st.fontFamily)) this.initStatus.fontFamily = st.fontFamily;
if (!isNil(st.fontItalic)) this.initStatus.fontItalic = st.fontItalic;
if (!isNil(st.fontWeight)) this.initStatus.fontWeight = st.fontWeight;
}
/**
@ -856,6 +863,7 @@ export class TextContentParser {
this.font = this.buildFont();
this.resolved = '';
this.wordBreak = [0];
this.wordBreakRule = this.config.wordBreak;
this.nodePointer = 0;
this.blockPointer = 0;
this.nowNode = 0;
@ -975,7 +983,6 @@ export class TextContentParser {
}
this.addTextNode(text.length, false);
return this.splitLines(width);
}
@ -1014,7 +1021,7 @@ export class TextContentParser {
this.blocks.forEach(v => {
if (v.type !== TextContentType.Wait) {
width += v.width;
height = v.height;
if (v.height > height) height = v.height;
}
});
const line: ITextContentLine = {
@ -1198,7 +1205,11 @@ export class TextContentParser {
this.newLine();
const nextStart = this.wordBreak[index];
const nextEnd = this.wordBreak[end];
if (index === this.bsStart) {
this.bsStart = this.bsStart + 1;
} else {
this.bsStart = index;
}
this.bsEnd = end;
const metrics = this.measure(node, nextStart, nextEnd);
if (metrics.width < width) {
@ -1338,11 +1349,9 @@ export class TextContentParser {
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
if (node.type === TextContentType.Text) {
this.wordBreak = [node.text.length];
this.wordBreak = [0, node.text.length];
}
const pointer =
node.type === TextContentType.Text ? node.text.length : 1;
const block = this.generateBlock(node, pointer);
const block = this.generateBlock(node, 1);
this.pushBlock(block, 1);
}
this.newLine();

View File

@ -66,8 +66,8 @@ export class Icon extends RenderItem<EIconEvent> implements IAnimateFrame {
*
* @param id id
*/
setIcon(id: AllIds | AllNumbers) {
if (id === 0) {
setIcon(id: AllIdsWithNone | AllNumbers) {
if (id === 0 || id === 'none') {
this.renderable = void 0;
return;
}

View File

@ -76,14 +76,14 @@ const MainScene = defineComponent(() => {
const mainTextboxProps: Props<typeof Textbox> = {
text: '',
hidden: true,
loc: [0, MAP_HEIGHT - 150, MAIN_WIDTH, 150],
loc: [0, MAP_HEIGHT - 150, MAP_WIDTH, 150],
zIndex: 30,
fillStyle: '#fff',
titleFill: 'gold',
font: new Font('normal'),
titleFont: new Font('normal', 20, 'px', 700),
winskin: 'winskin2.png',
interval: 100,
interval: 30,
lineHeight: 4,
width: MAP_WIDTH
};
@ -117,6 +117,7 @@ const MainScene = defineComponent(() => {
magicDef: 0
});
const replayStatus: ReplayingStatus = reactive({
replaying: false,
playing: false,
speed: 1,
played: 0,
@ -129,7 +130,6 @@ const MainScene = defineComponent(() => {
jumpCount: 0,
springCount: 0,
floor: 'MT0',
replaying: false,
replayStatus,
night: 0
});
@ -161,8 +161,8 @@ const MainScene = defineComponent(() => {
rightStatus.skillDesc = HeroSkill.getSkillDesc();
rightStatus.night = NightSpecial.getNight(floor);
rightStatus.floor = floor;
rightStatus.replaying = core.isReplaying();
const { pausing, speed, toReplay, totalList } = core.status.replay;
replayStatus.replaying = core.isReplaying();
replayStatus.playing = !pausing;
replayStatus.speed = speed;
replayStatus.played = totalList.length - toReplay.length;

View File

@ -12,12 +12,7 @@ import { transitionedColor } from '../use';
import { linear } from 'mutate-animate';
import { Scroll } from '../components';
import { getArea, MinimapDrawer } from '@motajs/legacy-ui';
import {
NumpadToolbar,
PlayingToolbar,
ReplayingStatus,
ReplayingToolbar
} from './toolbar';
import { MixedToolbar, ReplayingStatus } from './toolbar';
import { HeroSkill } from '@user/data-state';
import { openViewMap } from './viewmap';
import { mainUIController } from './controller';
@ -55,8 +50,6 @@ export interface IRightHeroStatus {
springCount: number;
/** 当前楼层 */
floor: FloorIds;
/** 是否正在录像播放 */
replaying: boolean;
/** 录像播放状态 */
replayStatus: ReplayingStatus;
/** 极昼永夜 */
@ -216,11 +209,6 @@ export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
const font2 = new Font('normal', 16);
const minimap = ref<Sprite>();
const inNumpad = ref(false);
const onNumpad = () => {
inNumpad.value = !inNumpad.value;
};
const s = p.status;
const skill = computed(() =>
@ -395,22 +383,10 @@ export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
lineWidth={1}
zIndex={-20}
></g-line>
{inNumpad.value ? (
<NumpadToolbar
loc={[0, 367, 180, 113]}
onNumpad={onNumpad}
/>
) : s.replaying ? (
<ReplayingToolbar
<MixedToolbar
loc={[0, 367, 180, 113]}
status={s.replayStatus}
/>
) : (
<PlayingToolbar
loc={[0, 367, 180, 113]}
onNumpad={onNumpad}
/>
)}
</container>
);
};

View File

@ -145,6 +145,8 @@ export const PlayingToolbar = defineComponent<
}, toolbarProps);
export interface ReplayingStatus {
/** 是否处在录像播放状态 */
replaying: boolean;
/** 是否正在播放 */
playing: boolean;
/** 录像播放速度 */
@ -378,3 +380,20 @@ export const NumpadToolbar = defineComponent<
</container>
);
}, toolbarProps);
export const MixedToolbar = defineComponent<ReplayingProps>(props => {
const inNumpad = ref(false);
const onNumpad = () => {
inNumpad.value = !inNumpad.value;
};
return () =>
inNumpad.value ? (
<NumpadToolbar loc={props.loc} onNumpad={onNumpad} />
) : props.status.replaying ? (
<ReplayingToolbar loc={props.loc} status={props.status} />
) : (
<PlayingToolbar loc={props.loc} onNumpad={onNumpad} />
);
}, replayingProps);

View File

@ -52,6 +52,7 @@ export class Text extends RenderItem<ETextEvent> {
ctx.strokeStyle = this.strokeStyle ?? 'transparent';
ctx.font = this.font.string();
ctx.lineWidth = this.strokeWidth;
ctx.lineJoin = 'round';
if (this.strokeStyle) {
ctx.strokeText(this.text, stroke, this.descent + stroke + SAFE_PAD);

View File

@ -810,7 +810,11 @@ action
| comment_s
| autoText_s
| scrollText_s
| createTextbox_s
| deleteTextbox_s
| setText_s
| createTip_s
| deleteTip_s
| tip_s
| setValue_s
| setEquip_s
@ -940,30 +944,27 @@ action
text_s
: '标题' EvalString? '图标' EvalString? '像素坐标 x' IntString? 'y' IntString? '宽' IntString? '高' IntString? '维持文本' Bool '打字间隔' IntString? '行高' IntString? BGNL? Newline
: '标题' EvalString? '图标' EvalString? '文本框id' EvalString? '像素坐标 x' IntString? 'y' IntString? '宽' IntString? '高' IntString? BGNL? Newline
EvalString_Multi Newline
/* text_s
tooltip : text显示一段文字剧情,选项较多请右键点击帮助
tooltip : text显示一段文字剧情文本框id 默认使用 main-textbox
helpUrl : /_docs/#/instruction
previewBlock : true
allIds : ['EvalString_1']
default : ["小妖精","fairy","","","","",false,"","","欢迎使用事件编辑器"]
default : ["","","","","","","","欢迎使用事件编辑器"]
EvalString_0= EvalString_0 ? (', "title": "'+EvalString_0+'"') : '';
EvalString_1= EvalString_1 ? (', "icon": "'+EvalString_1+'"') : '';
EvalString_2= EvalString_2 ? (', "textbox": "'+EvalString_2+'"') : '';
IntString_0= IntString_0 ? (', "x": '+IntString_0) : '';
IntString_1= IntString_1 ? (', "y": '+IntString_1) : '';
IntString_2= IntString_2 ? (', "width": '+IntString_2) : '';
IntString_3= IntString_3 ? (', "height": '+IntString_3) : '';
IntString_4= IntString_4 ? (', "interval": '+IntString_4) : '';
IntString_5= IntString_5 ? (', "lineHeight": '+IntString_5) : '';
var code = '{"type": "text"'+EvalString_0+EvalString_1+IntString_0+IntString_1+IntString_2+IntString_3+',"keepLast":'+Bool_0+IntString_4+IntString_5+'"text":"'+EvalString_Multi_0+'"},\n';
var code = '{"type": "text"'+EvalString_0+EvalString_1+EvalString_2+IntString_0+IntString_1+IntString_2+IntString_3+', "text": "'+EvalString_Multi_0+'"},\n';
return code
*/;
comment_s
: '添加注释' ':' EvalString_Multi Newline
@ -979,7 +980,7 @@ return code;
*/;
autoText_s
: '自动剧情文本: 标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '时间' Int BGNL? EvalString_Multi Newline
: '自动剧情文本: 标题' EvalString? '图标' EvalString? '文本框id' EvalString? '像素坐标 x' IntString? 'y' IntString? '宽' IntString? '高' IntString? '时间' Int BGNL? EvalString_Multi Newline
/* autoText_s
@ -987,40 +988,54 @@ tooltip : autoText自动剧情文本,用户无法跳过自动剧情文本,大
helpUrl : /_docs/#/instruction
doubleclicktext : EvalString_Multi_0
allIds : ['EvalString_1']
default : ["小妖精","fairy","",3000,"用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示"]
var title='';
if (EvalString_0==''){
if (EvalString_1=='' )title='';
else title='\\t['+EvalString_1+']';
} else {
if (EvalString_1=='')title='\\t['+EvalString_0+']';
else title='\\t['+EvalString_0+','+EvalString_1+']';
}
if(EvalString_2 && !(/^(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?$/.test(EvalString_2))) {
throw new Error('对话框效果的用法请右键点击帮助');
}
EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']');
var code = '{"type": "autoText", "text": "'+title+EvalString_2+EvalString_Multi_0+'", "time": '+Int_0+'},\n';
default : ["","","","","","","",3000,"用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示"]
EvalString_0= EvalString_0 ? (', "title": "'+EvalString_0+'"') : '';
EvalString_1= EvalString_1 ? (', "icon": "'+EvalString_1+'"') : '';
EvalString_2= EvalString_2 ? (', "textbox": "'+EvalString_2+'"') : '';
IntString_0= IntString_0 ? (', "x": '+IntString_0) : '';
IntString_1= IntString_1 ? (', "y": '+IntString_1) : '';
IntString_2= IntString_2 ? (', "width": '+IntString_2) : '';
IntString_3= IntString_3 ? (', "height": '+IntString_3) : '';
Int_0= ', "time": '+Int_0;
var code = '{"type": "autoText"'+EvalString_0+EvalString_1+EvalString_2+IntString_0+IntString_1+IntString_2+IntString_3+Int0+', "text": "'+EvalString_Multi_0+'},\n';
return code;
*/;
scrollText_s
: '滚动剧情文本:' '时间' Int '行距' Number '不等待执行完毕' Bool? BGNL? EvalString_Multi Newline
: '滚动剧情文本事件将在 2.B.1 实装'
/* scrollText_s
tooltip : scrollText滚动剧情文本,将从下到上进行滚动显示。
tooltip : scrollText滚动剧情文本事件将在 2.B.1 实装
helpUrl : /_docs/#/instruction
doubleclicktext : EvalString_Multi_0
default : [5000,1.4,false,"时间是总时间可以使用setText事件来控制字体、颜色、大小、偏移量等"]
Bool_0 = Bool_0?', "async": true':'';
var code = '{"type": "scrollText", "text": "'+EvalString_Multi_0+'"'+Bool_0+', "time" :'+Int_0+', "lineHeight": '+Number_0+'},\n';
return code;
default : []
return '{"type": "scrollText"}';
*/;
createTextbox_s
: '创建文本框将在 2.B.1 实装'
/* createTextbox_s
tooltip : createTextbox创建文本框事件将在 2.B.1 实装
helpUrl : /_docs/#/instruction
default : []
return '{"type": "createTextbox"},\n'
*/;
deleteTextbox_s
: '删除文本框将在 2.B.1 实装'
/* deleteTextbox_s
tooltip : deleteTextbox删除文本框事件将在 2.B.1 实装
helpUrl : /_docs/#/instruction
default : []
return '{"type": "deleteTextbox"},\n'
*/;
setText_s
: '设置剧情文本的属性' '位置像素x' IntString? 'y' IntString? '宽' IntString? '高' IntString? '字体类型' EvalString? '字体大小' IntString? '字体线宽' IntString? BGNL?
'是否斜体' Bool? '维持文本' Bool? '打字间隔' IntString? '行高' IntString? '文字颜色' ColorString? Colour '文字描边颜色' ColorString? Colour '描边线宽' IntString? '是否填充' Bool '是否描边' Bool BGNL?
: '配置文本框' '文本框id'EvalString '位置像素x' IntString? 'y' IntString? '宽' IntString? '高' IntString? '字体类型' EvalString? '字体大小' IntString? '字体线宽' IntString? '是否斜体' Bool? BGNL?
'维持文本' Bool? '打字间隔' IntString? '行高' IntString? '文字颜色' ColorString? Colour '文字描边颜色' ColorString? Colour '描边线宽' IntString? '是否填充' Bool '是否描边' Bool BGNL?
'背景色' ColorString? Colour '背景winskin' EvalString? '文字与边框距离' IntString? '标题是否填充' Bool '标题是否描边' Bool'标题与边框的距离' IntString? BGNL?
'对齐方式' TextAlign_List '分词原则' WordBreak_List '行首禁则' EvalString? '行尾禁则' EvalString? '分词规则识别字符' EvalString? Newline
@ -1029,42 +1044,141 @@ setText_s
tooltip : setText设置文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填,字符间距为字符之间的距离,为整数或不填。
helpUrl : /_docs/#/instruction
previewBlock : true
default : ["","","","","","","",false,false,"","","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",true,false,"",'rgba(255,255,255,1)',"","",true,false,"",'null','space',"","",""]
default : ["main-textbox","","","","","","","",false,false,"","","",'rgba(255,255,255,1)',"",'rgba(0,0,0,1)',"",true,false,"",'rgba(0,0,0,0.9)',"","",true,false,"",'null','null',"","",""]
Bool_0 = Bool_0 ? (', "fontItalic": '+Bool_0) : '';
Bool_1 = Bool_1 ? (', "keepLast": '+Bool_1) : '';
Bool_2 = !Bool_2 ? (', "fill": '+Bool_2) : '';
Bool_3 = Bool_3 ? (', "stroke": '+Bool_3) : '';
Bool_4 = !Bool_4 ? (', "titleFill": '+Bool_4) : '';
Bool_5 = Bool_5 ? (', "titleStroke": '+Bool_5) : '';
IntString_0= IntString_0 ? (', "x": '+IntString_0) : '';
IntString_1 = IntString_1 ? (', "y": '+IntString_1) : '';
IntString_2 = IntString_2 ? (', "width": '+IntString_2) : '';
IntString_3 = IntString_3 ? (', "height": '+IntString_3) : '';
EvalString_0 = EvalString_0 ? (', "fontFamily": '+EvalString_0) : '';
IntString_4 = IntString_4 ? (', "fontSize": '+IntString_4) : '';
IntString_5 = IntString_5 ? (', " interval": '+IntString_5) : '';
IntString_6 = IntString_6 ? (', "lineHeight": ' + IntString_6) : '';
IntString_7 = IntString_7? (', "strokeWidth": ' + IntString_7) : '';
EvalString_1 = EvalString_1 ? (', "winskin": '+EvalString_1) : '';
IntString_8 = IntString_8? (', "padding": ' + IntString_8) : '';
IntString_9 = IntString_9? (', "titlePadding": ' + IntString_9) : '';
IntString_5 = IntString_5? (', "fontWeight": ' + IntString_5) : '';
IntString_6 = IntString_6 ? (', "interval": '+IntString_6) : '';
IntString_7 = IntString_7 ? (', "lineHeight": ' + IntString_7) : '';
IntString_8 = IntString_8? (', "strokeWidth": ' + IntString_8) : '';
IntString_9 = IntString_9? (', "padding": ' + IntString_9) : '';
IntString_10 = IntString_10? (', "titlePadding": ' + IntString_10) : '';
EvalString_0 = EvalString_0 ? (', "textbox": "'+EvalString_0+'"') : '';
EvalString_1 = EvalString_1 ? (', "fontFamily": "'+EvalString_1+'"') : '';
EvalString_2 = EvalString_2 ? (', "winskin": "'+EvalString_2+'"') : '';
EvalString_3 = EvalString_3? (', "ignoreLineStart": "'+EvalString_3+'"') : '';
EvalString_4 = EvalString_4 ? (', "ignoreLineEnd": "'+EvalString_4+'"') : '';
EvalString_5 = EvalString_5 ? (', "breakChars": "'+EvalString_5+'"') : '';
ColorString_0=ColorString_0?(', "fillStyle": "rgba('+ColorString_0+')"'):'';
ColorString_1=ColorString_1?(', "strokeStyle": "rgba('+ColorString_1+')"'):'';
ColorString_2=ColorString_2?(', "backColor": "rgba('+ColorString_2+')"'):'';
TextAlign_List_0 = TextAlign_List_0==='null'?'':', "textAlign": "'+TextAlign_List_0+'"';
WordBreak_List_0 = WordBreak_List_0==='null'?'':', "wordBreak": "'+WordBreak_List_0+'"';
EvalString_2 = EvalString_2? (', "ignoreLineStart": '+EvalString_2) : '';
EvalString_3 = EvalString_3 ? (', "ignoreLineEnd": '+EvalString_3) : '';
EvalString_4 = EvalString_4 ? (', "breakChars": '+EvalString_4) : '';
ColorString_0=ColorString_0?(', "fillStyle": ['+ColorString_0+']'):'';
ColorString_1=ColorString_1?(', "strokeStyle": ['+ColorString_1+']'):'';
ColorString_2=ColorString_2?(', "backColor": ['+ColorString_2+']'):'';
var code = '{"type": "setText"'+IntString_0+IntString_1+IntString_2+IntString_3+EvalString_0+IntString_4+', " fontItalic": '+Bool_0+', " keepLast": '+Bool_1+IntString_5+IntString_6+ColorString_0+ColorString_1+IntString_7 +',"fill":'+Bool_2+',"stroke":'+Bool_3+ColorString_2+EvalString_1+IntString_8+',"titleFill":'+Bool_4+',"titleStroke":'+Bool_5+IntString_9 +TextAlign_List_0+WordBreak_List_0+EvalString_2+EvalString_3+EvalString_4+'},\n';
var code =
'{"type": "setText"'+
EvalString_0+ IntString_0+ IntString_1+ IntString_2+ IntString_3+ EvalString_1+ IntString_4+ IntString_5+ Bool_0+
Bool_1+ IntString_6+ IntString_7+ ColorString_0+ ColorString_1+ IntString_8+ Bool_2+ Bool_3+
ColorString_2+ EvalString_2+ IntString_9+ Bool_4+ Bool_5+ IntString_10+
TextAlign_List_0+ WordBreak_List_0+ EvalString_3+ EvalString_4+ EvalString_5+
'},\n';
return code;
*/;
createTip_s
: '创建提示栏事件将在 2.B.1 实装'
/* createTip_s
tooltip : createTip创建提示栏事件将在 2.B.1 实装
helpUrl : /_docs/#/instruction
default : []
return '{"type": "createTip"}';
*/;
deleteTip_s
: '删除提示栏事件将在 2.B.1 实装'
/* deleteTip_s
tooltip : createTip删除提示栏事件将在 2.B.1 实装
helpUrl : /_docs/#/instruction
default : []
return '{"type": "deleteTip"}';
*/;
tip_s
: '显示提示' ':' EvalString '图标ID' IdString? Newline
: '显示提示' '提示栏id' EvalString? '图标ID' IdString? BGNL?
'提示内容' EvalString Newline
/* tip_s
tooltip : tip显示一段提示文字
helpUrl : /_docs/#/instruction
allIds : ['IdString_0']
default : ["这段话将在左上角以气泡形式显示",""]
IdString_0 = IdString_0 && (', "icon": "' + IdString_0 + '"');
var code = '{"type": "tip", "text": "'+EvalString_0+'"'+IdString_0+'},\n';
default : ["","","这段话将在左上角以气泡形式显示"]
EvalString_0 = EvalString_0 ? (', "tip": "' + EvalString_0 + '"') : '';
IdString_0 = IdString_0 ? (', "icon": "' + IdString_0 + '"') : '';
EvalString_1 = EvalString_1 ? (', "text": "' + EvalString_1 + '"') : '';
var code = '{"type": "tip"'+EvalString_0+IdString_0+EvalString_1+'},\n';
return code;
*/;
confirm_s
: '显示确认框' ':' EvalString_Multi '超时毫秒数' Int BGNL? '确定的场合' ':' '(默认选中' Bool '' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline
/* confirm_s
tooltip : 弹出确认框
helpUrl : /_docs/#/instruction
default : ["确认要xxx吗?",0,false]
previewBlock : true
Bool_0 = Bool_0?', "default": true':''
Int_0 = Int_0 ? (', "timeout": '+Int_0) : '';
var code = ['{"type": "confirm"'+Int_0+Bool_0+', "text": "',EvalString_Multi_0,'",',
block.isCollapsed()?' "_collapsed": true,':'',
block.isEnabled()?'':' "_disabled": true,',
'\n"yes": [\n',action_0,'],\n',
'"no": [\n',action_1,']\n',
'},\n'].join('');
return code;
*/;
choices_s
: '选项' ':' EvalString_Multi? BGNL? '标题' EvalString? '图像' IdString? '超时毫秒数' Int BGNL? Newline choicesContext+ BEND Newline
/* choices_s
tooltip : choices: 给用户提供选项
helpUrl : /_docs/#/instruction
previewBlock : true
default : ["","","",0]
allIds : ['IdString_0']
EvalString_0 = EvalString_0 ? (', "title": "' + EvalString_0 + '"') : '';
IdString_0 = IdString_0 ? (', "icon": "' + IdString_0 + '"') : '';
EvalString_Multi_0 = EvalString_Multi_0 ?(', "text": "'+EvalString_Multi_0+'"'):'';
Int_0 = Int_0 ? (', "timeout": '+Int_0) : '';
var code = ['{"type": "choices"',EvalString_0,IdString_0,EvalString_Multi_0,Int_0,
block.isCollapsed()?', "_collapsed": true':'',
block.isEnabled()?'':', "_disabled": true',
', "choices": [\n',
choicesContext_0,
']},\n'].join('');
return code;
*/;
choicesContext
: '子选项' EvalString '图标' IdString? '颜色' ColorString? Colour '启用条件' EvalString? '出现条件' EvalString? BGNL? Newline action+
/* choicesContext
tooltip : 选项的选择
helpUrl : /_docs/#/instruction
default : ["提示文字:红钥匙","","","",""]
allIds : ['IdString_0']
colour : this.subColor
ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : '';
EvalString_1 = EvalString_1 && (', "need": "'+EvalString_1+'"');
EvalString_2 = EvalString_2 && (', "condition": "'+EvalString_2+'"');
IdString_0 = IdString_0?(', "icon": "'+IdString_0+'"'):'';
var collapsed=block.isCollapsed()?', "_collapsed": true':'';
var disabled=block.isEnabled()?'':', "_disabled": true';
var code = '{"text": "'+EvalString_0+'"'+IdString_0+ColorString_0+EvalString_1+EvalString_2+collapsed+disabled+', "action": [\n'+action_0+']},\n';
return code;
*/;
@ -2470,76 +2584,6 @@ var code = '{"case": "'+expression_0+'"'+Bool_0+collapsed+disabled+', "action":
return code;
*/;
choices_s
: '选项' ':' EvalString_Multi? BGNL? '标题' EvalString? '图像' IdString? '超时毫秒数' Int '宽度' IntString? BGNL? Newline choicesContext+ BEND Newline
/* choices_s
tooltip : choices: 给用户提供选项
helpUrl : /_docs/#/instruction
previewBlock : true
default : ["","流浪者","trader",0,'']
allIds : ['IdString_0']
var title='';
if (EvalString_0==''){
if (IdString_0=='')title='';
else title='\\t['+IdString_0+']';
} else {
if (IdString_0=='')title='\\t['+EvalString_0+']';
else title='\\t['+EvalString_0+','+IdString_0+']';
}
EvalString_Multi_0 = title+EvalString_Multi_0;
EvalString_Multi_0 = EvalString_Multi_0 ?(', "text": "'+EvalString_Multi_0+'"'):'';
Int_0 = Int_0 ? (', "timeout": '+Int_0) : '';
IntString_0 = IntString_0 ? (', "width": ' + IntString_0) : '';
var code = ['{"type": "choices"',EvalString_Multi_0,Int_0,IntString_0,
block.isCollapsed()?', "_collapsed": true':'',
block.isEnabled()?'':', "_disabled": true',
', "choices": [\n',
choicesContext_0,
']},\n'].join('');
return code;
*/;
choicesContext
: '子选项' EvalString '图标' IdString? '颜色' ColorString? Colour '启用条件' EvalString? '出现条件' EvalString? BGNL? Newline action+
/* choicesContext
tooltip : 选项的选择
helpUrl : /_docs/#/instruction
default : ["提示文字:红钥匙","","","",""]
allIds : ['IdString_0']
colour : this.subColor
ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : '';
EvalString_1 = EvalString_1 && (', "need": "'+EvalString_1+'"');
EvalString_2 = EvalString_2 && (', "condition": "'+EvalString_2+'"');
IdString_0 = IdString_0?(', "icon": "'+IdString_0+'"'):'';
var collapsed=block.isCollapsed()?', "_collapsed": true':'';
var disabled=block.isEnabled()?'':', "_disabled": true';
var code = '{"text": "'+EvalString_0+'"'+IdString_0+ColorString_0+EvalString_1+EvalString_2+collapsed+disabled+', "action": [\n'+action_0+']},\n';
return code;
*/;
confirm_s
: '显示确认框' ':' EvalString_Multi '超时毫秒数' Int BGNL? '确定的场合' ':' '(默认选中' Bool '' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline
/* confirm_s
tooltip : 弹出确认框
helpUrl : /_docs/#/instruction
default : ["确认要xxx吗?",0,false]
previewBlock : true
Bool_0 = Bool_0?', "default": true':''
Int_0 = Int_0 ? (', "timeout": '+Int_0) : '';
var code = ['{"type": "confirm"'+Int_0+Bool_0+', "text": "',EvalString_Multi_0,'",',
block.isCollapsed()?' "_collapsed": true,':'',
block.isEnabled()?'':' "_disabled": true,',
'\n"yes": [\n',action_0,'],\n',
'"no": [\n',action_1,']\n',
'},\n'].join('');
return code;
*/;
for_s
: '循环遍历' ': ' expression '从' EvalString '到' EvalString '步增' EvalString BGNL? Newline action+ BEND Newline

View File

@ -257,33 +257,60 @@ ActionParser.prototype.parseAction = function() {
return;
case "text": // 文字/对话
this.next = MotaActionBlocks['text_s'].xmlText([
data.title, data.icon, data.x, data.y, data.width, data.height, data.keepLast,data.interval,data.lineHeight, this.next]);
data.title,data.icon,data.textbox,data.x,data.y,data.width,data.height,data.text,this.next]);
break;
case "autoText": // 自动剧情文本
var info = this.getTitleAndPosition(data.text);
this.next = MotaActionBlocks['autoText_s'].xmlText([
info[0],info[1],info[2],data.time,info[3],this.next]);
data.title,data.icon,data.textbox,data.x,data.y,data.width,data.height,data.time,data.text,this.next]);
break;
case "scrollText":
this.next = MotaActionBlocks['scrollText_s'].xmlText([
data.time, data.lineHeight||1.4, data.async||false, this.EvalString_Multi(data.text), this.next]);
this.next = MotaActionBlocks['scrollText_s'].xmlText([this.next]);
break;
case "comment": // 注释
this.next = MotaActionBlocks['comment_s'].xmlText([this.EvalString_Multi(data.text),this.next]);
break;
case "createTextbox":
this.next = MotaActionBlocks['createTextbox_s'].xmlText([this.next]);
case "createTextbox":
this.next = MotaActionBlocks['deleteTextbox_s'].xmlText([this.next]);
case "setText": // 设置剧情文本的属性
//data.backColor=this.Colour(data.backColor);
//data.fillStyle=this.Colour(data.fillStyle);
//data.strokeStyle=this.Colour(data.strokeStyle);
const parsedFillStyle = data.fillStyle ? data.fillStyle.slice(5, -1) : '';
const parsedStrokeStyle = data.strokeStyle ? data.strokeStyle.slice(5, -1) : '';
const parsedBackColor = data.backColor ? data.backColor.slice(5, -1) : '';
this.next = MotaActionBlocks['setText_s'].xmlText([
data.x,data.y,data.width,data.height,data.fontFamily,data.fontSize,data.fontWeight,
data.fontItalic,data.keepLast,data.interval,data.lineHeight,,data.fillStyle,'rgba('+data.fillStyle+')',
data.strokeStyle,'rgba('+data.strokeStyle+')',data.strokeWidth,data.fill,data.stroke,data.backColor,'rgba('+data.backColor+')',
data.winskin,data.padding,data.titleFill,data.titleStroke,data.titlePadding,data.textAlign,data.wordBreak,data.ignoreLineStart,data.ignoreLineEnd,data.breakChars,this.next]);
data.textbox, data.x, data.y, data.width, data.height, data.fontFamily, data.fontSize, data.fontWeight, data.fontItalic,
data.keepLast, data.interval, data.lineHeight, parsedFillStyle, data.fillStyle, parsedStrokeStyle, data.strokeStyle, data.strokeWidth, data.fill, data.stroke,
parsedBackColor, data.backColor, data.winskin, data.padding, data.titleFill, data.titleStroke, data.titlePadding,
data.textAlign, data.wordBreak, data.ignoreLineStart, data.ignoreLineEnd, data.breakChars, this.next
]);
break;
case "createTip":
this.next = MotaActionBlocks['createTip_s'].xmlText([this.next]);
case "deleteTip":
this.next = MotaActionBlocks['deletetip_s'].xmlText([this.next]);
case "tip":
this.next = MotaActionBlocks['tip_s'].xmlText([
data.text,data.icon||"",this.next]);
data.tip,data.icon||"",data.text,this.next]);
break;
case "confirm": // 显示确认框
this.next = MotaActionFunctions.xmlText('confirm_s', [
this.EvalString_Multi(data.text), data.timeout||0, data["default"],
this.insertActionList(data["yes"]),
this.insertActionList(data["no"]),
this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled);
break;
case "choices": // 提供选项
var text_choices = null;
for(var ii=data.choices.length-1,choice;choice=data.choices[ii];ii--) {
choice.color = this.Colour(choice.color);
text_choices=MotaActionFunctions.xmlText('choicesContext', [
choice.text,choice.icon,choice.color,'rgba('+choice.color+')',choice.need||'',choice.condition||'',this.insertActionList(choice.action),text_choices],
/* isShadow */false, /*comment*/ null, /*collapsed*/ choice._collapsed, /*disabled*/ choice._disabled);
}
if (!this.isset(data.text)) data.text = '';
var info = this.getTitleAndPosition(data.text);
this.next = MotaActionFunctions.xmlText('choices_s', [
info[3],info[0],info[1],data.timeout||0,text_choices,this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled);
break;
case "show": // 显示
data.loc=data.loc||[];
@ -722,13 +749,6 @@ ActionParser.prototype.parseAction = function() {
this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled);
}
break;
case "confirm": // 显示确认框
this.next = MotaActionFunctions.xmlText('confirm_s', [
this.EvalString_Multi(data.text), data.timeout||0, data["default"],
this.insertActionList(data["yes"]),
this.insertActionList(data["no"]),
this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled);
break;
case "switch": // 多重条件分歧
var case_caseList = null;
for(var ii=data.caseList.length-1,caseNow;caseNow=data.caseList[ii];ii--) {
@ -740,19 +760,6 @@ ActionParser.prototype.parseAction = function() {
this.expandEvalBlock([data.condition]),
case_caseList,this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled);
break;
case "choices": // 提供选项
var text_choices = null;
for(var ii=data.choices.length-1,choice;choice=data.choices[ii];ii--) {
choice.color = this.Colour(choice.color);
text_choices=MotaActionFunctions.xmlText('choicesContext', [
choice.text,choice.icon,choice.color,'rgba('+choice.color+')',choice.need||'',choice.condition||'',this.insertActionList(choice.action),text_choices],
/* isShadow */false, /*comment*/ null, /*collapsed*/ choice._collapsed, /*disabled*/ choice._disabled);
}
if (!this.isset(data.text)) data.text = '';
var info = this.getTitleAndPosition(data.text);
this.next = MotaActionFunctions.xmlText('choices_s', [
info[3],info[0],info[1],data.timeout||0,data.width,text_choices,this.next], /* isShadow */false, /*comment*/ null, /*collapsed*/ data._collapsed, /*disabled*/ data._disabled);
break;
case "for": // 循环遍历
this.next = MotaActionFunctions.xmlText('for_s',[
this.expandEvalBlock([data.name]),

View File

@ -19,8 +19,8 @@ editor_blocklyconfig=(function(){
'入口方块':[
'<label text="入口方块会根据当前类型在此数组中筛选,具体控制在editor_blockly.entranceCategoryCallback中"></label>',
MotaActionFunctions.actionParser.parse([
"欢迎使用事件编辑器",
"本事件触发一次后会消失",
{"type": "text", "text": "欢迎使用事件编辑器"},
{"type": "text", "text": "本事件触发一次后会消失"},
{"type": "hide", "time": 500},
],'event'),
MotaActionFunctions.actionParser.parse({
@ -96,16 +96,19 @@ editor_blocklyconfig=(function(){
], 'splitImages'),
],
'显示文字':[
MotaActionBlocks['text_s'].xmlText(),
MotaActionBlocks['comment_s'].xmlText(),
MotaActionBlocks['text_s'].xmlText(),
MotaActionBlocks['autoText_s'].xmlText(),
MotaActionBlocks['scrollText_s'].xmlText(),
MotaActionBlocks['createTextbox_s'].xmlText(),
MotaActionBlocks['deleteTextbox_s'].xmlText(),
MotaActionBlocks['setText_s'].xmlText(),
MotaActionBlocks['createTip_s'].xmlText(),
MotaActionBlocks['deleteTip_s'].xmlText(),
MotaActionBlocks['tip_s'].xmlText(),
MotaActionBlocks['confirm_s'].xmlText(),
MotaActionBlocks['choices_s'].xmlText([
'选择剑或者盾','流浪者','man',0,'',MotaActionBlocks['choicesContext'].xmlText([
'选择剑或者盾','流浪者','man','',MotaActionBlocks['choicesContext'].xmlText([
'剑','','',null,'','',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
])
]),

View File

@ -1100,11 +1100,8 @@ actions.prototype._clickAction_text = function () {
if (core.status.event.animateUI) return;
const Store = Mota.require('@user/client-modules').TextboxStore;
const store = Store.get('main-textbox');
// var data = core.clone(core.status.event.data.current);
// if (typeof data == 'string') data = { type: 'text', text: data };
const id = core.events.nowTextbox ?? 'main-textbox';
const store = Store.get(id);
// 打字机效果显示全部文字
if (store.typing) {
store.endType();
@ -1112,19 +1109,8 @@ actions.prototype._clickAction_text = function () {
} else {
store.hide();
}
// if (core.status.event.interval != null) {
// data.showAll = true;
// core.insertAction(data);
// core.doAction();
// return;
// }
if (!data.code) {
core.ui._animateUI('hide', null, core.doAction);
} else {
// 不清除对话框
core.doAction();
}
};
////// 自定义事件时的点击操作 //////

View File

@ -876,6 +876,22 @@ control.prototype.setHeroOpacity = function (
////// 设置画布偏移
control.prototype.setGameCanvasTranslate = function (canvas, x, y) {
// Deprecated. Use RenderItem.transform instead.
// For editor compatibility.
var c = core.dom.gameCanvas[canvas];
x = x * core.domStyle.scale;
y = y * core.domStyle.scale;
c.style.transform = 'translate(' + x + 'px,' + y + 'px)';
c.style.webkitTransform = 'translate(' + x + 'px,' + y + 'px)';
c.style.OTransform = 'translate(' + x + 'px,' + y + 'px)';
c.style.MozTransform = 'translate(' + x + 'px,' + y + 'px)';
if (main.mode === 'editor' && editor.isMobile) {
c.style.transform =
'translate(' +
(x / core._PX_) * 96 +
'vw,' +
(y / core._PY_) * 96 +
'vw)';
}
};
////// 加减画布偏移

View File

@ -1563,109 +1563,71 @@ events.prototype.__action_doAsyncFunc = function (isAsync, func) {
}
};
events.prototype._action_text = function (data, x, y, prefix) {
events.prototype._action_text = function (data) {
if (this.__action_checkReplaying()) return;
const Store = Mota.require('@user/client-modules').TextboxStore;
const store = Store.get('main-textbox');
const { text } = data;
let title = '';
let inTitle = false;
let titleStartIndex = 0;
let titleEndIndex = 0;
for (let i = 0; i < text.length; i++) {
const char = text[i];
if (inTitle) {
if (char === '\\' && text[i + 1] === ']') {
title += ']';
i++;
} else if (char === ']') {
inTitle = false;
titleEndIndex = i + 1;
break;
} else {
title += char;
const { textbox = 'main-textbox', text, icon = 'none', title = '' } = data;
const store = Store.get(textbox);
if (!store) {
core.doAction();
return;
}
continue;
}
if (char === '\t' && text[i + 1] === '[') {
inTitle = true;
titleStartIndex = i;
// 跳转至方括号内
i++;
continue;
}
if (char === '\\' && text[i + 1] === 't' && text[i + 2] === '[') {
inTitle = true;
titleStartIndex = i;
// 跳转至方括号内
i += 2;
continue;
}
}
const showText = text.slice(0, titleStartIndex) + text.slice(titleEndIndex);
const loc = store.data.loc?.slice() ?? [];
loc[0] ??= 0;
loc[1] ??= 0;
loc[2] ??= 200;
loc[3] ??= 200;
const { x = loc[0], y = loc[1], width = loc[2], height = loc[3] } = data;
store.show();
store.modify({ title });
store.setText(showText);
// data.text = core.replaceText(data.text, prefix);
// var ctx = data.code ? '__text__' + data.code : null;
// data.ctx = ctx;
// if (core.getContextByName(ctx) && !data.showAll) {
// core.ui._animateUI('hide', ctx, function () {
// core.ui.drawTextBox(data.text, data);
// core.ui._animateUI('show', ctx, function () {
// if (data.async) core.doAction();
// });
// });
// return;
// }
// core.ui.drawTextBox(data.text, data);
// if (!data.showAll) {
// core.ui._animateUI('show', ctx, function () {
// if (data.async) core.doAction();
// });
// }
store.modify({
title,
icon,
x,
y,
width,
height,
loc: [x, y, width, height]
});
store.setText(text);
core.events.nowTextbox = textbox;
};
events.prototype._action_moveTextBox = function (data, x, y, prefix) {
events.prototype._action_autoText = function (data) {
if (this.__action_checkReplaying()) return;
this.__action_doAsyncFunc(
data.async,
core.moveTextBox,
data.code,
this.__action_getLoc(data.loc, x, y, prefix),
data.relative,
data.moveMode,
data.time
);
};
const Store = Mota.require('@user/client-modules').TextboxStore;
const { textbox = 'main-textbox', text, icon = 'none', title = '' } = data;
const store = Store.get(textbox);
if (!store) {
core.doAction();
return;
}
const loc = store.data.loc?.slice() ?? [];
loc[0] ??= 0;
loc[1] ??= 0;
loc[2] ??= 200;
loc[3] ??= 200;
const { x = loc[0], y = loc[1], width = loc[2], height = loc[3] } = data;
store.show();
store.modify({
title,
icon,
x,
y,
width,
height,
loc: [x, y, width, height]
});
store.setText(text);
events.prototype._action_clearTextBox = function (data, x, y, prefix) {
if (this.__action_checkReplaying()) return;
core.clearTextBox(data.code, core.doAction);
};
events.prototype._action_autoText = function (data, x, y, prefix) {
if (this.__action_checkReplaying()) return;
data.text = core.replaceText(data.text, prefix);
core.ui.drawTextBox(data.text);
setTimeout(core.doAction, data.time || 3000);
setTimeout(() => {
store.hide();
core.doAction();
}, data.time ?? 3000);
};
events.prototype._action_scrollText = function (data, x, y, prefix) {
if (this.__action_checkReplaying()) return;
data.text = core.replaceText(data.text, prefix);
this.__action_doAsyncFunc(
data.async,
core.drawScrollText,
data.text,
data.time || 5000,
data.lineHeight || 1.4
);
// todo: 2.B.1
};
events.prototype._action_comment = function (data, x, y, prefix) {
@ -1676,8 +1638,85 @@ events.prototype._action__label = function (data, x, y, prefix) {
core.doAction();
};
events.prototype._action_setText = function (data, x, y, prefix) {
this.setTextAttribute(data);
events.prototype._action_setText = function (data) {
const isNil = value => value === null || value === void 0;
const { textbox = 'main-textbox' } = data;
const Store = Mota.require('@user/client-modules').TextboxStore;
const { TextAlign, WordBreak } = Mota.require('@user/client-modules');
const Font = Mota.require('@motajs/render-style').Font;
const store = Store.get(textbox);
if (!store) {
core.doAction();
return;
}
// loc
const loc = store.data.loc?.slice() ?? [];
loc[0] ??= 0;
loc[1] ??= 0;
loc[2] ??= 200;
loc[3] ??= 200;
const { x = loc[0], y = loc[1], width = loc[2], height = loc[3] } = data;
const newLoc = [x, y, width, height];
// font
const { fontFamily, fontSize, fontWeight, fontItalic } = data;
const font = store.data.font ?? new Font();
const newFont = Font.clone(font, {
family: fontFamily,
size: fontSize,
weight: fontWeight,
italic: fontItalic
});
// config
const config = {
x,
y,
width,
height,
loc: newLoc,
font: newFont,
keepLast: data.keepLast,
interval: data.interval,
lineHeight: data.lineHeight,
fillStyle: data.fillStyle,
strokeStyle: data.strokeStyle,
strokeWidth: data.strokeWidth,
fill: isNil(data.fill),
stroke: !!data.stroke,
backColor: data.backColor,
winskin: data.winskin,
padding: data.padding,
titleFill: isNil(data.titleFill) ? 'gold' : 'transparent',
titleStroke: data.titleStroke ? 'black' : 'transparent',
titlePadding: data.titlePadding,
ignoreLineStart: data.ignoreLineStart,
ignoreLineEnd: data.ignoreLineEnd,
breakChars: data.breakChars
};
switch (data.textAlign) {
case 'left':
config.textAlign = TextAlign.Left;
break;
case 'center':
config.textAlign = TextAlign.Center;
break;
case 'right':
config.textAlign = TextAlign.Right;
break;
}
switch (data.wordBreak) {
case 'none':
config.wordBreak = WordBreak.None;
break;
case 'space':
config.wordBreak = WordBreak.Space;
break;
case 'all':
config.wordBreak = WordBreak.All;
break;
}
store.modify(config);
core.doAction();
};
@ -1686,6 +1725,29 @@ events.prototype._action_tip = function (data, x, y, prefix) {
core.doAction();
};
events.prototype._action_confirm = function (data, x, y, prefix) {
data.text = core.replaceText(data.text, prefix);
core.ui.drawConfirmBox(
data.text,
() => {
core.insertAction(data.yes ?? []);
core.doAction();
},
() => {
core.insertAction(data.no ?? []);
core.doAction();
}
);
};
events.prototype._action_choices = function (data, x, y, prefix) {
core.ui.drawChoices(
core.replaceText(data.text, prefix),
data.choices,
data.width
);
};
events.prototype._action_show = function (data, x, y, prefix) {
data.loc = this.__action_getLoc2D(data.loc, x, y, prefix);
if (data.time > 0 && data.floorId == core.status.floorId) {
@ -2519,14 +2581,6 @@ events.prototype._precompile_switch = function (data) {
return data;
};
events.prototype._action_choices = function (data, x, y, prefix) {
core.ui.drawChoices(
core.replaceText(data.text, prefix),
data.choices,
data.width
);
};
events.prototype.__action_choices_replaying = function (data, index) {
var selection = index;
if (index != 'none') {
@ -2580,21 +2634,6 @@ events.prototype._precompile_choices = function (data) {
return data;
};
events.prototype._action_confirm = function (data, x, y, prefix) {
data.text = core.replaceText(data.text, prefix);
core.ui.drawConfirmBox(
data.text,
() => {
core.insertAction(data.yes ?? []);
core.doAction();
},
() => {
core.insertAction(data.no ?? []);
core.doAction();
}
);
};
events.prototype.__action_confirm_replaying = function (data, index) {
if (index != 'none') {
var timeout = Math.floor(index / 100) || 0;

View File

@ -21,6 +21,7 @@ function main() {
this.dom = {
body: document.body,
gameDraw: document.getElementById('game-draw'),
gameCanvas: document.getElementsByClassName('gameCanvas'),
inputDiv: document.getElementById('inputDiv'),
inputMessage: document.getElementById('inputMessage'),
inputBox: document.getElementById('inputBox'),
@ -194,6 +195,10 @@ main.prototype.loadSync = function (mode, callback) {
};
main.prototype.loadAsync = async function (mode, callback) {
for (var i = 0; i < main.dom.gameCanvas.length; i++) {
main.canvas[main.dom.gameCanvas[i].id] =
main.dom.gameCanvas[i].getContext('2d');
}
main.mode = mode;
// 加载全塔属性代码

View File

@ -226,8 +226,14 @@ main.floors.MT14=
}
],
"8,2": [
"这一层有一个必须使用跳跃的地方需要1个跳跃次数你一共有3个跳跃次数请规划好",
"不要吐槽为什么天气变化这么大("
{
"type": "text",
"text": "这一层有一个必须使用跳跃的地方需要1个跳跃次数你一共有3个跳跃次数请规划好"
},
{
"type": "text",
"text": "不要吐槽为什么天气变化这么大("
}
],
"80,3": [
"你可以使用楼传传出去"

View File

@ -27,6 +27,8 @@ type ItemCls = 'tools' | 'items' | 'equips' | 'constants';
*/
type AllIds = keyof IdToNumber;
type AllIdsWithNone = AllIds | 'none';
/**
*
*/