|
1 | 1 | package oxy.bascenario.editor.containers; |
2 | 2 |
|
| 3 | +import lombok.RequiredArgsConstructor; |
| 4 | +import lombok.Setter; |
| 5 | +import lombok.experimental.Accessors; |
3 | 6 | import net.lenni0451.commons.color.Color; |
4 | 7 | import net.lenni0451.rivet.backend.render.Renderer; |
| 8 | +import net.lenni0451.rivet.component.Component; |
5 | 9 | import net.lenni0451.rivet.component.container.Container; |
| 10 | +import net.lenni0451.rivet.input.keyboard.Key; |
| 11 | +import net.lenni0451.rivet.input.keyboard.KeyEvent; |
6 | 12 | import net.lenni0451.rivet.input.mouse.MouseButton; |
7 | 13 | import net.lenni0451.rivet.input.mouse.MouseButtonEvent; |
8 | 14 | import net.lenni0451.rivet.input.mouse.MouseMoveEvent; |
| 15 | +import net.lenni0451.rivet.layout.Layout; |
9 | 16 | import net.lenni0451.rivet.layout.dock.DockLayout; |
10 | 17 | import net.lenni0451.rivet.layout.dock.DockPosition; |
11 | 18 | import net.lenni0451.rivet.math.Rectangle; |
12 | 19 | import net.lenni0451.rivet.math.Size; |
13 | 20 | import net.raphimc.thingl.ThinGL; |
14 | 21 | import net.raphimc.thingl.implementation.window.GLFWWindowInterface; |
15 | 22 | import org.lwjgl.glfw.GLFW; |
| 23 | +import oxy.bascenario.editor.EditorValues; |
| 24 | +import oxy.bascenario.editor.containers.assets.AssetsContainer; |
16 | 25 | import oxy.bascenario.editor.containers.timeline.TimelineContainer; |
17 | 26 |
|
18 | | -public class GlobalContainer extends Container { |
19 | | - private final TimelineContainer timeline; |
| 27 | +import java.util.HashMap; |
| 28 | +import java.util.Map; |
20 | 29 |
|
| 30 | +public class GlobalContainer extends Container { |
21 | 31 | public GlobalContainer() { |
22 | | - super(new DockLayout()); |
| 32 | + super(new DockLayout(3)); |
23 | 33 |
|
24 | | - addChild(timeline = new TimelineContainer(), c -> c.layoutOptions(DockPosition.BOTTOM)); |
| 34 | + addChild(new TimelineContainer(), c -> c.layoutOptions(DockPosition.BOTTOM)); |
| 35 | + addChild(new AssetsContainer(), c -> c.layoutOptions(DockPosition.LEFT)); |
| 36 | + |
| 37 | + for (Component component : children()) { |
| 38 | + resizableComponents.put((ResizeableContainer) component, new ResizeComponent( |
| 39 | + component.layoutOptions() == DockPosition.BOTTOM || component.layoutOptions() == DockPosition.TOP ? |
| 40 | + ResizeComponent.ResizeType.Vertical : ResizeComponent.ResizeType.Horizontal, |
| 41 | + (DockPosition) component.layoutOptions() |
| 42 | + )); |
| 43 | + } |
25 | 44 | } |
26 | 45 |
|
27 | | - float prevMouseY; |
28 | | - boolean nearTimeline, nearTimelineAndMouseDown; |
| 46 | + final Map<ResizeableContainer, ResizeComponent> resizableComponents = new HashMap<>(); |
| 47 | + |
29 | 48 | @Override |
30 | 49 | public void render(Renderer renderer, Size size) { |
31 | 50 | super.render(renderer, size); |
32 | 51 |
|
33 | | - if (nearTimelineAndMouseDown) { |
34 | | - Rectangle bounds = this.childBounds(timeline); |
35 | | - renderer.fillRect(bounds.x(), bounds.y() - 5, bounds.width(), 2, Color.fromRGB(115, 115, 115)); |
| 52 | + for (Map.Entry<ResizeableContainer, ResizeComponent> entry : resizableComponents.entrySet()) { |
| 53 | + if (!entry.getValue().nearAndMouseDown) { |
| 54 | + continue; |
| 55 | + } |
| 56 | + final ResizeComponent component = entry.getValue(); |
| 57 | + |
| 58 | + Rectangle bounds = this.childBounds(entry.getKey()); |
| 59 | + |
| 60 | + if (component.type == ResizeComponent.ResizeType.Horizontal) { |
| 61 | + if (component.position == DockPosition.LEFT) { |
| 62 | + renderer.fillRect(bounds.maxX() + 5, bounds.y(), 2, bounds.height(), Color.fromRGB(115, 115, 115)); |
| 63 | + } else { |
| 64 | + renderer.fillRect(bounds.x() + 5, bounds.y(), 2, bounds.height(), Color.fromRGB(115, 115, 115)); |
| 65 | + } |
| 66 | + } else { |
| 67 | + renderer.fillRect(bounds.x(), bounds.y() - 5, bounds.width(), 2, Color.fromRGB(115, 115, 115)); |
| 68 | + } |
36 | 69 | } |
37 | 70 | } |
38 | 71 |
|
39 | 72 | @Override |
40 | 73 | protected boolean onComponentMouseMove(MouseMoveEvent event, Size size) { |
41 | 74 | super.onComponentMouseMove(event, size); |
42 | 75 |
|
43 | | - Rectangle timelineBounds = this.childBounds(timeline); |
44 | | - boolean nearTimeline = Math.abs(event.y() - timelineBounds.y()) < 8; |
45 | | - if (nearTimeline && !this.nearTimeline) { |
46 | | - GLFW.glfwSetCursor(((GLFWWindowInterface) ThinGL.windowInterface()).getWindowHandle(), GLFW.glfwCreateStandardCursor(GLFW.GLFW_VRESIZE_CURSOR)); |
47 | | - } else if (!nearTimeline && this.nearTimeline && !nearTimelineAndMouseDown) { |
48 | | - GLFW.glfwSetCursor(((GLFWWindowInterface) ThinGL.windowInterface()).getWindowHandle(), GLFW.glfwCreateStandardCursor(GLFW.GLFW_ARROW_CURSOR)); |
49 | | - } |
50 | | - this.nearTimeline = nearTimeline; |
51 | | - if (!nearTimelineAndMouseDown) { |
52 | | - this.nearTimelineAndMouseDown = event.isHeld(MouseButton.LEFT) && nearTimeline; |
53 | | - } |
| 76 | + for (Map.Entry<ResizeableContainer, ResizeComponent> entry : resizableComponents.entrySet()) { |
| 77 | + final ResizeComponent component = entry.getValue(); |
| 78 | + Rectangle bounds = this.childBounds(entry.getKey()); |
54 | 79 |
|
55 | | - if (nearTimelineAndMouseDown && prevMouseY != Float.MAX_VALUE) { |
56 | | - float newHeight = timelineBounds.height() - (event.y() - prevMouseY); |
57 | | - float ratio = newHeight / size.height(); |
58 | | - timeline.relativeScale(ratio); |
59 | | - timeline.requestLayoutRecalculation(); |
60 | | - } |
| 80 | + boolean near; |
| 81 | + if (component.type == ResizeComponent.ResizeType.Vertical) { |
| 82 | + near = Math.abs(event.y() - bounds.y()) < 4; |
| 83 | + } else { |
| 84 | + if (component.position == DockPosition.LEFT) { |
| 85 | + near = Math.abs(event.x() - bounds.maxX()) < 4; |
| 86 | + } else { |
| 87 | + near = Math.abs(event.x() - bounds.x()) < 4; |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + if (near && !component.near) { |
| 92 | + int mouse = component.type == ResizeComponent.ResizeType.Vertical ? GLFW.GLFW_VRESIZE_CURSOR : GLFW.GLFW_HRESIZE_CURSOR; |
| 93 | + GLFW.glfwSetCursor(((GLFWWindowInterface) ThinGL.windowInterface()).getWindowHandle(), GLFW.glfwCreateStandardCursor(mouse)); |
| 94 | + } else if (!near && component.near && !component.nearAndMouseDown) { |
| 95 | + GLFW.glfwSetCursor(((GLFWWindowInterface) ThinGL.windowInterface()).getWindowHandle(), GLFW.glfwCreateStandardCursor(GLFW.GLFW_ARROW_CURSOR)); |
| 96 | + } |
| 97 | + |
| 98 | + component.near = near; |
| 99 | + if (!component.nearAndMouseDown) { |
| 100 | + component.nearAndMouseDown = event.isHeld(MouseButton.LEFT) && near; |
| 101 | + } |
| 102 | + |
| 103 | + if (component.nearAndMouseDown && component.prevMouse != Float.MAX_VALUE) { |
| 104 | + if (component.type == ResizeComponent.ResizeType.Vertical) { |
| 105 | + float newHeight = bounds.height() - (event.y() - component.prevMouse); |
| 106 | + entry.getKey().relativeScale = newHeight / size.height(); |
| 107 | + entry.getKey().requestLayoutRecalculation(); |
| 108 | + } else { |
| 109 | + float newWidth = bounds.width() - (event.x() - component.prevMouse) * (component.position == DockPosition.LEFT ? -1 : 1); |
| 110 | + entry.getKey().relativeScale = newWidth / size.width(); |
| 111 | + entry.getKey().requestLayoutRecalculation(); |
| 112 | + } |
| 113 | + } |
61 | 114 |
|
62 | | - prevMouseY = event.y(); |
63 | | - if (!nearTimeline || !nearTimelineAndMouseDown) { |
64 | | - prevMouseY = Float.MAX_VALUE; |
| 115 | + component.prevMouse = component.type == ResizeComponent.ResizeType.Vertical ? event.y() : event.x(); |
| 116 | + if (!component.near || !component.nearAndMouseDown) { |
| 117 | + component.prevMouse = Float.MAX_VALUE; |
| 118 | + } |
65 | 119 | } |
66 | 120 |
|
67 | 121 | return true; |
68 | 122 | } |
69 | 123 |
|
70 | 124 | @Override |
71 | 125 | protected boolean onComponentMouseUp(MouseButtonEvent event, Size size) { |
72 | | - this.nearTimelineAndMouseDown = false; |
| 126 | + this.resizableComponents.values().forEach(c -> c.nearAndMouseDown = false); |
73 | 127 | return super.onComponentMouseUp(event, size); |
74 | 128 | } |
75 | 129 |
|
76 | 130 | @Override |
77 | 131 | protected boolean onComponentMouseDown(MouseButtonEvent event, Size size) { |
78 | | - this.nearTimelineAndMouseDown = event.button() == MouseButton.LEFT && nearTimeline; |
79 | | - if (!nearTimelineAndMouseDown) { |
80 | | - prevMouseY = Float.MAX_VALUE; |
81 | | - } |
| 132 | + this.resizableComponents.values().forEach(c -> { |
| 133 | + c.nearAndMouseDown = event.button() == MouseButton.LEFT && c.near; |
| 134 | + if (!c.nearAndMouseDown) { |
| 135 | + c.prevMouse = Float.MAX_VALUE; |
| 136 | + } |
| 137 | + }); |
82 | 138 |
|
83 | 139 | super.onComponentMouseDown(event, size); |
84 | 140 | return true; |
85 | 141 | } |
| 142 | + |
| 143 | + @Override |
| 144 | + protected boolean onComponentKeyUp(KeyEvent event) { |
| 145 | + if (event.key() == Key.SPACE) { |
| 146 | + EditorValues.instance().playing(!EditorValues.instance().playing()); |
| 147 | + } |
| 148 | + |
| 149 | + return super.onComponentKeyUp(event); |
| 150 | + } |
| 151 | + |
| 152 | + @RequiredArgsConstructor |
| 153 | + private static class ResizeComponent { |
| 154 | + private final ResizeType type; |
| 155 | + private final DockPosition position; |
| 156 | + private boolean near, nearAndMouseDown; |
| 157 | + private float prevMouse = Float.MAX_VALUE; |
| 158 | + |
| 159 | + public enum ResizeType { |
| 160 | + Horizontal, Vertical |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + @Accessors(fluent = true) |
| 165 | + public static class ResizeableContainer extends Container { |
| 166 | + @Setter |
| 167 | + protected float relativeScale = 0.2f; |
| 168 | + public ResizeableContainer(Layout layout) { |
| 169 | + super(layout); |
| 170 | + } |
| 171 | + } |
86 | 172 | } |
0 commit comments