Skip to content

Commit 4a81a04

Browse files
committed
fix(app): many updates
1 parent 66923a5 commit 4a81a04

36 files changed

Lines changed: 765 additions & 363 deletions

packages/app/components/App.vue

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
<cw-panel-unit-preview v-if="selectedUnit" :unit="selectedUnit">
99
<template #actions>
1010
<cw-button @click="onClickRotate">Rotate</cw-button>
11+
<cw-button
12+
v-if="canPlaced"
13+
:selected="!!placedUnit"
14+
@click="onClickPlacement"
15+
>Move</cw-button
16+
>
1117
</template>
1218
</cw-panel-unit-preview>
1319
<cw-panel-camera-control v-if="app" :app="app" />
@@ -16,8 +22,16 @@
1622

1723
<script lang="ts" setup>
1824
import Renderer from './Renderer.vue';
19-
import { markRaw, nextTick, onMounted, onUnmounted, ref, type Raw } from 'vue';
20-
import { Subscription } from 'rxjs';
25+
import {
26+
computed,
27+
markRaw,
28+
nextTick,
29+
onMounted,
30+
onUnmounted,
31+
ref,
32+
type Raw
33+
} from 'vue';
34+
import { fromEvent, Subscription } from 'rxjs';
2135
import { Vector2 } from 'three';
2236
import Player from '../lib/classes/Player';
2337
import App from '../lib/classes/App';
@@ -37,7 +51,6 @@ const rendererEl = ref<InstanceType<typeof Renderer> | null>(null);
3751
const subscription = new Subscription();
3852
3953
const dimension = ref<Vector2>();
40-
let resizeObserver: ResizeObserver;
4154
4255
setupFonts();
4356
defineProps<{
@@ -46,6 +59,9 @@ defineProps<{
4659
4760
const app = ref<App>();
4861
const selectedUnit = ref<Raw<Unit> | null>(null);
62+
const placedUnit = ref<Raw<Unit> | null>(null);
63+
const canPlaced = computed(() => selectedUnit.value?.options.canPlaced);
64+
4965
// let sceneUnsubscribe;
5066
onMounted(async () => {
5167
nextTick(() => {
@@ -54,7 +70,7 @@ onMounted(async () => {
5470
});
5571
5672
function setup() {
57-
const { $el, renderer } = rendererEl.value!;
73+
const { renderer } = rendererEl.value!;
5874
5975
if (!renderer) {
6076
throw new Error('Renderer not ready');
@@ -77,27 +93,51 @@ function setup() {
7793
selectedUnit.value = unit ? markRaw(unit) : null;
7894
})
7995
);
96+
subscription.add(
97+
app.value.modules.placement.startPlace$.subscribe(unit => {
98+
placedUnit.value = unit;
99+
})
100+
);
101+
subscription.add(
102+
app.value.modules.placement.stopPlace$.subscribe(() => {
103+
placedUnit.value = null;
104+
})
105+
);
80106
81-
const onResize = () => {
82-
dimension.value = new Vector2($el.offsetWidth, $el.offsetHeight);
83-
renderer.resize(dimension.value);
84-
};
85-
resizeObserver = new ResizeObserver(onResize);
107+
subscription.add(
108+
fromEvent(window, 'resize', {
109+
passive: true
110+
}).subscribe(() => {
111+
onResize();
112+
})
113+
);
86114
87-
resizeObserver.observe($el);
115+
onResize();
88116
}
89117
90118
onUnmounted(() => {
91-
resizeObserver.disconnect();
92119
subscription.unsubscribe();
93120
app.value?.destroy();
94121
});
95122
123+
const rootEl = ref<HTMLElement>();
124+
function onResize() {
125+
const { width, height } = rootEl.value!.getBoundingClientRect();
126+
dimension.value = new Vector2(width, height);
127+
rendererEl.value?.renderer?.resize(dimension.value);
128+
}
129+
96130
function onClickRotate() {
97131
if (selectedUnit.value) {
98132
selectedUnit.value.rotateRight();
99133
}
100134
}
135+
136+
function onClickPlacement() {
137+
if (selectedUnit.value) {
138+
app.value?.modules.placement?.startPlace(selectedUnit.value);
139+
}
140+
}
101141
</script>
102142

103143
<style lang="postcss" scoped>

packages/app/components/Button.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<base-button
33
class="cw-button"
4-
:class="{ [`style-type-${styleType}`]: styleType }">
4+
:class="{ selected, [`style-type-${styleType}`]: styleType }">
55
<slot>Button</slot>
66
</base-button>
77
</template>
@@ -11,6 +11,7 @@ import BaseButton from './base/Button.vue';
1111
1212
defineProps<{
1313
styleType?: 'light' | 'dark';
14+
selected?: boolean;
1415
}>();
1516
</script>
1617

@@ -30,6 +31,7 @@ defineProps<{
3031
opacity: 0.5;
3132
}
3233
34+
&.selected,
3335
&:not([disabled]):hover {
3436
background: rgb(255 255 255 / 10%);
3537
}

packages/app/components/Panel.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ defineProps<{
2222
gap: 10px;
2323
padding: 1em;
2424
color: white;
25-
background: rgb(0 0 0 / 60%);
25+
background: rgb(0 0 0 / 80%);
26+
border: solid 1px rgb(255 255 255 / 80%);
2627
border-radius: 9px;
28+
box-shadow: 0 0 4px 0 rgb(0 0 0 / 40%);
2729
2830
& .title {
2931
display: block;
32+
font-size: 14px;
3033
font-weight: bold;
3134
text-align: center;
3235
}

packages/app/components/Renderer.vue

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div ref="rootEl" class="cw-renderer">
2+
<div
3+
ref="rootEl"
4+
class="cw-renderer"
5+
:class="{ pixelated: renderer?.pixelated }">
36
<canvas ref="canvasEl" />
47
</div>
58
</template>
@@ -35,7 +38,7 @@ const canvasEl = ref();
3538
const subscription = new Subscription();
3639
3740
const defaultRendererOptions: RendererOptions = {
38-
pixelSize: 1,
41+
pixelated: false,
3942
controls: true
4043
};
4144
@@ -44,15 +47,15 @@ onMounted(async () => {
4447
rootEl.value.offsetWidth,
4548
rootEl.value.offsetHeight
4649
);
47-
const { pixelSize, controls } = $props.options || defaultRendererOptions;
50+
const { pixelated, controls } = $props.options || defaultRendererOptions;
4851
4952
renderer.value = markRaw(
5053
new Renderer(
5154
canvasEl.value,
5255
dimension,
5356
{
5457
debug: !!$props.debug,
55-
pixelSize: pixelSize,
58+
pixelated: pixelated,
5659
controls: controls
5760
},
5861
$props.modules
@@ -86,10 +89,15 @@ defineExpose({
8689
</script>
8790

8891
<style lang="postcss" scoped>
89-
canvas {
90-
touch-action: none;
91-
image-rendering: optimizeSpeed; /* Für ältere Browser */
92-
image-rendering: crisp-edges; /* Für moderne Browser */
93-
image-rendering: pixelated;
92+
.cw-renderer {
93+
&.pixelated {
94+
image-rendering: optimizeSpeed;
95+
image-rendering: crisp-edges;
96+
image-rendering: pixelated;
97+
}
98+
99+
& canvas {
100+
touch-action: none;
101+
}
94102
}
95103
</style>

packages/app/components/debug/UnitPreview.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ function setupScene(renderer: Renderer) {
101101
const groundMesh = new Mesh(groundTile.geometry, groundTile.material);
102102
groundMesh.material.side = DoubleSide;
103103
groundMesh.receiveShadow = true;
104+
groundMesh.material.side = DoubleSide;
104105
scene.add(groundMesh);
105106
// #endregion
106107

packages/app/components/panel/UnitPreview.vue

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
</li>
1212
</ul>
1313

14-
<div v-if="$slots.actions">
14+
<div v-if="$slots.actions" class="actions">
1515
<slot name="actions"></slot>
1616
</div>
1717
</cw-panel>
@@ -48,13 +48,15 @@ function refresh(unit: Unit) {
4848
}
4949
5050
function refreshDebugInfo(unit: Unit) {
51-
const position = unit.getRootPosition();
51+
const position = unit.getPosition();
5252
const rotation = unit.getRootRotation();
53+
const size = unit.size;
5354
5455
const info = {
5556
Pos: `${position.x.toFixed(2)}x${position.y.toFixed(2)}x${position.z.toFixed(2)}`,
5657
Rot: `${rotation.x.toFixed(2)}x${rotation.y.toFixed(2)}`,
57-
URot: `${$props.unit.rotation}`
58+
URot: `${$props.unit.rotation}`,
59+
Size: `${size.x}x${size.y}`
5860
};
5961
debugInfo.value = Object.entries(info);
6062
}
@@ -211,5 +213,12 @@ watch(
211213
align-items: center;
212214
justify-content: center;
213215
}
216+
217+
& .actions {
218+
display: flex;
219+
flex-direction: row;
220+
gap: 10px;
221+
justify-content: center;
222+
}
214223
}
215224
</style>

packages/app/lib/classes/App.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@ import UnitFocusAppModule from './appModule/UnitFocus';
77
import RoomAppModule from './appModule/Room';
88
import PlayerAppModule from './appModule/Player';
99
import SelectionAppModule from './appModule/Selection';
10+
import PlacementAppModule from './appModule/Placement';
1011

1112
type AppModuleList = (
1213
| typeof UnitFocusAppModule
1314
| typeof PlayerAppModule
1415
| typeof RoomAppModule
1516
| typeof SelectionAppModule
17+
| typeof PlacementAppModule
1618
)[];
1719
interface AppModules {
1820
room: RoomAppModule;
1921
player: PlayerAppModule;
2022
unitFocus: UnitFocusAppModule;
2123
selection: SelectionAppModule;
24+
placement: PlacementAppModule;
2225
}
2326

2427
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
@@ -43,7 +46,8 @@ export default class App {
4346
RoomAppModule,
4447
PlayerAppModule,
4548
UnitFocusAppModule,
46-
SelectionAppModule
49+
SelectionAppModule,
50+
PlacementAppModule
4751
);
4852

4953
// #region Modules

0 commit comments

Comments
 (0)