mirror of
https://github.com/DaanVandenBosch/phantasmal-world.git
synced 2025-04-04 22:58:29 +08:00
Now using golden-layout in quest editor.
This commit is contained in:
parent
e4f78a9d82
commit
350ae884e8
@ -8,20 +8,26 @@
|
||||
@primary-1: fade(@primary-color, 50%);
|
||||
@primary-2: fade(@primary-color, 40%);
|
||||
|
||||
@body-background: hsl(200, 10%, 20%);
|
||||
@body-background: hsl(200, 0%, 20%);
|
||||
@component-background: @body-background;
|
||||
@text-color: hsl(200, 10%, 90%);
|
||||
@text-color-secondary: hsl(200, 20%, 80%);
|
||||
@text-color: hsl(200, 0%, 90%);
|
||||
@text-color-secondary: hsl(200, 0%, 80%);
|
||||
@text-color-dark: fade(white, 85%);
|
||||
@text-color-secondary-dark: fade(white, 65%);
|
||||
|
||||
@heading-color: fade(@black, 85%);
|
||||
|
||||
@border-radius-base: 2px;
|
||||
@border-radius-base: 0px;
|
||||
@border-radius-sm: 0px;
|
||||
|
||||
// vertical paddings
|
||||
@padding-lg: 12px; // containers
|
||||
@padding-md: 8px; // small containers and buttons
|
||||
@padding-sm: 6px; // Form controls and items
|
||||
@padding-xs: 4px; // small items
|
||||
|
||||
@background-color-light: lighten(@component-background, 20%); // background of header and selected item
|
||||
@background-color-base: fade(@primary-color, 20%); // Default grey background color
|
||||
@background-color-base: @component-background; // Default grey background color
|
||||
|
||||
@item-active-bg: fade(@primary-color, 20%);
|
||||
@item-hover-bg: fade(@primary-color, 10%);
|
||||
@ -33,16 +39,24 @@
|
||||
@disabled-color: fade(#fff, 50%);
|
||||
|
||||
// Animation
|
||||
@animation-duration-slow: 0.1s; // Modal
|
||||
@animation-duration-base: 0.066s;
|
||||
@animation-duration-fast: 0.033s; // Tooltip
|
||||
@animation-duration-slow: 0s; // Modal
|
||||
@animation-duration-base: 0s;
|
||||
@animation-duration-fast: 0s; // Tooltip
|
||||
|
||||
// Input
|
||||
@input-bg: darken(@component-background, 5%);
|
||||
|
||||
@input-height-base: 28px;
|
||||
@input-height-lg: 34px;
|
||||
@input-height-sm: 24px;
|
||||
|
||||
// Buttons
|
||||
@btn-default-bg: lighten(@component-background, 10%);
|
||||
|
||||
@btn-height-base: 28px;
|
||||
@btn-height-lg: 34px;
|
||||
@btn-height-sm: 24px;
|
||||
|
||||
// Modal
|
||||
@modal-mask-bg: fade(black, 80%);
|
||||
|
||||
@ -52,3 +66,14 @@
|
||||
|
||||
// Menu
|
||||
@menu-dark-bg: @component-background;
|
||||
|
||||
|
||||
// Tabs
|
||||
// ---
|
||||
@tabs-card-head-background: darken(@background-color-base, 5%);
|
||||
@tabs-card-height: 28px;
|
||||
@tabs-card-active-color: white;
|
||||
@tabs-highlight-color: white;
|
||||
@tabs-hover-color: white;
|
||||
@tabs-card-active-color: white;
|
||||
@tabs-ink-bar-color: white;
|
||||
|
@ -1,5 +1,6 @@
|
||||
const CracoAntDesignPlugin = require("craco-antd");
|
||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
||||
const webpack = require("webpack")
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
@ -15,13 +16,24 @@ module.exports = {
|
||||
},
|
||||
webpack: {
|
||||
configure: config => {
|
||||
// golden-layout config.
|
||||
config.plugins.push(new webpack.ProvidePlugin({
|
||||
React: "react",
|
||||
ReactDOM: "react-dom",
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
}));
|
||||
|
||||
// worker-loader config.
|
||||
config.module.rules.push({
|
||||
test: /\.worker\.js$/,
|
||||
use: { loader: 'worker-loader' }
|
||||
});
|
||||
|
||||
// Work-around until create-react-app uses webpack-dev-server 4.
|
||||
// See https://github.com/webpack/webpack/issues/6642
|
||||
config.output.globalObject = "this";
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
"@types/text-encoding": "^0.0.35",
|
||||
"antd": "^3.20.1",
|
||||
"craco-antd": "^1.11.0",
|
||||
"golden-layout": "^1.5.9",
|
||||
"javascript-lp-solver": "^0.4.5",
|
||||
"js-logger": "^1.6.0",
|
||||
"lodash": "^4.17.14",
|
||||
|
@ -6,6 +6,8 @@ import { ApplicationComponent } from "./ui/ApplicationComponent";
|
||||
import "react-virtualized/styles.css";
|
||||
import "react-select/dist/react-select.css";
|
||||
import "react-virtualized-select/styles.css";
|
||||
import "golden-layout/src/css/goldenlayout-base.css";
|
||||
import "golden-layout/src/css/goldenlayout-dark-theme.css";
|
||||
|
||||
Logger.useDefaults({
|
||||
defaultLevel: (Logger as any)[process.env["REACT_APP_LOG_LEVEL"] || "OFF"],
|
||||
|
@ -42,7 +42,7 @@ export class Renderer<C extends Camera> {
|
||||
this.controls.mouseButtons.PAN = MOUSE.LEFT;
|
||||
this.controls.addEventListener("change", this.schedule_render);
|
||||
|
||||
this.scene.background = new Color(0x151c21);
|
||||
this.scene.background = new Color(0x181818);
|
||||
this.light_holder.add(this.light);
|
||||
this.scene.add(this.light_holder);
|
||||
|
||||
|
@ -13,6 +13,8 @@ import { create_new_quest } from "./quest_creation";
|
||||
const logger = Logger.get("stores/QuestEditorStore");
|
||||
|
||||
class QuestEditorStore {
|
||||
@observable debug = false;
|
||||
|
||||
readonly undo_stack = new UndoStack();
|
||||
|
||||
@observable current_quest_filename?: string;
|
||||
@ -24,6 +26,11 @@ class QuestEditorStore {
|
||||
@observable save_dialog_filename?: string;
|
||||
@observable save_dialog_open: boolean = false;
|
||||
|
||||
@action
|
||||
toggle_debug = () => {
|
||||
this.debug = !this.debug;
|
||||
};
|
||||
|
||||
@action
|
||||
set_selected_entity = (entity?: QuestEntity) => {
|
||||
if (entity) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
cursor: pointer;
|
||||
background-color: @component-background;
|
||||
color: @text-color;
|
||||
height: 32px;
|
||||
height: 28px;
|
||||
border-color: @border-color-base;
|
||||
border-radius: @border-radius-base;
|
||||
}
|
||||
@ -13,11 +13,11 @@
|
||||
}
|
||||
|
||||
& .Select-placeholder, & .Select--single > .Select-control .Select-value {
|
||||
line-height: 32px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
& .Select-input {
|
||||
height: 30px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
&:hover > .Select-control {
|
||||
|
@ -1,6 +1,7 @@
|
||||
.EntityInfoComponent-container {
|
||||
width: 200px;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 2px 10px 10px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -3,16 +3,13 @@ import { autorun, IReactionDisposer } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import React, { Component, PureComponent, ReactNode } from "react";
|
||||
import { QuestEntity, QuestNpc, QuestObject } from "../../domain";
|
||||
import { quest_editor_store } from "../../stores/QuestEditorStore";
|
||||
import "./EntityInfoComponent.css";
|
||||
|
||||
export type Props = {
|
||||
entity?: QuestEntity;
|
||||
};
|
||||
|
||||
@observer
|
||||
export class EntityInfoComponent extends Component<Props> {
|
||||
export class EntityInfoComponent extends Component {
|
||||
render(): ReactNode {
|
||||
const entity = this.props.entity;
|
||||
const entity = quest_editor_store.selected_entity;
|
||||
|
||||
if (entity) {
|
||||
const section_id = entity.section ? entity.section.id : entity.section_id;
|
||||
|
@ -8,24 +8,3 @@
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.qe-QuestEditorComponent-tabcontainer {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
& > .ant-tabs-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.qe-QuestEditorComponent-tab.ant-tabs-tabpane-active {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.qe-QuestEditorComponent-tab-main {
|
||||
flex: 1;
|
||||
}
|
||||
|
@ -1,62 +1,97 @@
|
||||
import GoldenLayout from "golden-layout";
|
||||
import { observer } from "mobx-react";
|
||||
import React, { Component, ReactNode } from "react";
|
||||
import { get_quest_renderer } from "../../rendering/QuestRenderer";
|
||||
import React, { Component, createRef, ReactNode } from "react";
|
||||
import { application_store } from "../../stores/ApplicationStore";
|
||||
import { quest_editor_store } from "../../stores/QuestEditorStore";
|
||||
import { RendererComponent } from "../RendererComponent";
|
||||
import { EntityInfoComponent } from "./EntityInfoComponent";
|
||||
import "./QuestEditorComponent.less";
|
||||
import { QuestInfoComponent } from "./QuestInfoComponent";
|
||||
import { Toolbar } from "./Toolbar";
|
||||
import { Tabs } from "antd";
|
||||
import { QuestRendererComponent } from "./QuestRendererComponent";
|
||||
import { ScriptEditorComponent } from "./ScriptEditorComponent";
|
||||
import { AutoSizer } from "react-virtualized";
|
||||
import { Toolbar } from "./Toolbar";
|
||||
|
||||
@observer
|
||||
export class QuestEditorComponent extends Component<{}, { debug: boolean }> {
|
||||
state = { debug: false };
|
||||
export class QuestEditorComponent extends Component {
|
||||
private layout_element = createRef<HTMLDivElement>();
|
||||
private layout?: GoldenLayout;
|
||||
|
||||
componentDidMount(): void {
|
||||
application_store.on_global_keyup("quest_editor", this.keyup);
|
||||
|
||||
window.addEventListener("resize", this.resize);
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.layout_element.current && !this.layout) {
|
||||
this.layout = new GoldenLayout(
|
||||
{
|
||||
settings: {
|
||||
showPopoutIcon: false,
|
||||
},
|
||||
content: [
|
||||
{
|
||||
type: "row",
|
||||
content: [
|
||||
{
|
||||
title: "Info",
|
||||
type: "react-component",
|
||||
component: "QuestInfoComponent",
|
||||
isClosable: false,
|
||||
width: 3,
|
||||
},
|
||||
{
|
||||
type: "stack",
|
||||
width: 9,
|
||||
content: [
|
||||
{
|
||||
title: "3D View",
|
||||
type: "react-component",
|
||||
component: "QuestRendererComponent",
|
||||
isClosable: false,
|
||||
},
|
||||
{
|
||||
title: "Script",
|
||||
type: "react-component",
|
||||
component: "ScriptEditorComponent",
|
||||
isClosable: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Entity",
|
||||
type: "react-component",
|
||||
component: "EntityInfoComponent",
|
||||
isClosable: false,
|
||||
width: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
this.layout_element.current
|
||||
);
|
||||
this.layout.registerComponent("QuestInfoComponent", QuestInfoComponent);
|
||||
this.layout.registerComponent("QuestRendererComponent", QuestRendererComponent);
|
||||
this.layout.registerComponent("EntityInfoComponent", EntityInfoComponent);
|
||||
this.layout.registerComponent("ScriptEditorComponent", ScriptEditorComponent);
|
||||
this.layout.init();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
window.removeEventListener("resize", this.resize);
|
||||
|
||||
if (this.layout) {
|
||||
this.layout.destroy();
|
||||
this.layout = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
render(): ReactNode {
|
||||
const quest = quest_editor_store.current_quest;
|
||||
|
||||
return (
|
||||
<div className="qe-QuestEditorComponent">
|
||||
<Toolbar />
|
||||
<div className="qe-QuestEditorComponent-main">
|
||||
<QuestInfoComponent quest={quest} />
|
||||
<Tabs type="card" className="qe-QuestEditorComponent-tabcontainer">
|
||||
<Tabs.TabPane
|
||||
tab="Entities"
|
||||
key="entities"
|
||||
className="qe-QuestEditorComponent-tab"
|
||||
>
|
||||
<div className="qe-QuestEditorComponent-tab-main">
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<RendererComponent
|
||||
renderer={get_quest_renderer()}
|
||||
width={width}
|
||||
height={height}
|
||||
debug={this.state.debug}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
<EntityInfoComponent entity={quest_editor_store.selected_entity} />
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane
|
||||
tab="Script"
|
||||
key="script"
|
||||
className="qe-QuestEditorComponent-tab"
|
||||
>
|
||||
<ScriptEditorComponent className="qe-QuestEditorComponent-tab-main" />
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div className="qe-QuestEditorComponent-main" ref={this.layout_element} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -67,7 +102,13 @@ export class QuestEditorComponent extends Component<{}, { debug: boolean }> {
|
||||
} else if (e.ctrlKey && e.key === "Z" && !e.altKey) {
|
||||
quest_editor_store.undo_stack.redo();
|
||||
} else if (e.ctrlKey && e.altKey && e.key === "d") {
|
||||
this.setState(state => ({ debug: !state.debug }));
|
||||
quest_editor_store.toggle_debug();
|
||||
}
|
||||
};
|
||||
|
||||
private resize = () => {
|
||||
if (this.layout) {
|
||||
this.layout.updateSize();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
.qe-QuestInfoComponent {
|
||||
width: 280px;
|
||||
padding: 10px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 2px 10px 10px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -1,69 +1,76 @@
|
||||
import React from "react";
|
||||
import { NpcType, Quest } from "../../domain";
|
||||
import { observer } from "mobx-react";
|
||||
import React, { Component, ReactNode } from "react";
|
||||
import { NpcType } from "../../domain";
|
||||
import { quest_editor_store } from "../../stores/QuestEditorStore";
|
||||
import "./QuestInfoComponent.css";
|
||||
|
||||
export function QuestInfoComponent({ quest }: { quest?: Quest }): JSX.Element {
|
||||
if (quest) {
|
||||
const episode = quest.episode === 4 ? "IV" : quest.episode === 2 ? "II" : "I";
|
||||
const npc_counts = new Map<NpcType, number>();
|
||||
@observer
|
||||
export class QuestInfoComponent extends Component {
|
||||
render(): ReactNode {
|
||||
const quest = quest_editor_store.current_quest;
|
||||
|
||||
for (const npc of quest.npcs) {
|
||||
const val = npc_counts.get(npc.type) || 0;
|
||||
npc_counts.set(npc.type, val + 1);
|
||||
}
|
||||
if (quest) {
|
||||
const episode = quest.episode === 4 ? "IV" : quest.episode === 2 ? "II" : "I";
|
||||
const npc_counts = new Map<NpcType, number>();
|
||||
|
||||
const extra_canadines = (npc_counts.get(NpcType.Canane) || 0) * 8;
|
||||
for (const npc of quest.npcs) {
|
||||
const val = npc_counts.get(npc.type) || 0;
|
||||
npc_counts.set(npc.type, val + 1);
|
||||
}
|
||||
|
||||
// Sort by type ID.
|
||||
const sorted_npc_counts = [...npc_counts].sort((a, b) => a[0].id - b[0].id);
|
||||
const extra_canadines = (npc_counts.get(NpcType.Canane) || 0) * 8;
|
||||
|
||||
// Sort by type ID.
|
||||
const sorted_npc_counts = [...npc_counts].sort((a, b) => a[0].id - b[0].id);
|
||||
|
||||
const npc_count_rows = sorted_npc_counts.map(([npc_type, count]) => {
|
||||
const extra = npc_type === NpcType.Canadine ? extra_canadines : 0;
|
||||
return (
|
||||
<tr key={npc_type.id}>
|
||||
<td>{npc_type.name}:</td>
|
||||
<td>{count + extra}</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
|
||||
const npc_count_rows = sorted_npc_counts.map(([npc_type, count]) => {
|
||||
const extra = npc_type === NpcType.Canadine ? extra_canadines : 0;
|
||||
return (
|
||||
<tr key={npc_type.id}>
|
||||
<td>{npc_type.name}:</td>
|
||||
<td>{count + extra}</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="qe-QuestInfoComponent">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Name:</th>
|
||||
<td>{quest.name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Episode:</th>
|
||||
<td>{episode}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<pre>{quest.short_description}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<pre>{quest.long_description}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="qe-QuestInfoComponent-npc-counts-container">
|
||||
<div className="qe-QuestInfoComponent">
|
||||
<table>
|
||||
<thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colSpan={2}>NPC Counts</th>
|
||||
<th>Name:</th>
|
||||
<td>{quest.name}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{npc_count_rows}</tbody>
|
||||
<tr>
|
||||
<th>Episode:</th>
|
||||
<td>{episode}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<pre>{quest.short_description}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={2}>
|
||||
<pre>{quest.long_description}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="qe-QuestInfoComponent-npc-counts-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th colSpan={2}>NPC Counts</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{npc_count_rows}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <div className="qe-QuestInfoComponent" />;
|
||||
);
|
||||
} else {
|
||||
return <div className="qe-QuestInfoComponent" />;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
src/ui/quest_editor/QuestRendererComponent.tsx
Normal file
24
src/ui/quest_editor/QuestRendererComponent.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { observer } from "mobx-react";
|
||||
import React, { Component, ReactNode } from "react";
|
||||
import { AutoSizer } from "react-virtualized";
|
||||
import { get_quest_renderer } from "../../rendering/QuestRenderer";
|
||||
import { quest_editor_store } from "../../stores/QuestEditorStore";
|
||||
import { RendererComponent } from "../RendererComponent";
|
||||
|
||||
@observer
|
||||
export class QuestRendererComponent extends Component {
|
||||
render(): ReactNode {
|
||||
return (
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<RendererComponent
|
||||
renderer={get_quest_renderer()}
|
||||
width={width}
|
||||
height={height}
|
||||
debug={quest_editor_store.debug}
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
.qe-ScriptEditorComponent {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
@ -96,7 +96,7 @@ editor.defineTheme("phantasmal-world", {
|
||||
base: "vs-dark",
|
||||
inherit: true,
|
||||
rules: [
|
||||
{ token: "", foreground: "e0e0e0", background: "151c21" },
|
||||
{ token: "", foreground: "e0e0e0", background: "#181818" },
|
||||
{ token: "tag", foreground: "99bbff" },
|
||||
{ token: "predefined", foreground: "bbffbb" },
|
||||
{ token: "number", foreground: "ffffaa" },
|
||||
@ -104,18 +104,15 @@ editor.defineTheme("phantasmal-world", {
|
||||
{ token: "string.escape", foreground: "8888ff" },
|
||||
],
|
||||
colors: {
|
||||
"editor.background": "#151c21",
|
||||
"editor.lineHighlightBackground": "#1a2228",
|
||||
"editor.background": "#181818",
|
||||
"editor.lineHighlightBackground": "#202020",
|
||||
},
|
||||
});
|
||||
|
||||
export class ScriptEditorComponent extends Component<{ className?: string }> {
|
||||
export class ScriptEditorComponent extends Component {
|
||||
render(): ReactNode {
|
||||
let className = "qe-ScriptEditorComponent";
|
||||
if (this.props.className) className += " " + this.props.className;
|
||||
|
||||
return (
|
||||
<section className={className}>
|
||||
<section className="qe-ScriptEditorComponent">
|
||||
<AutoSizer>
|
||||
{({ width, height }) => <MonacoComponent width={width} height={height} />}
|
||||
</AutoSizer>
|
||||
|
@ -1,8 +1,8 @@
|
||||
.qe-Toolbar {
|
||||
display: flex;
|
||||
padding: 10px 5px;
|
||||
padding: 6px 3px;
|
||||
}
|
||||
|
||||
.qe-Toolbar > * {
|
||||
margin: 0 5px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Button, Dropdown, Form, Icon, Input, Menu, Modal, Select, Upload } from "antd";
|
||||
import { ClickParam } from "antd/lib/menu";
|
||||
import { UploadChangeParam, UploadFile } from "antd/lib/upload/interface";
|
||||
import { observer } from "mobx-react";
|
||||
import React, { ChangeEvent, Component, ReactNode } from "react";
|
||||
import { Episode } from "../../domain";
|
||||
import { quest_editor_store } from "../../stores/QuestEditorStore";
|
||||
import "./Toolbar.less";
|
||||
import { ClickParam } from "antd/lib/menu";
|
||||
|
||||
@observer
|
||||
export class Toolbar extends Component {
|
||||
@ -42,6 +42,25 @@ export class Toolbar extends Component {
|
||||
>
|
||||
<Button icon="file">Open file...</Button>
|
||||
</Upload>
|
||||
<Button icon="save" onClick={quest_editor_store.open_save_dialog} disabled={!quest}>
|
||||
Save as...
|
||||
</Button>
|
||||
<Button
|
||||
icon="undo"
|
||||
onClick={this.undo}
|
||||
title={"Undo" + (undo.first_undo ? ` "${undo.first_undo.description}"` : "")}
|
||||
disabled={!undo.can_undo}
|
||||
>
|
||||
Undo
|
||||
</Button>
|
||||
<Button
|
||||
icon="redo"
|
||||
onClick={this.redo}
|
||||
title={"Redo" + (undo.first_redo ? ` "${undo.first_redo.description}"` : "")}
|
||||
disabled={!quest_editor_store.undo_stack.can_redo}
|
||||
>
|
||||
Redo
|
||||
</Button>
|
||||
<Select
|
||||
onChange={quest_editor_store.set_current_area_id}
|
||||
value={area_id}
|
||||
@ -54,21 +73,6 @@ export class Toolbar extends Component {
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
<Button icon="save" onClick={quest_editor_store.open_save_dialog} disabled={!quest}>
|
||||
Save as...
|
||||
</Button>
|
||||
<Button
|
||||
icon="undo"
|
||||
onClick={this.undo}
|
||||
title={"Undo" + (undo.first_undo ? ` "${undo.first_undo.description}"` : "")}
|
||||
disabled={!undo.can_undo}
|
||||
/>
|
||||
<Button
|
||||
icon="redo"
|
||||
onClick={this.redo}
|
||||
title={"Redo" + (undo.first_redo ? ` "${undo.first_redo.description}"` : "")}
|
||||
disabled={!quest_editor_store.undo_stack.can_redo}
|
||||
/>
|
||||
<SaveQuestComponent />
|
||||
</div>
|
||||
);
|
||||
|
@ -3,3 +3,26 @@
|
||||
|
||||
@table-scrollbar-color: lighten(@scrollbar-color, 1%);
|
||||
@table-scrollbar-thumb-color: lighten(@scrollbar-thumb-color, 5%);
|
||||
|
||||
#phantasmal-world-root {
|
||||
& .lm_header {
|
||||
background: darken(@component-background, 5%);
|
||||
}
|
||||
|
||||
& .lm_goldenlayout {
|
||||
background: darken(@component-background, 5%);
|
||||
}
|
||||
|
||||
& .lm_content {
|
||||
background: @component-background;
|
||||
}
|
||||
|
||||
& .lm_tab {
|
||||
background: darken(@component-background, 5%);
|
||||
box-shadow: none;
|
||||
|
||||
&.lm_active {
|
||||
background: @component-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
yarn.lock
12
yarn.lock
@ -4781,6 +4781,13 @@ globby@^6.1.0:
|
||||
pify "^2.0.0"
|
||||
pinkie-promise "^2.0.0"
|
||||
|
||||
golden-layout@^1.5.9:
|
||||
version "1.5.9"
|
||||
resolved "https://registry.yarnpkg.com/golden-layout/-/golden-layout-1.5.9.tgz#a39bc1f6a67e6f886b797c016dd924e9426ba77f"
|
||||
integrity sha1-o5vB9qZ+b4hreXwBbdkk6UJrp38=
|
||||
dependencies:
|
||||
jquery "*"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b"
|
||||
@ -6090,6 +6097,11 @@ jest@24.7.1:
|
||||
import-local "^2.0.0"
|
||||
jest-cli "^24.7.1"
|
||||
|
||||
jquery@*:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
|
||||
integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
|
||||
|
||||
js-levenshtein@^1.1.3:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
||||
|
Loading…
Reference in New Issue
Block a user