diff --git a/src/tea/components/BoxCollider.ts b/src/tea/components/BoxCollider.ts index e395d09..955ad1e 100644 --- a/src/tea/components/BoxCollider.ts +++ b/src/tea/components/BoxCollider.ts @@ -45,6 +45,7 @@ export class BoxCollider extends Collider { return null; } var boxCollider = new BoxCollider(app); + boxCollider.enabled = json.enabled; boxCollider.center = Tea.Vector3.fromArray(json.center); boxCollider.size = Tea.Vector3.fromArray(json.size); return boxCollider; diff --git a/src/tea/components/Camera.ts b/src/tea/components/Camera.ts index 7618cb2..309368b 100644 --- a/src/tea/components/Camera.ts +++ b/src/tea/components/Camera.ts @@ -430,6 +430,7 @@ export class Camera extends Component { return null; } var camera = new Camera(app); + camera.enabled = json.enabled; camera.depth = json.depth; camera.clearFlags = Tea.CameraClearFlags[json.clearFlags as string]; camera.fieldOfView = json.fieldOfView; diff --git a/src/tea/components/Light.ts b/src/tea/components/Light.ts index 35cad22..6623b9c 100644 --- a/src/tea/components/Light.ts +++ b/src/tea/components/Light.ts @@ -61,6 +61,7 @@ export class Light extends Component { return null; } var light = new Light(app); + light.enabled = json.enabled; light.color = Tea.Color.fromArray(json.color); light.intensity = json.intensity; light.range = json.range; diff --git a/src/tea/components/LineRenderer.ts b/src/tea/components/LineRenderer.ts index 3655ac5..643b65d 100644 --- a/src/tea/components/LineRenderer.ts +++ b/src/tea/components/LineRenderer.ts @@ -84,6 +84,7 @@ export class LineRenderer extends Renderer { return null; } var lineRenderer = new LineRenderer(app); + lineRenderer.enabled = json.enabled; return lineRenderer; } diff --git a/src/tea/components/MeshFilter.ts b/src/tea/components/MeshFilter.ts index bafe626..4307e61 100644 --- a/src/tea/components/MeshFilter.ts +++ b/src/tea/components/MeshFilter.ts @@ -31,6 +31,7 @@ export class MeshFilter extends Component { return null; } var meshFilter = new MeshFilter(app); + meshFilter.enabled = json.enabled; meshFilter.mesh = Tea.Mesh.fromJSON(app, json.mesh); return meshFilter; } diff --git a/src/tea/components/MeshRenderer.ts b/src/tea/components/MeshRenderer.ts index 599b9e4..eebe0ca 100644 --- a/src/tea/components/MeshRenderer.ts +++ b/src/tea/components/MeshRenderer.ts @@ -181,6 +181,7 @@ export class MeshRenderer extends Renderer { return null; } var meshRenderer = new MeshRenderer(app); + meshRenderer.enabled = json.enabled; meshRenderer.receiveShadows = json.receiveShadows; meshRenderer._wireframe = json.wireframe; meshRenderer.material = Tea.Material.fromJSON(app, json.material); diff --git a/src/tea/components/ParticleSystem.ts b/src/tea/components/ParticleSystem.ts index 15bf481..59eebcd 100644 --- a/src/tea/components/ParticleSystem.ts +++ b/src/tea/components/ParticleSystem.ts @@ -290,6 +290,7 @@ export class ParticleSystem extends Component { return null; } var particleSystem = new ParticleSystem(app); + particleSystem.enabled = json.enabled; return particleSystem; } diff --git a/src/tea/components/Rigidbody.ts b/src/tea/components/Rigidbody.ts index cd4795e..f89d90d 100644 --- a/src/tea/components/Rigidbody.ts +++ b/src/tea/components/Rigidbody.ts @@ -319,6 +319,7 @@ export class Rigidbody extends Component { return null; } var rigidbody = new Rigidbody(app); + rigidbody.enabled = json.enabled; return rigidbody; } diff --git a/src/tea/components/ShadowMapCamera.ts b/src/tea/components/ShadowMapCamera.ts index 2e782e5..c29eaa0 100644 --- a/src/tea/components/ShadowMapCamera.ts +++ b/src/tea/components/ShadowMapCamera.ts @@ -39,6 +39,7 @@ export class ShadowMapCamera extends Camera { return null; } var shadowMapCamera = new ShadowMapCamera(app); + shadowMapCamera.enabled = json.enabled; return shadowMapCamera; } } diff --git a/src/tea/components/TextMesh.ts b/src/tea/components/TextMesh.ts index f801bb7..487086e 100644 --- a/src/tea/components/TextMesh.ts +++ b/src/tea/components/TextMesh.ts @@ -225,6 +225,7 @@ export class TextMesh extends Component { return null; } var textMesh = new TextMesh(app); + textMesh.enabled = json.enabled; //textMesh.material = Tea.Material.fromJSON(json.material); textMesh._characterSize = json.characterSize; textMesh._lineSpacing = json.lineSpacing; diff --git a/src/tea/editor/Editor.ts b/src/tea/editor/Editor.ts index 746b593..e5ac5af 100644 --- a/src/tea/editor/Editor.ts +++ b/src/tea/editor/Editor.ts @@ -30,6 +30,7 @@ import { VResizeBar } from "./basic/VResizeBar"; import { Panel } from "./containers/Panel"; import { HLayout } from "./containers/HLayout"; import { VLayout } from "./containers/VLayout"; +import { Tabs, TabItem } from "./containers/Tabs"; import { Window } from "./containers/Window"; import { BoxCollider } from "./components/BoxCollider"; @@ -68,6 +69,8 @@ Vue.component("VResizeBar", VResizeBar); Vue.component("Panel", Panel); Vue.component("HLayout", HLayout); Vue.component("VLayout", VLayout); +Vue.component("Tabs", Tabs); +Vue.component("TabItem", TabItem); Vue.component("Window", Window); Vue.component("BoxCollider", BoxCollider); @@ -115,15 +118,22 @@ Vue.component("TextMesh", TextMesh); - - - - - - - + + + + + + + + + + + + + test + - + diff --git a/src/tea/editor/EditorBehavior.ts b/src/tea/editor/EditorBehavior.ts index 9901ff8..cd671d5 100644 --- a/src/tea/editor/EditorBehavior.ts +++ b/src/tea/editor/EditorBehavior.ts @@ -157,21 +157,24 @@ export class EditorBehavior { var inspectorView = this.editor.inspectorView; inspectorView._commands = this.commands; - inspectorView.$on("update", (key: string, value: any) => { - if (hierarchyView.getSelectedItem() == null) { - return; - } - var object3d = this.hierarchyViewCommand.getSelectedObject(); - if (object3d == null) { - return; - } - switch (key) { - case "name": - hierarchyView.getSelectedItem().model.text = value; - break; - case "rotation": - this.objectInspectorCommand.snoozeUpdateTimer(1000); - break; + inspectorView.$on("update", (type: string, key: string, value: any) => { + if (type === "ObjectInspector") { + if (hierarchyView.getSelectedItem() == null) { + return; + } + var object3d = this.hierarchyViewCommand.getSelectedObject(); + if (object3d == null) { + return; + } + this.editorCommand.isChanged = true; + switch (key) { + case "name": + hierarchyView.getSelectedItem().model.text = value; + break; + case "rotation": + this.objectInspectorCommand.snoozeUpdateTimer(1000); + break; + } } }); inspectorView.$on("change", (type: any, property: string, value: any) => { @@ -273,12 +276,9 @@ export class EditorBehavior { } setScene(scene: Tea.Scene) { - var onResize = () => { - this.updateScreenSize(); - }; var renderer = scene.app.renderer; - renderer.removeListener("resize", onResize); - renderer.on("resize", onResize); + renderer.off("resize", this.updateScreenSize); + renderer.on("resize", this.updateScreenSize); renderer.once("update", () => { this.hierarchyViewCommand.update(true); }); @@ -291,7 +291,7 @@ export class EditorBehavior { this.objectInspectorCommand.scene = scene; } - updateScreenSize(): void { + updateScreenSize = (): void => { var app = this.scene.app; var aspect = this.editor.$refs.aspect as SelectAspect; var canvas = this.editor.$refs.canvas as HTMLCanvasElement; diff --git a/src/tea/editor/ObjectInspector.ts b/src/tea/editor/ObjectInspector.ts index 8c29f27..0289174 100644 --- a/src/tea/editor/ObjectInspector.ts +++ b/src/tea/editor/ObjectInspector.ts @@ -2,7 +2,6 @@ import Vue from "vue"; import Component from "vue-class-component"; import * as Tea from "../Tea"; import { ComponentPanel } from "./components/ComponentPanel"; -import { UICommands } from "./commands/UICommands"; @Component({ template: ` @@ -38,6 +37,7 @@ import { UICommands } from "./commands/UICommands"; v-for="(item, index) in components" :type="item" :key="index" + @update="onUpdateComponent" @change="onChangeComponent" @config="onComponentMenu"> @@ -64,7 +64,6 @@ import { UICommands } from "./commands/UICommands"; } }) export class ObjectInspector extends Vue { - _commands: UICommands; _object3d: Tea.Object3D; name: string; isActive: boolean; @@ -160,6 +159,7 @@ export class ObjectInspector extends Vue { if (this._object3d != null) { this._object3d.isActive = bValue; } + this.$emit("update", "ObjectInspector", "isActive", bValue); break; case "name": var sValue = value as string; @@ -178,7 +178,7 @@ export class ObjectInspector extends Vue { if (this._object3d != null) { this._object3d.name = sValue; } - this.$emit("update", "name", sValue); + this.$emit("update", "ObjectInspector", "name", sValue); break; } } @@ -191,6 +191,7 @@ export class ObjectInspector extends Vue { if (this._object3d != null) { this._object3d.localPosition.set(x, y, z); } + this.$emit("update", "ObjectInspector", "position", position); } protected onUpdateRotation(x: number, y: number, z: number): void { @@ -201,7 +202,7 @@ export class ObjectInspector extends Vue { if (this._object3d != null) { this._object3d.localRotation.setEuler(x, y, z); } - this.$emit("update", "rotation"); + this.$emit("update", "ObjectInspector", "rotation", rotation); } protected onUpdateScale(x: number, y: number, z: number): void { @@ -212,6 +213,7 @@ export class ObjectInspector extends Vue { if (this._object3d != null) { this._object3d.localScale.set(x, y, z); } + this.$emit("update", "ObjectInspector", "rotation", scale); } protected onChangePosition(x: number, y: number, z: number): void { @@ -241,6 +243,10 @@ export class ObjectInspector extends Vue { }); } + protected onUpdateComponent(property: string, value: any): void { + this.$emit("update", "ObjectInspector", property, value); + } + protected onChangeComponent(type: any, property: string, value: any): void { this.$emit("change", type, property, value); } diff --git a/src/tea/editor/commands/EditorCommand.ts b/src/tea/editor/commands/EditorCommand.ts index 29ccec0..8cd91b3 100644 --- a/src/tea/editor/commands/EditorCommand.ts +++ b/src/tea/editor/commands/EditorCommand.ts @@ -16,18 +16,29 @@ export class EditorCommand { inspectorView: InspectorView; filename: string; - isChanged: boolean; - + protected _isChanged: boolean; protected eventHandler: EventDispatcher; constructor() { this.filename = null; - this.isChanged = false; + this._isChanged = false; this.eventHandler = new EventDispatcher(); + this.updateWindowTitle(); + } + + get isChanged(): boolean { + return this._isChanged; + } + set isChanged(value: boolean) { + if (this._isChanged === value) { + return; + } + this._isChanged = value; + this.updateWindowTitle(); } - newScene(): void { - if (this.isChanged) { + newScene(force: boolean = false): void { + if (force === false && this._isChanged) { this.showConfirmSaveDialog((response: string) => { switch (response) { case "Save": @@ -39,8 +50,7 @@ export class EditorCommand { this.saveScene(); break; case "Don't Save": - this.isChanged = false; - this.newScene(); + this.newScene(true); break; } }); @@ -59,9 +69,9 @@ export class EditorCommand { this.editor.setScene(scene); } - openScene(): void { + openScene(force: boolean = false): void { console.log("openScene"); - if (this.isChanged) { + if (force === false && this._isChanged) { this.showConfirmSaveDialog((response: string) => { switch (response) { case "Save": @@ -73,8 +83,7 @@ export class EditorCommand { this.saveScene(); break; case "Don't Save": - this.isChanged = false; - this.openScene(); + this.openScene(true); break; } }); @@ -96,7 +105,7 @@ export class EditorCommand { saveScene(): void { console.log("saveScene"); - if (this.isChanged === false) { + if (this._isChanged === false) { this.eventHandler.emit("save", null); return; } @@ -143,6 +152,26 @@ export class EditorCommand { ); } + protected updateWindowTitle(): void { + if (remote == null || remote.getCurrentWindow == null) { + return; + } + var window = remote.getCurrentWindow(); + var title = window.getTitle(); + var suffix = title.substr(-2); + if (this._isChanged) { + if (suffix !== " *") { + title += " *"; + window.setTitle(title); + } + } else { + if (suffix === " *") { + title = title.substr(0, title.length - 2); + window.setTitle(title); + } + } + } + protected save(): void { var filename = this.filename; var json = this.scene.toJSON(); diff --git a/src/tea/editor/commands/UICommands.ts b/src/tea/editor/commands/UICommands.ts index 8ee5766..2f20bb7 100644 --- a/src/tea/editor/commands/UICommands.ts +++ b/src/tea/editor/commands/UICommands.ts @@ -152,15 +152,15 @@ export class UICommands { } inspectorView.hide(); //setTimeout(() => { - var commands = this; + //var commands = this; inspectorView.component = ObjectInspector.extend({ created: function () { //(this as any)._object3d = object3d; var self = this as ObjectInspector; - self._commands = commands; + //self._commands = commands; self.setObject3D(object3d); object3d = undefined; - commands = undefined; + //commands = undefined; } }); //inspectorView.setObject3D(object3d); diff --git a/src/tea/editor/components/ComponentPanel.ts b/src/tea/editor/components/ComponentPanel.ts index 865e10e..24285a3 100644 --- a/src/tea/editor/components/ComponentPanel.ts +++ b/src/tea/editor/components/ComponentPanel.ts @@ -12,6 +12,7 @@ import { TitleBar } from "./TitleBar"; `, @@ -51,6 +52,7 @@ export class ComponentPanel extends Vue { this.enabled = value; var component = this.$refs.component as Vue; component.$data.enabled = value; + this.$emit("update", "enabled", value); } protected onClickConfig(): void { @@ -58,6 +60,10 @@ export class ComponentPanel extends Vue { this.$emit("config", component._component); } + protected onUpdate(property: string, value: any): void { + this.$emit("update", property, value); + } + protected onChange(property: string, value: any): void { var component = (this.$refs.component as any)._component; var type = null; diff --git a/src/tea/editor/containers/HLayout.ts b/src/tea/editor/containers/HLayout.ts index 4514913..af592f1 100644 --- a/src/tea/editor/containers/HLayout.ts +++ b/src/tea/editor/containers/HLayout.ts @@ -6,8 +6,7 @@ type Panel = Tea.Editor.Panel; @Component({ template: ` -
+
diff --git a/src/tea/editor/containers/Tabs.ts b/src/tea/editor/containers/Tabs.ts new file mode 100644 index 0000000..cdc19f3 --- /dev/null +++ b/src/tea/editor/containers/Tabs.ts @@ -0,0 +1,212 @@ +import Vue, { VNode } from "vue"; +import Component from "vue-class-component"; + +@Component({ + template: ` +
  • + `, + props: { + name: { + type: String, + default: "" + }, + index: { + type: Number, + default: -1 + } + } +}) +export class TabBarItem extends Vue { + name: string; + index: number; + + select(): void { + this.$el.classList.add("selected"); + } + + unselect(): void { + this.$el.classList.remove("selected"); + } + + protected onClick(): void { + this.$emit("select", this); + } +} + +@Component({ + template: ` +
      + {{ name }} +
    + `, + props: { + names: { + type: Array, + default: function () { + return []; + } + } + }, + data: () => { + return { + selectedIndex: -1 + } + }, + components: { + TabBarItem: TabBarItem + } +}) +export class TabBar extends Vue { + names: Array; + selectedIndex: number; + + select(index: number): void { + var item = this.$children[index] as TabBarItem; + if (item == null) { + return; + } + this.$children.forEach((child: TabBarItem) => { + child.unselect(); + }); + item.select(); + this.selectedIndex = index; + } + + protected onSelect(item: TabBarItem): void { + if (this.selectedIndex === item.index) { + return; + } + this.$children.forEach((child: TabBarItem) => { + child.unselect(); + }); + item.select(); + this.selectedIndex = item.index; + this.$emit("select", item.index); + } +} + +@Component({ + template: ` +
    + +
    + `, + props: { + name: { + type: String, + default: "" + } + }, + data: () => { + return { + } + } +}) +export class TabItem extends Vue { + name: string; + + show(): void { + this.$el.style.display = null; + } + + hide(): void { + this.$el.style.display = "none"; + } +} + +@Component({ + template: ` +
    + + +
    + `, + data: () => { + return { + } + }, + components: { + TabBar: TabBar + } +}) +export class Tabs extends Vue { + select(index: number): void { + console.log("select", index); + var item = this.getItem(index); + if (item == null) { + return; + } + var defaultSlot = this.$slots.default; + defaultSlot.forEach((node: VNode) => { + var child = node.componentInstance; + if (child instanceof TabItem) { + child.hide(); + } + }); + item.show(); + } + + protected mounted(): void { + var bar = this.$refs.bar as TabBar; + var firstTab = true; + var defaultSlot = this.$slots.default; + defaultSlot.forEach((node: VNode, index: number) => { + var child = node.componentInstance as TabItem; + if ((child instanceof TabItem) === false) { + return; + } + if (firstTab === false) { + child.hide(); + } + firstTab = false; + var name = this.getName(child.name, index); + bar.names.push(name); + }); + this.$nextTick(() => { + bar.select(0); + }); + } + + protected getName(name: string, index: number): string { + if (name != null && name !== "") { + return name; + } + return "Tab " + index; + } + + protected getItem(index: number): TabItem { + if (index < 0) { + return null; + } + var item: TabItem = null; + var count = 0; + var defaultSlot = this.$slots.default; + defaultSlot.some((node: VNode): boolean => { + var child = node.componentInstance as TabItem; + if ((child instanceof TabItem) === false) { + return; + } + if (count == index) { + item = child; + return true; + } + count++; + return false; + }); + return item; + } + + protected onSelect(index: number): void { + if (index < 0) { + return; + } + this.select(index); + } +} diff --git a/src/tea/editor/containers/VLayout.ts b/src/tea/editor/containers/VLayout.ts index 4f5e0fc..2dfb11e 100644 --- a/src/tea/editor/containers/VLayout.ts +++ b/src/tea/editor/containers/VLayout.ts @@ -6,8 +6,7 @@ type Panel = Tea.Editor.Panel; @Component({ template: ` -
    +
    diff --git a/src/tea/editor/containers/css/Tabs.scss b/src/tea/editor/containers/css/Tabs.scss new file mode 100644 index 0000000..c2a733c --- /dev/null +++ b/src/tea/editor/containers/css/Tabs.scss @@ -0,0 +1,37 @@ +#{$parent} { + div.Tabs { + display: flex; + flex-direction: column; + position: relative; + box-sizing: border-box; + background-color: theme("background"); + overflow: hidden; + + > ul.TabBar { + display: flex; + flex-direction: row; + justify-content: flex-start; + margin: 0; + padding: 0; + list-style-type: none; + + > li { + margin-right: 0.1em; + padding: 2px 5px 1px 5px; + } + > li.selected { + padding: 1px 4px 1px 4px; + border-top: 1px solid gray; + border-left: 1px solid gray; + border-right: 1px solid gray; + border-radius: 0.3em 0.3em 0 0; + } + } + + div.TabItem { + flex: 1; + width: 100%; + overflow: hidden; + } + } +} diff --git a/src/tea/editor/css/Editor.scss b/src/tea/editor/css/Editor.scss index f999090..f1bf4ac 100644 --- a/src/tea/editor/css/Editor.scss +++ b/src/tea/editor/css/Editor.scss @@ -23,6 +23,7 @@ $parent: "#editor"; @import "../containers/css/Panel.scss"; @import "../containers/css/HLayout.scss"; @import "../containers/css/VLayout.scss"; +@import "../containers/css/Tabs.scss"; @import "../containers/css/Window.scss"; @import "../components/css/Camera.scss"; @@ -74,10 +75,13 @@ $parent: "#editor"; div.CanvasPanel::-webkit-scrollbar { display: none; } - div.BottomLayout { - position: relative; + + div.Tabs.Bottom { height: 200px; border-top: 1px solid theme("border"); + } + div.BottomLayout { + position: relative; .Panel { overflow: auto; @@ -99,8 +103,8 @@ $parent: "#editor"; div.dragImages { position: absolute; - left: -300px; - top: 0; + left: 0; + top: 101%; > .dragImage { opacity: 0.6; diff --git a/src/tea/objects/Scene.ts b/src/tea/objects/Scene.ts index 3ea081a..ddbdb4e 100644 --- a/src/tea/objects/Scene.ts +++ b/src/tea/objects/Scene.ts @@ -292,11 +292,7 @@ export class Scene { this._isCleared = false; this._children = []; this._components = new SceneComponents(); - this.app.renderer.on("resize", () => { - //console.log("resize"); - this.renderTexture.destroy(); - this.refreshRenderTexture(); - }) + this.app.renderer.on("resize", this.onResize); } get children(): Array { @@ -308,6 +304,7 @@ export class Scene { } destroy(): void { + this.app.renderer.off("resize", this.onResize); var children = this.children; var length = children.length; for (var i = length - 1; i >= 0 ; i--) { @@ -767,4 +764,10 @@ export class Scene { //this.renderTexture.filterMode = Tea.FilterMode.Bilinear; //this.renderTexture.wrapMode = Tea.TextureWrapMode.Mirror; } + + protected onResize = () => { + //console.log("resize"); + this.renderTexture.destroy(); + this.refreshRenderTexture(); + } }