@kubohiroya/turbowarp-plus-editor-project-model 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
type VariableType = '' | 'list';
|
|
1
2
|
export type SpriteVariableEdit = {
|
|
2
3
|
type: 'create';
|
|
3
4
|
name: string;
|
|
5
|
+
variableType?: '';
|
|
6
|
+
isCloud?: boolean;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'create';
|
|
9
|
+
name: string;
|
|
10
|
+
variableType: 'list';
|
|
11
|
+
isCloud?: false;
|
|
4
12
|
} | {
|
|
5
13
|
type: 'rename';
|
|
6
14
|
id: string;
|
|
@@ -9,7 +17,7 @@ export type SpriteVariableEdit = {
|
|
|
9
17
|
type: 'delete';
|
|
10
18
|
id: string;
|
|
11
19
|
};
|
|
12
|
-
export type SpriteVariableEditError = 'emptyName' | 'duplicateName' | 'inUse' | 'unavailable';
|
|
20
|
+
export type SpriteVariableEditError = 'emptyName' | 'duplicateName' | 'inUse' | 'unavailable' | 'cloudLimit';
|
|
13
21
|
type Variable = {
|
|
14
22
|
name: string;
|
|
15
23
|
type: string;
|
|
@@ -29,9 +37,9 @@ type VariableEvent = {
|
|
|
29
37
|
type: 'var_create';
|
|
30
38
|
varId: string;
|
|
31
39
|
varName: string;
|
|
32
|
-
varType:
|
|
40
|
+
varType: VariableType;
|
|
33
41
|
isLocal: boolean;
|
|
34
|
-
isCloud:
|
|
42
|
+
isCloud: boolean;
|
|
35
43
|
} | {
|
|
36
44
|
type: 'var_rename';
|
|
37
45
|
varId: string;
|
|
@@ -58,9 +66,78 @@ type VariableProject = {
|
|
|
58
66
|
targets: readonly VariableTarget[];
|
|
59
67
|
getEditingTarget(): VariableTarget | null;
|
|
60
68
|
getTargetForStage(): VariableTarget | null;
|
|
69
|
+
canAddCloudVariable?(): boolean;
|
|
61
70
|
};
|
|
62
71
|
refreshWorkspace(): void;
|
|
63
72
|
};
|
|
73
|
+
export type SpriteListItem = string | number | boolean;
|
|
74
|
+
export type SpriteVariableValue = string | number | readonly SpriteListItem[];
|
|
75
|
+
type VariableValue = {
|
|
76
|
+
id: string;
|
|
77
|
+
name: string;
|
|
78
|
+
type: string;
|
|
79
|
+
value: unknown;
|
|
80
|
+
isCloud?: boolean;
|
|
81
|
+
_monitorUpToDate?: boolean;
|
|
82
|
+
};
|
|
83
|
+
export declare function readSpriteVariable(variable: VariableValue): {
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
value: readonly SpriteListItem[];
|
|
87
|
+
isCloud?: undefined;
|
|
88
|
+
} | {
|
|
89
|
+
id: string;
|
|
90
|
+
name: string;
|
|
91
|
+
value: string | number;
|
|
92
|
+
isCloud: boolean | undefined;
|
|
93
|
+
} | undefined;
|
|
94
|
+
export declare function writeSpriteVariableValue(vm: {
|
|
95
|
+
runtime: {
|
|
96
|
+
getTargetById(id: string): {
|
|
97
|
+
variables: Record<string, VariableValue>;
|
|
98
|
+
} | undefined;
|
|
99
|
+
};
|
|
100
|
+
setVariableValue(targetId: string, variableId: string, value: SpriteVariableValue): boolean;
|
|
101
|
+
}, targetId: string, id: string, value: SpriteVariableValue): boolean;
|
|
64
102
|
export declare const cloudVariablePrefix = "\u2601 ";
|
|
103
|
+
type VariableMonitorBlock = {
|
|
104
|
+
id: string;
|
|
105
|
+
opcode: string;
|
|
106
|
+
isMonitored?: boolean;
|
|
107
|
+
targetId: string | null;
|
|
108
|
+
};
|
|
109
|
+
type VariableMonitorRuntime = {
|
|
110
|
+
getTargetById(id: string): VariableTarget | undefined;
|
|
111
|
+
getMonitorState(): {
|
|
112
|
+
get(id: string): {
|
|
113
|
+
visible: boolean;
|
|
114
|
+
} | undefined;
|
|
115
|
+
};
|
|
116
|
+
monitorBlocks: {
|
|
117
|
+
getBlock(id: string): VariableMonitorBlock | undefined;
|
|
118
|
+
createBlock(block: VariableMonitorBlock & {
|
|
119
|
+
fields: Record<string, {
|
|
120
|
+
id: string;
|
|
121
|
+
name: string;
|
|
122
|
+
value: string;
|
|
123
|
+
variableType: '' | 'list';
|
|
124
|
+
}>;
|
|
125
|
+
inputs: Record<string, never>;
|
|
126
|
+
next: null;
|
|
127
|
+
parent: null;
|
|
128
|
+
topLevel: true;
|
|
129
|
+
shadow: false;
|
|
130
|
+
x: number;
|
|
131
|
+
y: number;
|
|
132
|
+
}): void;
|
|
133
|
+
changeBlock(change: {
|
|
134
|
+
id: string;
|
|
135
|
+
element: 'checkbox';
|
|
136
|
+
value: boolean;
|
|
137
|
+
}): void;
|
|
138
|
+
};
|
|
139
|
+
emitProjectChanged(): void;
|
|
140
|
+
};
|
|
141
|
+
export declare function showSpriteVariableOnStage(runtime: VariableMonitorRuntime, targetId: string, id: string, visible: boolean): void;
|
|
65
142
|
export declare function editSpriteVariable(vm: VariableProject, targetId: string, edit: SpriteVariableEdit): SpriteVariableEditError | void;
|
|
66
143
|
export {};
|
|
@@ -1,4 +1,46 @@
|
|
|
1
|
+
export function readSpriteVariable(variable) {
|
|
2
|
+
const { id, name, type, value, isCloud } = variable;
|
|
3
|
+
if (type === 'list' && Array.isArray(value))
|
|
4
|
+
return { id, name, value: value };
|
|
5
|
+
if (type === '' && (typeof value === 'number' || typeof value === 'string' || typeof value === 'boolean')) {
|
|
6
|
+
return { id, name, value: typeof value === 'boolean' ? String(value) : value, isCloud };
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function writeSpriteVariableValue(vm, targetId, id, value) {
|
|
10
|
+
const variable = vm.runtime.getTargetById(targetId)?.variables[id];
|
|
11
|
+
const list = typeof value === 'object';
|
|
12
|
+
if (!variable || variable.type !== (list ? 'list' : '') || !vm.setVariableValue(targetId, id, value))
|
|
13
|
+
return false;
|
|
14
|
+
if (list)
|
|
15
|
+
variable._monitorUpToDate = false;
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
1
18
|
export const cloudVariablePrefix = '☁ ';
|
|
19
|
+
export function showSpriteVariableOnStage(runtime, targetId, id, visible) {
|
|
20
|
+
const owner = runtime.getTargetById(targetId);
|
|
21
|
+
const variable = owner?.variables[id];
|
|
22
|
+
if (!owner?.isOriginal || !variable || !['', 'list'].includes(variable.type) ||
|
|
23
|
+
Boolean(runtime.getMonitorState().get(id)?.visible) === visible)
|
|
24
|
+
return;
|
|
25
|
+
const list = variable.type === 'list';
|
|
26
|
+
const opcode = list ? 'data_listcontents' : 'data_variable';
|
|
27
|
+
const field = list ? 'LIST' : 'VARIABLE';
|
|
28
|
+
const { monitorBlocks } = runtime;
|
|
29
|
+
let block = monitorBlocks.getBlock(id);
|
|
30
|
+
if (!block) {
|
|
31
|
+
monitorBlocks.createBlock({
|
|
32
|
+
id, opcode, targetId: owner.isStage ? null : owner.id, inputs: {},
|
|
33
|
+
fields: { [field]: { id, name: field, value: variable.name, variableType: list ? 'list' : '' } },
|
|
34
|
+
next: null, parent: null, topLevel: true, shadow: false, x: 0, y: 0
|
|
35
|
+
});
|
|
36
|
+
block = monitorBlocks.getBlock(id);
|
|
37
|
+
}
|
|
38
|
+
if (block?.opcode !== opcode)
|
|
39
|
+
return;
|
|
40
|
+
block.isMonitored = !visible;
|
|
41
|
+
monitorBlocks.changeBlock({ id, element: 'checkbox', value: visible });
|
|
42
|
+
runtime.emitProjectChanged();
|
|
43
|
+
}
|
|
2
44
|
function isUsed(target, targets, id, name) {
|
|
3
45
|
const targetName = target.isStage ? '_stage_' : target.getName();
|
|
4
46
|
return targets.some(({ blocks }) => {
|
|
@@ -30,20 +72,29 @@ export function editSpriteVariable(vm, targetId, edit) {
|
|
|
30
72
|
target.blocks.blocklyListen({ type: 'var_delete', varId: edit.id });
|
|
31
73
|
}
|
|
32
74
|
else {
|
|
33
|
-
const
|
|
75
|
+
const variableType = edit.type === 'create' ? edit.variableType ?? '' : '';
|
|
76
|
+
const cloud = edit.type === 'create' ? variableType === '' && edit.isCloud === true : variable?.isCloud === true;
|
|
77
|
+
const name = (cloud && edit.name.startsWith(cloudVariablePrefix) ?
|
|
78
|
+
edit.name.slice(cloudVariablePrefix.length) : edit.name).trim();
|
|
34
79
|
if (!name)
|
|
35
80
|
return 'emptyName';
|
|
36
|
-
const fullName =
|
|
81
|
+
const fullName = cloud ? cloudVariablePrefix + name : name;
|
|
37
82
|
if (fullName === variable?.name)
|
|
38
83
|
return;
|
|
39
84
|
const scope = target.isStage ? runtime.targets.filter(item => item.isStage || item.isOriginal) :
|
|
40
85
|
[target, runtime.getTargetForStage()];
|
|
41
|
-
if (scope.some(owner => owner && Object.values(owner.variables).some(item => item.type ===
|
|
86
|
+
if (scope.some(owner => owner && Object.values(owner.variables).some(item => item.type === variableType && item.name === fullName))) {
|
|
42
87
|
return 'duplicateName';
|
|
43
88
|
}
|
|
44
89
|
if (edit.type === 'create') {
|
|
90
|
+
if (cloud && !target.isStage)
|
|
91
|
+
return 'unavailable';
|
|
92
|
+
if (cloud && !runtime.canAddCloudVariable?.())
|
|
93
|
+
return 'cloudLimit';
|
|
45
94
|
const varId = Array.from(crypto.getRandomValues(new Uint32Array(4)), value => value.toString(16).padStart(8, '0')).join('');
|
|
46
|
-
target.blocks.blocklyListen({
|
|
95
|
+
target.blocks.blocklyListen({
|
|
96
|
+
type: 'var_create', varId, varName: fullName, varType: variableType, isLocal: !target.isStage, isCloud: cloud
|
|
97
|
+
});
|
|
47
98
|
}
|
|
48
99
|
else {
|
|
49
100
|
target.blocks.blocklyListen({ type: 'var_rename', varId: edit.id, newName: fullName });
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
type VariableType = '' | 'list';
|
|
2
|
+
|
|
1
3
|
export type SpriteVariableEdit =
|
|
2
|
-
{type: 'create'; name: string} |
|
|
4
|
+
{type: 'create'; name: string; variableType?: ''; isCloud?: boolean} |
|
|
5
|
+
{type: 'create'; name: string; variableType: 'list'; isCloud?: false} |
|
|
3
6
|
{type: 'rename'; id: string; name: string} |
|
|
4
7
|
{type: 'delete'; id: string};
|
|
5
8
|
|
|
6
|
-
export type SpriteVariableEditError = 'emptyName' | 'duplicateName' | 'inUse' | 'unavailable';
|
|
9
|
+
export type SpriteVariableEditError = 'emptyName' | 'duplicateName' | 'inUse' | 'unavailable' | 'cloudLimit';
|
|
7
10
|
|
|
8
11
|
type Variable = {name: string; type: string; isCloud?: boolean};
|
|
9
12
|
type Block = {
|
|
@@ -12,7 +15,7 @@ type Block = {
|
|
|
12
15
|
inputs: Record<string, {block: string | null; shadow: string | null}>;
|
|
13
16
|
};
|
|
14
17
|
type VariableEvent =
|
|
15
|
-
{type: 'var_create'; varId: string; varName: string; varType:
|
|
18
|
+
{type: 'var_create'; varId: string; varName: string; varType: VariableType; isLocal: boolean; isCloud: boolean} |
|
|
16
19
|
{type: 'var_rename'; varId: string; newName: string} |
|
|
17
20
|
{type: 'var_delete'; varId: string};
|
|
18
21
|
type VariableTarget = {
|
|
@@ -33,12 +36,88 @@ type VariableProject = {
|
|
|
33
36
|
targets: readonly VariableTarget[];
|
|
34
37
|
getEditingTarget(): VariableTarget | null;
|
|
35
38
|
getTargetForStage(): VariableTarget | null;
|
|
39
|
+
canAddCloudVariable?(): boolean;
|
|
36
40
|
};
|
|
37
41
|
refreshWorkspace(): void;
|
|
38
42
|
};
|
|
39
43
|
|
|
44
|
+
export type SpriteListItem = string | number | boolean;
|
|
45
|
+
export type SpriteVariableValue = string | number | readonly SpriteListItem[];
|
|
46
|
+
|
|
47
|
+
type VariableValue = {id: string; name: string; type: string; value: unknown; isCloud?: boolean; _monitorUpToDate?: boolean};
|
|
48
|
+
|
|
49
|
+
export function readSpriteVariable(variable: VariableValue) {
|
|
50
|
+
const {id, name, type, value, isCloud} = variable;
|
|
51
|
+
if (type === 'list' && Array.isArray(value)) return {id, name, value: value as readonly SpriteListItem[]};
|
|
52
|
+
if (type === '' && (typeof value === 'number' || typeof value === 'string' || typeof value === 'boolean')) {
|
|
53
|
+
return {id, name, value: typeof value === 'boolean' ? String(value) : value, isCloud};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function writeSpriteVariableValue(vm: {
|
|
58
|
+
runtime: {getTargetById(id: string): {variables: Record<string, VariableValue>} | undefined};
|
|
59
|
+
setVariableValue(targetId: string, variableId: string, value: SpriteVariableValue): boolean;
|
|
60
|
+
}, targetId: string, id: string, value: SpriteVariableValue) {
|
|
61
|
+
const variable = vm.runtime.getTargetById(targetId)?.variables[id];
|
|
62
|
+
const list = typeof value === 'object';
|
|
63
|
+
if (!variable || variable.type !== (list ? 'list' : '') || !vm.setVariableValue(targetId, id, value)) return false;
|
|
64
|
+
if (list) variable._monitorUpToDate = false;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
40
68
|
export const cloudVariablePrefix = '☁ ';
|
|
41
69
|
|
|
70
|
+
type VariableMonitorBlock = {
|
|
71
|
+
id: string;
|
|
72
|
+
opcode: string;
|
|
73
|
+
isMonitored?: boolean;
|
|
74
|
+
targetId: string | null;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
type VariableMonitorRuntime = {
|
|
78
|
+
getTargetById(id: string): VariableTarget | undefined;
|
|
79
|
+
getMonitorState(): {get(id: string): {visible: boolean} | undefined};
|
|
80
|
+
monitorBlocks: {
|
|
81
|
+
getBlock(id: string): VariableMonitorBlock | undefined;
|
|
82
|
+
createBlock(block: VariableMonitorBlock & {
|
|
83
|
+
fields: Record<string, {id: string; name: string; value: string; variableType: '' | 'list'}>;
|
|
84
|
+
inputs: Record<string, never>;
|
|
85
|
+
next: null;
|
|
86
|
+
parent: null;
|
|
87
|
+
topLevel: true;
|
|
88
|
+
shadow: false;
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
}): void;
|
|
92
|
+
changeBlock(change: {id: string; element: 'checkbox'; value: boolean}): void;
|
|
93
|
+
};
|
|
94
|
+
emitProjectChanged(): void;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export function showSpriteVariableOnStage(runtime: VariableMonitorRuntime, targetId: string, id: string, visible: boolean) {
|
|
98
|
+
const owner = runtime.getTargetById(targetId);
|
|
99
|
+
const variable = owner?.variables[id];
|
|
100
|
+
if (!owner?.isOriginal || !variable || !['', 'list'].includes(variable.type) ||
|
|
101
|
+
Boolean(runtime.getMonitorState().get(id)?.visible) === visible) return;
|
|
102
|
+
const list = variable.type === 'list';
|
|
103
|
+
const opcode = list ? 'data_listcontents' : 'data_variable';
|
|
104
|
+
const field = list ? 'LIST' : 'VARIABLE';
|
|
105
|
+
const {monitorBlocks} = runtime;
|
|
106
|
+
let block = monitorBlocks.getBlock(id);
|
|
107
|
+
if (!block) {
|
|
108
|
+
monitorBlocks.createBlock({
|
|
109
|
+
id, opcode, targetId: owner.isStage ? null : owner.id, inputs: {},
|
|
110
|
+
fields: {[field]: {id, name: field, value: variable.name, variableType: list ? 'list' : ''}},
|
|
111
|
+
next: null, parent: null, topLevel: true, shadow: false, x: 0, y: 0
|
|
112
|
+
});
|
|
113
|
+
block = monitorBlocks.getBlock(id);
|
|
114
|
+
}
|
|
115
|
+
if (block?.opcode !== opcode) return;
|
|
116
|
+
block.isMonitored = !visible;
|
|
117
|
+
monitorBlocks.changeBlock({id, element: 'checkbox', value: visible});
|
|
118
|
+
runtime.emitProjectChanged();
|
|
119
|
+
}
|
|
120
|
+
|
|
42
121
|
function isUsed(target: VariableTarget, targets: readonly VariableTarget[], id: string, name: string) {
|
|
43
122
|
const targetName = target.isStage ? '_stage_' : target.getName();
|
|
44
123
|
return targets.some(({blocks}) => {
|
|
@@ -65,18 +144,26 @@ export function editSpriteVariable(vm: VariableProject, targetId: string, edit:
|
|
|
65
144
|
if (isUsed(target, runtime.targets, edit.id, variable!.name)) return 'inUse';
|
|
66
145
|
target.blocks.blocklyListen({type: 'var_delete', varId: edit.id});
|
|
67
146
|
} else {
|
|
68
|
-
const
|
|
147
|
+
const variableType = edit.type === 'create' ? edit.variableType ?? '' : '';
|
|
148
|
+
const cloud = edit.type === 'create' ? variableType === '' && edit.isCloud === true : variable?.isCloud === true;
|
|
149
|
+
const name = (cloud && edit.name.startsWith(cloudVariablePrefix) ?
|
|
150
|
+
edit.name.slice(cloudVariablePrefix.length) : edit.name).trim();
|
|
69
151
|
if (!name) return 'emptyName';
|
|
70
|
-
const fullName =
|
|
152
|
+
const fullName = cloud ? cloudVariablePrefix + name : name;
|
|
71
153
|
if (fullName === variable?.name) return;
|
|
72
154
|
const scope = target.isStage ? runtime.targets.filter(item => item.isStage || item.isOriginal) :
|
|
73
155
|
[target, runtime.getTargetForStage()];
|
|
74
|
-
if (scope.some(owner => owner && Object.values(owner.variables).some(item =>
|
|
156
|
+
if (scope.some(owner => owner && Object.values(owner.variables).some(item =>
|
|
157
|
+
item.type === variableType && item.name === fullName))) {
|
|
75
158
|
return 'duplicateName';
|
|
76
159
|
}
|
|
77
160
|
if (edit.type === 'create') {
|
|
161
|
+
if (cloud && !target.isStage) return 'unavailable';
|
|
162
|
+
if (cloud && !runtime.canAddCloudVariable?.()) return 'cloudLimit';
|
|
78
163
|
const varId = Array.from(crypto.getRandomValues(new Uint32Array(4)), value => value.toString(16).padStart(8, '0')).join('');
|
|
79
|
-
target.blocks.blocklyListen({
|
|
164
|
+
target.blocks.blocklyListen({
|
|
165
|
+
type: 'var_create', varId, varName: fullName, varType: variableType, isLocal: !target.isStage, isCloud: cloud
|
|
166
|
+
});
|
|
80
167
|
} else {
|
|
81
168
|
target.blocks.blocklyListen({type: 'var_rename', varId: edit.id, newName: fullName});
|
|
82
169
|
}
|