Update style on cell editor
<div id="text" class="flex-auto"></div>
<div id="actions"></div>
</div>
- <div id="editor-container" class="vflex sidebar">
- <h1>Cell Editor</h1>
- <h2>Title</h2>
- <input name="title">
- <h2>Description</h2>
- <textarea name="description" class="flex-auto"></textarea>
- <h2>Events</h2>
- <div id="event-list"></div>
- <button id="add-event">Add Event</button>
- <div class="hflex">
- <button id="editor-close">Close</button>
- </div>
- </div>
</div>
-<div id="textwindow" style="display:none">
+<div id="editor-container">
+ <div class="box hflex">
+ <div class="vflex flex-auto">
+ <h1>Cell Editor</h1>
+ <h2>Title</h2>
+ <input name="title">
+ <h2>Description</h2>
+ <textarea name="description" class="flex-auto"></textarea>
+ <div class="hflex">
+ <button id="editor-close">Close</button>
+ </div>
+ </div>
+ <div class="events">
+ <h2>Events</h2>
+ <div id="event-list"></div>
+ <button id="add-event">Add Event</button>
+ </div>
+ </div>
</div>
-<a id="continue" style="display:none" href="#" onclick="doContinue(); return false">continue</a>
-
-<script type="text/javascript">
-</script>
</body>
</html>
addEvent(event?: GameEvent) {
const eventForm = document.createElement('div');
+ eventForm.className = 'vflex';
eventForm.innerHTML = `
<h3>ID</h3>
<input name="id">
<input name="title">
<h3>Script</h3>
<textarea name="script"></textarea>
- <button name="delete">Delete Event</button>
+ <div>
+ <button name="delete">Delete Event</button>
+ </div>
`;
this.eventListRef.appendChild(eventForm);
-import gs from './gamestate';
-
-interface ScriptInstruction {
- execute(): Promise<void>
-}
-
-class SayInstruction implements ScriptInstruction {
- s: string
-
- constructor(s: string) {
- this.s = s;
- }
-
- execute(): Promise<void> {
- gs.textView.print(this.s);
- return Promise.resolve();
- }
-}
-
-interface QueryOption {
- label: string, instruction: ScriptInstruction
-}
-
-class QueryInstruction implements ScriptInstruction {
- options: QueryOption[]
-
- constructor(options: QueryOption[]) {
- this.options = options;
- }
-
- execute(): Promise<void> {
- return new Promise( (resolve, reject) => {
- gs.actions.clear();
- for (let o of this.options) {
- gs.actions.addAction(o.label, () => {
- gs.actions.clear();
- resolve(o.instruction.execute());
- });
- }
- });
- }
-}
-
-class SleepInstruction implements ScriptInstruction {
- duration: number
-
- constructor(duration: number) {
- this.duration = duration;
- }
-
- execute(): Promise<void> {
- return new Promise( (resolve, reject) => {
- setTimeout(resolve, this.duration * 1000);
- });
- }
-}
-
-class PauseInstruction implements ScriptInstruction {
- text: string
-
- constructor(text?: string) {
- this.text = text || 'Continue';
- }
-
- execute(): Promise<void> {
- return new Promise( (resolve, reject) => {
- gs.actions.clear();
- gs.actions.addAction(this.text, () => {
- gs.actions.clear();
- resolve();
- });
- });
- }
-}
-
-class ClearScreenInstruction implements ScriptInstruction {
- execute(): Promise<void> {
- gs.textView.clear();
- return Promise.resolve();
- }
-}
-
-export class Script {
- instructions: ScriptInstruction[]
- pc: number
-
- constructor(text?: string) {
- this.instructions = [];
- this.pc = 0;
- if (text)
- this.parse(text);
- }
-
- parse(text: string) {
- const lines = text.split(/[\r\n]+/);
-
- let n = 0;
- var parseQuery = () => {
- const options: QueryOption[] = [];
- let tokens;
- do {
- n++;
- tokens = this.parseLine(lines[n]);
- const arr = tokens.indexOf('=>');
- if (arr == -1)
- continue;
- const label = tokens.slice(0, arr).join(' ');
- const instruction = parseTokens(tokens.slice(arr + 1));
- options.push({ label, instruction });
- } while (tokens[0] != 'endquery');
- return new QueryInstruction(options);
- }
-
- var parseTokens = (tokens: string[]) => {
- switch (tokens[0]) {
- case 'say':
- return new SayInstruction(tokens.slice(1).join(' '));
- case 'query':
- return parseQuery();
- case 'sleep':
- return new SleepInstruction(parseFloat(tokens[1]));
- case 'pause':
- return new PauseInstruction(tokens.slice(1).join(' '));
- case 'clear':
- return new ClearScreenInstruction();
- case undefined:
- // empty line
- break;
- default:
- this.dump();
- throw Error('Unrecognized instruction on line ' + n + ': ' + tokens[0]);
- }
- }
-
- while (n < lines.length) {
- const tokens = this.parseLine(lines[n]);
- const instruction = parseTokens(tokens);
- if (instruction) {
- this.instructions.push(instruction);
- }
- n++;
- }
- }
-
- parseLine(line: string): string[] {
- const tokens: string[] = [];
- let b = 0;
- let n = 0;
- const scan = (test: (c: string) => boolean) => {
- while (n < line.length && test(line[n]))
- n++;
- };
-
- const pushToken = () => {
- if (b < n)
- tokens.push(line.slice(b, n));
- };
-
- // fun function fuckery I'll forget in a fortnight
- const testFor = (r: RegExp) => (c: string) => r.test(c);
- const testForNot = (r: RegExp) => (c: string) => !r.test(c);
- const testQuote = testFor(/['"]/);
- const testNotQuote = testForNot(/['"]/);
- const testWhitespace = testFor(/\s/);
-
- scan(testWhitespace);
- b = n;
-
- while (n < line.length) {
- if (testQuote(line[n])) {
- const q = line[n];
- n++;
- b = n;
- // scan until next matching quote
- const re = new RegExp(q);
- scan(testForNot(re));
- pushToken();
- n++;
- //scan(testWhitespace);
- b = n;
- } else if (testWhitespace(line[n])) {
- pushToken();
- scan(testWhitespace);
- b = n;
- } else if (n + 1 == line.length) {
- n++;
- pushToken();
- } else {
- n++;
- }
- }
-
- return tokens;
- }
-
- step(): Promise<void> {
- let r = this.instructions[this.pc].execute();
- this.pc++;
- return r;
- }
-
- async execute() {
- this.pc = 0;
- while (this.pc < this.instructions.length) {
- await this.step();
- }
- }
-
- dump() {
- console.log(this.instructions);
- }
-}
-
-export class ScriptEngine {
-
-}
+import gs from './gamestate';
+
+interface ScriptInstruction {
+ execute(): Promise<void>
+}
+
+class SayInstruction implements ScriptInstruction {
+ s: string
+
+ constructor(s: string) {
+ this.s = s;
+ }
+
+ execute(): Promise<void> {
+ gs.textView.print(this.s);
+ return Promise.resolve();
+ }
+}
+
+interface QueryOption {
+ label: string, instruction: ScriptInstruction
+}
+
+class QueryInstruction implements ScriptInstruction {
+ options: QueryOption[]
+
+ constructor(options: QueryOption[]) {
+ this.options = options;
+ }
+
+ execute(): Promise<void> {
+ return new Promise( (resolve, reject) => {
+ gs.actions.clear();
+ for (let o of this.options) {
+ gs.actions.addAction(o.label, () => {
+ gs.actions.clear();
+ resolve(o.instruction.execute());
+ });
+ }
+ });
+ }
+}
+
+class SleepInstruction implements ScriptInstruction {
+ duration: number
+
+ constructor(duration: number) {
+ this.duration = duration;
+ }
+
+ execute(): Promise<void> {
+ return new Promise( (resolve, reject) => {
+ setTimeout(resolve, this.duration * 1000);
+ });
+ }
+}
+
+class PauseInstruction implements ScriptInstruction {
+ text: string
+
+ constructor(text?: string) {
+ this.text = text || 'Continue';
+ }
+
+ execute(): Promise<void> {
+ return new Promise( (resolve, reject) => {
+ gs.actions.clear();
+ gs.actions.addAction(this.text, () => {
+ gs.actions.clear();
+ resolve();
+ });
+ });
+ }
+}
+
+class ClearScreenInstruction implements ScriptInstruction {
+ execute(): Promise<void> {
+ gs.textView.clear();
+ return Promise.resolve();
+ }
+}
+
+export class Script {
+ instructions: ScriptInstruction[]
+ pc: number
+
+ constructor(text?: string) {
+ this.instructions = [];
+ this.pc = 0;
+ if (text)
+ this.parse(text);
+ }
+
+ parse(text: string) {
+ const lines = text.split(/[\r\n]+/);
+
+ let n = 0;
+ var parseQuery = () => {
+ const options: QueryOption[] = [];
+ let tokens;
+ do {
+ n++;
+ tokens = this.parseLine(lines[n]);
+ const arr = tokens.indexOf('=>');
+ if (arr == -1)
+ continue;
+ const label = tokens.slice(0, arr).join(' ');
+ const instruction = parseTokens(tokens.slice(arr + 1));
+ options.push({ label, instruction });
+ } while (tokens[0] != 'endquery');
+ return new QueryInstruction(options);
+ }
+
+ var parseTokens = (tokens: string[]) => {
+ switch (tokens[0]) {
+ case 'say':
+ return new SayInstruction(tokens.slice(1).join(' '));
+ case 'query':
+ return parseQuery();
+ case 'sleep':
+ return new SleepInstruction(parseFloat(tokens[1]));
+ case 'pause':
+ return new PauseInstruction(tokens.slice(1).join(' '));
+ case 'clear':
+ return new ClearScreenInstruction();
+ case undefined:
+ // empty line
+ break;
+ default:
+ this.dump();
+ throw Error('Unrecognized instruction on line ' + n + ': ' + tokens[0]);
+ }
+ }
+
+ while (n < lines.length) {
+ const tokens = this.parseLine(lines[n]);
+ const instruction = parseTokens(tokens);
+ if (instruction) {
+ this.instructions.push(instruction);
+ }
+ n++;
+ }
+ }
+
+ parseLine(line: string): string[] {
+ const tokens: string[] = [];
+ let b = 0;
+ let n = 0;
+ const scan = (test: (c: string) => boolean) => {
+ while (n < line.length && test(line[n]))
+ n++;
+ };
+
+ const pushToken = () => {
+ if (b < n)
+ tokens.push(line.slice(b, n));
+ };
+
+ // fun function fuckery I'll forget in a fortnight
+ const testFor = (r: RegExp) => (c: string) => r.test(c);
+ const testForNot = (r: RegExp) => (c: string) => !r.test(c);
+ const testQuote = testFor(/['"]/);
+ const testNotQuote = testForNot(/['"]/);
+ const testWhitespace = testFor(/\s/);
+
+ scan(testWhitespace);
+ b = n;
+
+ while (n < line.length) {
+ if (testQuote(line[n])) {
+ const q = line[n];
+ n++;
+ b = n;
+ // scan until next matching quote
+ const re = new RegExp(q);
+ scan(testForNot(re));
+ pushToken();
+ n++;
+ //scan(testWhitespace);
+ b = n;
+ } else if (testWhitespace(line[n])) {
+ pushToken();
+ scan(testWhitespace);
+ b = n;
+ } else if (n + 1 == line.length) {
+ n++;
+ pushToken();
+ } else {
+ n++;
+ }
+ }
+
+ return tokens;
+ }
+
+ step(): Promise<void> {
+ let r = this.instructions[this.pc].execute();
+ this.pc++;
+ return r;
+ }
+
+ async execute() {
+ this.pc = 0;
+ while (this.pc < this.instructions.length) {
+ await this.step();
+ }
+ }
+
+ dump() {
+ console.log(this.instructions);
+ }
+}
+
+export class ScriptEngine {
+
+}
#editor-container {
display: none;
- width: 320px;
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 100vw;
+ height: 100vh;
+}
+
+#editor-container .box {
+ width: 800px;
+ height: 600px;
+ margin-top: calc(50vh - 300px);
+ margin-left: calc(50vw - 400px);
+ border: 3px double white;
+ padding: 16px;
+ background-color: black;
}
#editor-container.visible {
display: initial;
}
-.sidebar h1 {
- font-size: 18px;
+#editor-container textarea[name="description"] {
+ height: 80px;
+}
+
+#editor-container .events {
+ margin-left: 16px;
+ overflow-y: auto;
+ width: 320px;
}
-.sidebar h2 {
+#event-list > div {
+ border-left: 1px solid white;
+ border-bottom: 1px solid white;
+ padding: 0 0 24px 12px;
+ margin: 0 0 8px 4px;
+}
+
+#event-list textarea[name="script"] {
+ height: 200px;
+}
+
+h1 {
+ font-size: 32px;
+ font-weight: normal;
+ color: #00FF00;
+ margin: 0;
+}
+
+h2 {
font-size: 16px;
+ font-weight: normal;
+ color: #00FF00;
}
-.sidebar h3 {
+h3 {
+ color: #00FF00;
font-size: 16px;
+ font-weight: bold;
+}
+
+h1:first-child, h2:first-child, h3:first-child {
+ margin-top: 0;
+}
+
+input {
+ background-color: black;
+ color: white;
+ border: none;
+ border-bottom: 1px solid white;
+ font: 16px "Modern DOS 437";
+}
+
+textarea, select {
+ background-color: black;
+ color: white;
+ border: 1px solid white;
+ padding: 8px 4px;
+ margin: 7px 3px;
+ font: 16px "Modern DOS 437";
+}
+
+button {
+ padding: 8px 4px 8px 6px;
+ margin: 7px 3px;
+ background-color: black;
+ color: white;
+ border: 1px solid white;
+ font: 16px "Modern DOS 437";
+}
+
+button:active {
+ margin: 0;
+ padding: 15px 8px;
+ background-color: white;
+ color: black;
}
#actions {
width: calc(25% - 8px);
margin: 4px;
padding: 4px;
- font: 16px "Modern DOS 437";
- background-color: black;
- color: white;
- border: 1px solid white;
}
#actions button:hover, #actions button:focus {