gaesup-world 0.9.58 → 0.9.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -731,17 +731,17 @@ The **Passive** component defines objects that do not require interaction, such
731
731
 
732
732
  ---
733
733
 
734
- #### JumpPortal
734
+ #### teleport
735
735
 
736
736
  - **Description**: Represents a clickable portal that allows users to teleport to a specified location within the 3D world. Ideal for creating interactive teleportation points in your application.
737
737
 
738
738
  - **Props**:
739
739
 
740
- | Prop Name | Type | Required | Description | Default Value |
741
- | ----------------- | ------------- | -------- | ----------------------------------------------------------- | ------------- |
742
- | `text` | string | Optional | The text to display on the portal. | `undefined` |
743
- | `position` | THREE.Vector3 | Required | The target position to teleport to using a `THREE.Vector3`. | None |
744
- | `jumpPortalStyle` | CSSProperties | Optional | CSS styles for customizing the appearance of the portal. | `undefined` |
740
+ | Prop Name | Type | Required | Description | Default Value |
741
+ | --------------- | ------------- | -------- | ----------------------------------------------------------- | ------------- |
742
+ | `text` | string | Optional | The text to display on the portal. | `undefined` |
743
+ | `position` | THREE.Vector3 | Required | The target position to teleport to using a `THREE.Vector3`. | None |
744
+ | `teleportStyle` | CSSProperties | Optional | CSS styles for customizing the appearance of the portal. | `undefined` |
745
745
 
746
746
  - **Usage Example**:
747
747
 
@@ -749,7 +749,7 @@ The **Passive** component defines objects that do not require interaction, such
749
749
  import React from 'react';
750
750
  import { Canvas } from '@react-three/fiber';
751
751
  import { Physics } from '@react-three/rapier';
752
- import { GaesupWorld, JumpPortal } from '../../../src';
752
+ import { GaesupWorld, teleport } from '../../../src';
753
753
  import * as THREE from 'three';
754
754
 
755
755
  export default function App() {
@@ -764,10 +764,10 @@ The **Passive** component defines objects that do not require interaction, such
764
764
  >
765
765
  <Canvas>
766
766
  <Physics>
767
- <JumpPortal
767
+ <teleport
768
768
  text="Teleport"
769
769
  position={new THREE.Vector3(10, 0, 5)}
770
- jumpPortalStyle={{ backgroundColor: "blue", color: "white" }}
770
+ teleportStyle={{ backgroundColor: "blue", color: "white" }}
771
771
  />
772
772
  {/* Other components */}
773
773
  </Physics>
@@ -779,7 +779,7 @@ The **Passive** component defines objects that do not require interaction, such
779
779
 
780
780
  - **Key Features**:
781
781
  - **Teleport Functionality**: Moves the camera and character to the specified position upon clicking the portal.
782
- - **Custom Styling**: Customize the portal's appearance using `jumpPortalStyle`.
782
+ - **Custom Styling**: Customize the portal's appearance using `teleportStyle`.
783
783
  - **Text Display**: Displays text on the portal to guide users.
784
784
 
785
785
  ---
@@ -1543,17 +1543,17 @@ export default function App() {
1543
1543
 
1544
1544
  ---
1545
1545
 
1546
- #### JumpPortal
1546
+ #### teleport
1547
1547
 
1548
1548
  - **설명**: 클릭 가능한 포탈을 통해 사용자를 지정된 위치로 텔레포트할 수 있는 컴포넌트입니다. 인터랙티브한 텔레포테이션 포인트를 생성하는 데 사용됩니다.
1549
1549
 
1550
1550
  - **Props**:
1551
1551
 
1552
- | Prop Name | Type | Required | Description | Default Value |
1553
- | ----------------- | ------------- | -------- | ---------------------------------------------- | ------------- |
1554
- | `text` | string | Optional | 포탈에 표시할 텍스트 | `undefined` |
1555
- | `position` | THREE.Vector3 | Required | 텔레포트할 목표 위치 | None |
1556
- | `jumpPortalStyle` | CSSProperties | Optional | 포탈의 외관을 커스터마이징하기 위한 CSS 스타일 | `undefined` |
1552
+ | Prop Name | Type | Required | Description | Default Value |
1553
+ | --------------- | ------------- | -------- | ---------------------------------------------- | ------------- |
1554
+ | `text` | string | Optional | 포탈에 표시할 텍스트 | `undefined` |
1555
+ | `position` | THREE.Vector3 | Required | 텔레포트할 목표 위치 | None |
1556
+ | `teleportStyle` | CSSProperties | Optional | 포탈의 외관을 커스터마이징하기 위한 CSS 스타일 | `undefined` |
1557
1557
 
1558
1558
  - **사용 예제**:
1559
1559
 
@@ -1561,7 +1561,7 @@ export default function App() {
1561
1561
  import React from 'react';
1562
1562
  import { Canvas } from '@react-three/fiber';
1563
1563
  import { Physics } from '@react-three/rapier';
1564
- import { GaesupWorld, JumpPortal } from '../../../src';
1564
+ import { GaesupWorld, teleport } from '../../../src';
1565
1565
  import * as THREE from 'three';
1566
1566
 
1567
1567
  export default function App() {
@@ -1576,10 +1576,10 @@ export default function App() {
1576
1576
  >
1577
1577
  <Canvas>
1578
1578
  <Physics>
1579
- <JumpPortal
1579
+ <teleport
1580
1580
  text="Teleport"
1581
1581
  position={new THREE.Vector3(10, 0, 5)}
1582
- jumpPortalStyle={{ backgroundColor: "blue", color: "white" }}
1582
+ teleportStyle={{ backgroundColor: "blue", color: "white" }}
1583
1583
  />
1584
1584
  {/* 다른 컴포넌트 */}
1585
1585
  </Physics>
@@ -1591,7 +1591,7 @@ export default function App() {
1591
1591
 
1592
1592
  - **주요 기능**:
1593
1593
  - **텔레포트 기능**: 버튼 클릭 시 카메라와 캐릭터를 지정된 위치로 이동시킵니다.
1594
- - **커스터마이징**: `jumpPortalStyle`을 통해 포탈의 외관을 자유롭게 커스터마이징할 수 있습니다.
1594
+ - **커스터마이징**: `teleportStyle`을 통해 포탈의 외관을 자유롭게 커스터마이징할 수 있습니다.
1595
1595
  - **텍스트 표시**: 포탈에 표시할 텍스트를 통해 사용자에게 명확한 안내를 제공합니다.
1596
1596
 
1597
1597
  ---
@@ -1,52 +1,12 @@
1
1
  import { useFrame } from "@react-three/fiber";
2
- import { Ref, useContext, useEffect } from "react";
3
- import * as THREE from "three";
4
- import {
5
- AnimationAction,
6
- AnimationClip,
7
- AnimationMixer,
8
- Object3D,
9
- Object3DEventMap,
10
- } from "three";
11
- import { animationTagType, groundRayType } from "../controller/type";
2
+ import { useContext, useEffect } from "react";
3
+ import { animationTagType } from "../controller/type";
12
4
  import { useGaesupAnimation } from "../hooks/useGaesupAnimation";
13
5
  import {
14
6
  GaesupWorldContext,
15
7
  GaesupWorldDispatchContext,
16
8
  } from "../world/context";
17
-
18
- export type Api<T extends AnimationClip> = {
19
- ref: React.MutableRefObject<Object3D | undefined | null>;
20
- clips: AnimationClip[];
21
- mixer: AnimationMixer;
22
- names: T["name"][];
23
- actions: {
24
- [key in T["name"]]: AnimationAction | null;
25
- };
26
- };
27
-
28
- export type playActionsType = {
29
- type: "character" | "vehicle" | "airplane";
30
- currentAnimation?: string;
31
- actions: actionsType;
32
- animationRef: Ref<Object3D<Object3DEventMap>>;
33
- isActive: boolean;
34
- };
35
-
36
- export type subscribeActionsType = {
37
- type: "character" | "vehicle" | "airplane";
38
- groundRay: groundRayType;
39
- animations: AnimationClip[];
40
- };
41
-
42
- export type actionsType = {
43
- [x: string]: THREE.AnimationAction | null;
44
- };
45
-
46
- export type playResultType = {
47
- actions: actionsType;
48
- ref: Ref<Object3D<Object3DEventMap>>;
49
- };
9
+ import { playActionsType, subscribeActionsType } from "./type";
50
10
 
51
11
  export function subscribeActions({ type }: subscribeActionsType) {
52
12
  const { states } = useContext(GaesupWorldContext);
@@ -0,0 +1,43 @@
1
+ import { Ref } from "react";
2
+ import * as THREE from "three";
3
+ import {
4
+ AnimationAction,
5
+ AnimationClip,
6
+ AnimationMixer,
7
+ Object3D,
8
+ Object3DEventMap,
9
+ } from "three";
10
+ import { groundRayType } from "../controller/type";
11
+
12
+ export type Api<T extends AnimationClip> = {
13
+ ref: React.MutableRefObject<Object3D | undefined | null>;
14
+ clips: AnimationClip[];
15
+ mixer: AnimationMixer;
16
+ names: T["name"][];
17
+ actions: {
18
+ [key in T["name"]]: AnimationAction | null;
19
+ };
20
+ };
21
+
22
+ export type playActionsType = {
23
+ type: "character" | "vehicle" | "airplane";
24
+ currentAnimation?: string;
25
+ actions: actionsType;
26
+ animationRef: Ref<Object3D<Object3DEventMap>>;
27
+ isActive: boolean;
28
+ };
29
+
30
+ export type subscribeActionsType = {
31
+ type: "character" | "vehicle" | "airplane";
32
+ groundRay: groundRayType;
33
+ animations: AnimationClip[];
34
+ };
35
+
36
+ export type actionsType = {
37
+ [x: string]: THREE.AnimationAction | null;
38
+ };
39
+
40
+ export type playResultType = {
41
+ actions: actionsType;
42
+ ref: Ref<Object3D<Object3DEventMap>>;
43
+ };
@@ -6,7 +6,13 @@ import {
6
6
  RigidBody,
7
7
  euler,
8
8
  } from "@react-three/rapier";
9
- import { MutableRefObject, forwardRef, useContext, useMemo } from "react";
9
+ import {
10
+ MutableRefObject,
11
+ forwardRef,
12
+ useContext,
13
+ useEffect,
14
+ useMemo,
15
+ } from "react";
10
16
  import * as THREE from "three";
11
17
  import { SkeletonUtils } from "three-stdlib";
12
18
  import playActions, { subscribeActions } from "../../../animation/actions";
@@ -27,13 +33,15 @@ export const RigidBodyRef = forwardRef(
27
33
  (props: rigidBodyRefType, ref: MutableRefObject<RapierRigidBody>) => {
28
34
  const { size } = useGltfAndSize({ url: props.url });
29
35
  const setGroundRay = useSetGroundRay();
30
-
31
- props.groundRay &&
32
- setGroundRay({
33
- groundRay: props.groundRay,
34
- length: 0.5,
35
- colliderRef: props.colliderRef,
36
- });
36
+ useEffect(() => {
37
+ if (props.groundRay && props.colliderRef) {
38
+ setGroundRay({
39
+ groundRay: props.groundRay,
40
+ length: 0.5,
41
+ colliderRef: props.colliderRef,
42
+ });
43
+ }
44
+ }, [props.groundRay, props.colliderRef, setGroundRay]);
37
45
  const { scene, animations } = useGLTF(props.url);
38
46
  const { actions, ref: animationRef } = useAnimations(animations);
39
47
  const worldContext = useContext(GaesupWorldContext);
@@ -1,12 +1,11 @@
1
1
  // useSetGroundRay.ts
2
2
  import { useRapier } from "@react-three/rapier";
3
- import { groundRayType } from "../../../controller/type";
4
- import { getRayHit } from "../../../utils";
3
+ import { useRayHit } from "../../../hooks/useRayHit";
5
4
  import { setGroundRayType } from "./type";
6
5
 
7
6
  export function useSetGroundRay() {
8
7
  const { rapier } = useRapier();
9
-
8
+ const getRayHit = useRayHit();
10
9
  const setGroundRay = ({
11
10
  groundRay,
12
11
  length,
@@ -14,7 +13,7 @@ export function useSetGroundRay() {
14
13
  }: setGroundRayType) => {
15
14
  groundRay.length = length;
16
15
  groundRay.rayCast = new rapier.Ray(groundRay.origin, groundRay.dir);
17
- groundRay.hit = getRayHit<groundRayType>({
16
+ groundRay.hit = getRayHit({
18
17
  ray: groundRay,
19
18
  ref: colliderRef,
20
19
  });
@@ -0,0 +1,25 @@
1
+ import { Collider } from "@dimforge/rapier3d-compat";
2
+ import { useRapier } from "@react-three/rapier";
3
+ import { RefObject, useCallback } from "react";
4
+ import { groundRayType } from "../../controller/type";
5
+
6
+ export function useRayHit() {
7
+ const rapier = useRapier();
8
+
9
+ const getRayHit = useCallback(
10
+ ({ ray, ref }: { ray: groundRayType; ref: RefObject<Collider> }) => {
11
+ return rapier.world.castRay(
12
+ ray.rayCast,
13
+ ray.length,
14
+ true,
15
+ undefined,
16
+ undefined,
17
+ ref.current as any,
18
+ undefined
19
+ );
20
+ },
21
+ [rapier]
22
+ );
23
+
24
+ return getRayHit;
25
+ }
@@ -1,16 +1,18 @@
1
+ import { useContext } from "react";
1
2
  import * as THREE from "three";
3
+ import { GaesupWorldContext } from "../../world/context";
2
4
 
3
5
  export function useTeleport() {
4
- // const worldContext = useContext(GaesupWorldContext);
6
+ const worldContext = useContext(GaesupWorldContext);
5
7
 
6
8
  const Teleport = (position: THREE.Vector3) => {
7
- // if (
8
- // worldContext &&
9
- // worldContext?.refs &&
10
- // worldContext?.refs?.rigidBodyRef &&
11
- // worldContext?.refs?.rigidBodyRef?.current
12
- // )
13
- // worldContext.refs.rigidBodyRef.current.setTranslation(position, true);
9
+ if (
10
+ worldContext &&
11
+ worldContext?.refs &&
12
+ worldContext?.refs?.rigidBodyRef &&
13
+ worldContext?.refs?.rigidBodyRef?.current
14
+ )
15
+ worldContext.refs.rigidBodyRef.current.setTranslation(position, true);
14
16
  };
15
17
 
16
18
  return {
@@ -1,5 +1,5 @@
1
- // style.css.ts
2
1
  import { globalStyle, style } from "@vanilla-extract/css";
2
+ import { commonButton } from "../shared.css";
3
3
 
4
4
  export const gamePad = style({
5
5
  display: "grid",
@@ -9,36 +9,26 @@ export const gamePad = style({
9
9
  gridTemplateRows: "repeat(3, 1fr)",
10
10
  });
11
11
 
12
- export const padButton = style({
13
- display: "flex",
14
- justifyContent: "center",
15
- alignItems: "center",
16
- position: "relative",
17
- width: "5rem",
18
- height: "5rem",
19
- borderRadius: "50%",
20
- fontSize: "1rem",
21
- backgroundColor: "rgba(0, 0, 0, 0.5)",
22
- color: "white",
23
- boxShadow: "0 0 0.5rem rgba(0, 0, 0, 0.5)",
24
- cursor: "pointer",
25
- transition: "all 0.3s ease-in",
26
- margin: "0.5rem",
27
- selectors: {
28
- "&:hover": {
29
- boxShadow: "0 0 1rem rgba(0, 0, 0, 0.5)",
30
- },
31
- "&::after": {
32
- content: '""',
33
- position: "absolute",
34
- width: "4rem",
35
- height: "4rem",
36
- borderRadius: "50%",
37
- background: "rgba(0, 0, 0, 0.2)",
38
- zIndex: 100000,
12
+ export const padButton = style([
13
+ commonButton,
14
+ {
15
+ position: "relative",
16
+ fontSize: "1rem",
17
+ margin: "0.5rem",
18
+ borderRadius: "50%",
19
+ selectors: {
20
+ "&::after": {
21
+ content: '""',
22
+ position: "absolute",
23
+ width: "4rem",
24
+ height: "4rem",
25
+ borderRadius: "50%",
26
+ background: "rgba(0, 0, 0, 0.2)",
27
+ zIndex: 100000,
28
+ },
39
29
  },
40
30
  },
41
- });
31
+ ]);
42
32
 
43
33
  export const isClicked = style({
44
34
  background:
@@ -46,6 +36,7 @@ export const isClicked = style({
46
36
  boxShadow: "0 0 1rem rgba(245, 177, 97, 1)",
47
37
  color: "black",
48
38
  transition: "all 0.3s ease-in",
39
+ borderRadius: "50%",
49
40
  selectors: {
50
41
  "&:hover": {
51
42
  boxShadow: "0 0 2rem rgba(245, 177, 97, 1)",
@@ -1,6 +1,4 @@
1
- // MiniMap.tsx
2
1
  import { useCallback, useContext, useState } from "react";
3
-
4
2
  import { GaesupWorldContext } from "../../world/context";
5
3
  import * as S from "./style.css";
6
4
 
@@ -1,12 +1,5 @@
1
- // style.css.ts
2
- import { globalFontFace, keyframes, style } from "@vanilla-extract/css";
3
-
4
- // @font-face 정의
5
- globalFontFace("Open Sans", {
6
- src: 'url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap")',
7
- fontWeight: "300",
8
- fontStyle: "normal",
9
- });
1
+ import { keyframes, style } from "@vanilla-extract/css";
2
+ import { flexCenter, minimapSize } from "../shared.css";
10
3
 
11
4
  // 키프레임 정의
12
5
  const pulseWhite = keyframes({
@@ -25,123 +18,111 @@ const pulseWhite = keyframes({
25
18
  });
26
19
 
27
20
  // 스타일 정의
28
- export const minimap = style({
29
- margin: "1rem",
30
- borderRadius: "50%",
31
- background: "rgba(0, 0, 0, 0.6)",
32
- boxShadow: "0 0 10px rgba(0, 0, 0, 0.5)",
33
- backdropFilter: "blur(1rem)",
34
- WebkitBackdropFilter: "blur(1rem)",
35
- width: "18rem",
36
- height: "18rem",
37
- border: "4px solid rgba(0, 0, 0, 0.5)",
38
- overflow: "hidden",
39
- "@media": {
40
- "screen and (max-width: 1024px)": {
41
- width: "17rem",
42
- height: "17rem",
43
- },
44
- "screen and (max-width: 768px)": {
45
- width: "16rem",
46
- height: "16rem",
47
- },
21
+ export const minimap = style([
22
+ {
23
+ margin: "1rem",
24
+ borderRadius: "50%",
25
+ background: "rgba(0, 0, 0, 0.6)",
26
+ boxShadow: "0 0 10px rgba(0, 0, 0, 0.5)",
27
+ backdropFilter: "blur(1rem)",
28
+ WebkitBackdropFilter: "blur(1rem)",
29
+ border: "4px solid rgba(0, 0, 0, 0.5)",
30
+ overflow: "hidden",
48
31
  },
49
- });
32
+ minimapSize,
33
+ ]);
50
34
 
51
- export const minimapOuter = style({
52
- position: "absolute",
53
- display: "flex",
54
- alignItems: "center",
55
- justifyContent: "center",
56
- textAlign: "center",
57
- width: "18rem",
58
- height: "18rem",
59
- overflow: "hidden",
60
- });
35
+ export const minimapOuter = style([
36
+ flexCenter,
37
+ {
38
+ position: "absolute",
39
+ textAlign: "center",
40
+ overflow: "hidden",
41
+ },
42
+ minimapSize,
43
+ ]);
61
44
 
62
- export const minimapInner = style({
63
- position: "relative",
64
- display: "flex",
65
- top: "50%",
66
- left: "50%",
67
- width: "18rem",
68
- height: "18rem",
69
- transformOrigin: "50% 50%",
70
- borderRadius: "50%",
71
- overflow: "hidden",
72
- "@media": {
73
- "screen and (max-width: 1024px)": {
74
- width: "17rem",
75
- height: "17rem",
76
- },
77
- "screen and (max-width: 768px)": {
78
- width: "16rem",
79
- height: "16rem",
80
- },
45
+ export const minimapInner = style([
46
+ {
47
+ position: "relative",
48
+ display: "flex",
49
+ top: "50%",
50
+ left: "50%",
51
+ transformOrigin: "50% 50%",
52
+ borderRadius: "50%",
53
+ overflow: "hidden",
81
54
  },
82
- });
55
+ minimapSize,
56
+ ]);
83
57
 
84
- export const avatar = style({
85
- position: "absolute",
86
- display: "flex",
87
- alignItems: "center",
88
- justifyContent: "center",
89
- textAlign: "center",
90
- top: "50%",
91
- left: "50%",
92
- transform: "translate(-50%, -50%)",
93
- width: "2rem",
94
- height: "2rem",
95
- borderRadius: "50%",
96
- background: "rgba(5, 222, 250, 1)",
97
- boxShadow: "0 0 10px rgba(5, 222, 250, 1)",
98
- border: "2px solid transparent",
99
- objectFit: "cover",
100
- zIndex: 100,
101
- animation: `${pulseWhite} 2s infinite`,
102
- });
58
+ export const avatar = style([
59
+ {
60
+ position: "absolute",
61
+ display: "flex",
62
+ alignItems: "center",
63
+ justifyContent: "center",
64
+ textAlign: "center",
65
+ top: "50%",
66
+ left: "50%",
67
+ transform: "translate(-50%, -50%)",
68
+ width: "2rem",
69
+ height: "2rem",
70
+ borderRadius: "50%",
71
+ background: "rgba(5, 222, 250, 1)",
72
+ boxShadow: "0 0 10px rgba(5, 222, 250, 1)",
73
+ border: "2px solid transparent",
74
+ objectFit: "cover",
75
+ zIndex: 100,
76
+ animation: `${pulseWhite} 2s infinite`,
77
+ },
78
+ ]);
103
79
 
104
- export const plusMinus = style({
105
- position: "relative",
106
- display: "flex",
107
- justifyContent: "center",
108
- alignItems: "center",
109
- width: "2rem",
110
- height: "2rem",
111
- borderRadius: "50%",
112
- background: "rgba(0, 0, 0, 0.5)",
113
- boxShadow: "0 0 5px rgba(0, 0, 0, 0.5)",
114
- transition: "all 0.5s ease-in",
115
- cursor: "pointer",
116
- border: "2px solid transparent",
117
- ":hover": {
118
- boxShadow: "0 0 10px rgba(0, 0, 0, 0.5)",
80
+ export const plusMinus = style([
81
+ {
82
+ position: "relative",
83
+ display: "flex",
84
+ justifyContent: "center",
85
+ alignItems: "center",
86
+ width: "2rem",
87
+ height: "2rem",
88
+ borderRadius: "50%",
89
+ background: "rgba(0, 0, 0, 0.5)",
90
+ boxShadow: "0 0 5px rgba(0, 0, 0, 0.5)",
91
+ transition: "all 0.5s ease-in",
92
+ cursor: "pointer",
93
+ border: "2px solid transparent",
94
+ selectors: {
95
+ "&:hover": {
96
+ boxShadow: "0 0 10px rgba(0, 0, 0, 0.5)",
97
+ },
98
+ },
119
99
  },
120
- });
100
+ ]);
121
101
 
122
- export const scale = style({
123
- position: "absolute",
124
- width: "13rem",
125
- bottom: "-5rem",
126
- left: "50%",
127
- transform: "translateX(-50%)",
128
- display: "flex",
129
- alignItems: "center",
130
- justifyContent: "space-between",
131
- textAlign: "center",
132
- fontSize: "1.2rem",
133
- color: "white",
134
- textShadow: "0 0 10px black",
135
- padding: "0.5rem",
136
- borderRadius: "0.5rem",
137
- boxShadow: "0 0 10px black",
138
- background: "rgba(0, 0, 0, 0.5)",
139
- zIndex: 3,
140
- WebkitBackdropFilter: "blur(2rem)",
141
- backdropFilter: "blur(2rem)",
142
- fontFamily: '"Open Sans", sans-serif',
143
- fontWeight: 300,
144
- });
102
+ export const scale = style([
103
+ {
104
+ position: "absolute",
105
+ width: "13rem",
106
+ bottom: "-5rem",
107
+ left: "50%",
108
+ transform: "translateX(-50%)",
109
+ display: "flex",
110
+ alignItems: "center",
111
+ justifyContent: "space-between",
112
+ fontSize: "1.2rem",
113
+ color: "white",
114
+ textShadow: "0 0 10px black",
115
+ padding: "0.5rem",
116
+ borderRadius: "0.5rem",
117
+ boxShadow: "0 0 10px black",
118
+ background: "rgba(0, 0, 0, 0.5)",
119
+ zIndex: 3,
120
+ WebkitBackdropFilter: "blur(2rem)",
121
+ backdropFilter: "blur(2rem)",
122
+ fontFamily: '"Open Sans", sans-serif',
123
+ fontWeight: 300,
124
+ },
125
+ ]);
145
126
 
146
127
  export const text = style({
147
128
  position: "relative",
@@ -0,0 +1,44 @@
1
+ import { style } from "@vanilla-extract/css";
2
+
3
+ // 공통 Flex 중앙 정렬 스타일
4
+ export const flexCenter = style({
5
+ display: "flex",
6
+ justifyContent: "center",
7
+ alignItems: "center",
8
+ textAlign: "center",
9
+ });
10
+
11
+ // 공통 버튼 스타일
12
+ export const commonButton = style([
13
+ flexCenter,
14
+ {
15
+ width: "5rem",
16
+ height: "5rem",
17
+ cursor: "pointer",
18
+ transition: "all 0.3s ease-in",
19
+ boxShadow: "0 0 0.5rem rgba(0, 0, 0, 0.5)",
20
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
21
+ color: "white",
22
+ selectors: {
23
+ "&:hover": {
24
+ boxShadow: "0 0 1rem rgba(0, 0, 0, 0.5)",
25
+ },
26
+ },
27
+ },
28
+ ]);
29
+
30
+ // 미니맵 공통 사이즈 및 미디어 쿼리
31
+ export const minimapSize = {
32
+ width: "18rem",
33
+ height: "18rem",
34
+ "@media": {
35
+ "screen and (max-width: 1024px)": {
36
+ width: "17rem",
37
+ height: "17rem",
38
+ },
39
+ "screen and (max-width: 768px)": {
40
+ width: "16rem",
41
+ height: "16rem",
42
+ },
43
+ },
44
+ };
@@ -1,22 +1,18 @@
1
- // JumpPortal.tsx
1
+ // teleport.tsx
2
2
  import { useTeleport } from "../../hooks/useTeleport";
3
3
  import * as S from "./style.css";
4
- import { JumpPortalType } from "./type.ts";
4
+ import { teleportType } from "./type.ts";
5
5
 
6
- export function JumpPortal({
7
- text,
8
- position,
9
- jumpPortalStyle,
10
- }: JumpPortalType) {
6
+ export function teleport({ text, position, teleportStyle }: teleportType) {
11
7
  const { Teleport } = useTeleport();
12
8
 
13
9
  return (
14
10
  <div
15
- className={S.jumpPortal}
11
+ className={S.teleport}
16
12
  onClick={() => {
17
13
  Teleport(position);
18
14
  }}
19
- style={jumpPortalStyle}
15
+ style={teleportStyle}
20
16
  >
21
17
  {text}
22
18
  </div>
@@ -0,0 +1,14 @@
1
+ import { style } from "@vanilla-extract/css";
2
+ import { commonButton } from "../shared.css";
3
+
4
+ export const teleport = style([
5
+ commonButton,
6
+ {
7
+ margin: "1rem",
8
+ fontSize: "0.8rem",
9
+ background: "rgba(0, 0, 0, 0.6)",
10
+ boxShadow: "0 0 5px 0 rgba(0, 0, 0, 0.6)",
11
+ transition: "all 0.2s ease-in",
12
+ borderRadius: "50%",
13
+ },
14
+ ]);
@@ -1,8 +1,8 @@
1
1
  import { CSSProperties } from "react";
2
2
  import * as THREE from "three";
3
3
 
4
- export type JumpPortalType = {
4
+ export type teleportType = {
5
5
  text?: string;
6
6
  position: THREE.Vector3;
7
- jumpPortalStyle?: CSSProperties;
7
+ teleportStyle?: CSSProperties;
8
8
  };
@@ -1,16 +1,16 @@
1
+ import { Collider } from "@dimforge/rapier3d-compat";
1
2
  import { useRapier } from "@react-three/rapier";
2
- import { MutableRefObject } from "react";
3
- import { rayType } from "../controller/type";
3
+ import { RefObject } from "react";
4
+ import { groundRayType } from "../controller/type";
4
5
 
5
- // @ts-ignore
6
- export const getRayHit = <T extends rayType>({
6
+ export const getRayHit = ({
7
7
  ray,
8
8
  ref,
9
9
  }: {
10
- ray: any;
11
- ref: MutableRefObject<any>;
10
+ ray: groundRayType;
11
+ ref: RefObject<Collider>;
12
12
  }) => {
13
- const { world } = useRapier() as any;
13
+ const { world } = useRapier();
14
14
  return world.castRay(
15
15
  ray.rayCast,
16
16
  ray.length,
@@ -40,7 +40,7 @@ export type keyControlType = {
40
40
  export type portalType = {
41
41
  text?: string;
42
42
  position: THREE.Vector3;
43
- jumpPortalStlye?: CSSProperties;
43
+ teleportStlye?: CSSProperties;
44
44
  };
45
45
 
46
46
  export type portalsType = portalType[];
package/dist/index.ts CHANGED
@@ -7,9 +7,9 @@ export { GaesupController } from "./gaesup/controller";
7
7
  export { GaeSupProps } from "./gaesup/gaesupProps";
8
8
  export { Clicker } from "./gaesup/tools/clicker";
9
9
  export { GamePad } from "./gaesup/tools/gamepad";
10
- export { JumpPortal } from "./gaesup/tools/jumpPortal";
11
10
  export { MiniMap } from "./gaesup/tools/minimap";
12
11
  export { Rideable } from "./gaesup/tools/rideable";
12
+ export { teleport } from "./gaesup/tools/teleport";
13
13
  export { InnerHtml } from "./gaesup/utils/innerHtml";
14
14
  export { Elr, Qt, V3, V30, V31 } from "./gaesup/utils/vector";
15
15
  export { GaesupWorld } from "./gaesup/world";
package/index.ts CHANGED
@@ -5,9 +5,6 @@ export {
5
5
  GaesupController,
6
6
  GaesupWorld,
7
7
  GamePad,
8
- JoyStick,
9
- JumpPortal,
10
- KeyBoardToolTip,
11
8
  MiniMap,
12
9
  PassiveAirplane,
13
10
  PassiveCharacter,
@@ -17,6 +14,7 @@ export {
17
14
  V3,
18
15
  V30,
19
16
  V31,
17
+ teleport,
20
18
  useClicker,
21
19
  useGaesupAnimation,
22
20
  useGaesupController,
package/output.md ADDED
@@ -0,0 +1,327 @@
1
+ # 코드 추출 결과
2
+
3
+ ## CSS TypeScript Files (.css.ts)
4
+
5
+ ### gaesup/tools/gamepad/style.css.ts
6
+
7
+ ```typescript
8
+ // style.css.ts
9
+ import { globalStyle, style } from "@vanilla-extract/css";
10
+
11
+ export const gamePad = style({
12
+ display: "grid",
13
+ alignItems: "center",
14
+ justifyContent: "center",
15
+ gridTemplateColumns: "repeat(3, 1fr)",
16
+ gridTemplateRows: "repeat(3, 1fr)",
17
+ });
18
+
19
+ export const padButton = style({
20
+ display: "flex",
21
+ justifyContent: "center",
22
+ alignItems: "center",
23
+ position: "relative",
24
+ width: "5rem",
25
+ height: "5rem",
26
+ borderRadius: "50%",
27
+ fontSize: "1rem",
28
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
29
+ color: "white",
30
+ boxShadow: "0 0 0.5rem rgba(0, 0, 0, 0.5)",
31
+ cursor: "pointer",
32
+ transition: "all 0.3s ease-in",
33
+ margin: "0.5rem",
34
+ selectors: {
35
+ "&:hover": {
36
+ boxShadow: "0 0 1rem rgba(0, 0, 0, 0.5)",
37
+ },
38
+ "&::after": {
39
+ content: '""',
40
+ position: "absolute",
41
+ width: "4rem",
42
+ height: "4rem",
43
+ borderRadius: "50%",
44
+ background: "rgba(0, 0, 0, 0.2)",
45
+ zIndex: 100000,
46
+ },
47
+ },
48
+ });
49
+
50
+ export const isClicked = style({
51
+ background:
52
+ "radial-gradient(circle at center, rgba(245, 177, 97, 1) 0.4%, rgba(236, 54, 110, 1) 100.2%)",
53
+ boxShadow: "0 0 1rem rgba(245, 177, 97, 1)",
54
+ color: "black",
55
+ transition: "all 0.3s ease-in",
56
+ selectors: {
57
+ "&:hover": {
58
+ boxShadow: "0 0 2rem rgba(245, 177, 97, 1)",
59
+ },
60
+ },
61
+ });
62
+
63
+ // 사용자 선택 방지 글로벌 스타일
64
+ globalStyle(`${gamePad} *`, {
65
+ WebkitTouchCallout: "none",
66
+ WebkitUserSelect: "none",
67
+ MozUserSelect: "none",
68
+ msUserSelect: "none",
69
+ userSelect: "none",
70
+ });
71
+
72
+ ```
73
+
74
+ ### gaesup/tools/teleport/style.css.ts
75
+
76
+ ```typescript
77
+ import { style } from "@vanilla-extract/css";
78
+
79
+ export const teleport = style({
80
+ display: "flex",
81
+ justifyContent: "center",
82
+ alignItems: "center",
83
+ textAlign: "center",
84
+ margin: "1rem",
85
+ fontSize: "0.8rem",
86
+ borderRadius: "50%",
87
+ width: "5rem",
88
+ height: "5rem",
89
+ color: "white",
90
+ background: "rgba(0, 0, 0, 0.6)",
91
+ boxShadow: "0 0 5px 0 rgba(0, 0, 0, 0.6)",
92
+ transition: "all 0.2s ease-in",
93
+ cursor: "pointer",
94
+ });
95
+
96
+ ```
97
+
98
+ ### gaesup/tools/minimap/style.css.ts
99
+
100
+ ```typescript
101
+ // style.css.ts
102
+ import { globalFontFace, keyframes, style } from "@vanilla-extract/css";
103
+
104
+ // @font-face 정의
105
+ globalFontFace("Open Sans", {
106
+ src: 'url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap")',
107
+ fontWeight: "300",
108
+ fontStyle: "normal",
109
+ });
110
+
111
+ // 키프레임 정의
112
+ const pulseWhite = keyframes({
113
+ "0%": {
114
+ boxShadow: "0 0 0 0 rgba(255, 255, 255, 0.7)",
115
+ opacity: 1,
116
+ },
117
+ "70%": {
118
+ boxShadow: "0 0 0 10px rgba(255, 255, 255, 0)",
119
+ opacity: 0.7,
120
+ },
121
+ "100%": {
122
+ boxShadow: "0 0 0 0 rgba(255, 255, 255, 0)",
123
+ opacity: 1,
124
+ },
125
+ });
126
+
127
+ // 스타일 정의
128
+ export const minimap = style({
129
+ margin: "1rem",
130
+ borderRadius: "50%",
131
+ background: "rgba(0, 0, 0, 0.6)",
132
+ boxShadow: "0 0 10px rgba(0, 0, 0, 0.5)",
133
+ backdropFilter: "blur(1rem)",
134
+ WebkitBackdropFilter: "blur(1rem)",
135
+ width: "18rem",
136
+ height: "18rem",
137
+ border: "4px solid rgba(0, 0, 0, 0.5)",
138
+ overflow: "hidden",
139
+ "@media": {
140
+ "screen and (max-width: 1024px)": {
141
+ width: "17rem",
142
+ height: "17rem",
143
+ },
144
+ "screen and (max-width: 768px)": {
145
+ width: "16rem",
146
+ height: "16rem",
147
+ },
148
+ },
149
+ });
150
+
151
+ export const minimapOuter = style({
152
+ position: "absolute",
153
+ display: "flex",
154
+ alignItems: "center",
155
+ justifyContent: "center",
156
+ textAlign: "center",
157
+ width: "18rem",
158
+ height: "18rem",
159
+ overflow: "hidden",
160
+ });
161
+
162
+ export const minimapInner = style({
163
+ position: "relative",
164
+ display: "flex",
165
+ top: "50%",
166
+ left: "50%",
167
+ width: "18rem",
168
+ height: "18rem",
169
+ transformOrigin: "50% 50%",
170
+ borderRadius: "50%",
171
+ overflow: "hidden",
172
+ "@media": {
173
+ "screen and (max-width: 1024px)": {
174
+ width: "17rem",
175
+ height: "17rem",
176
+ },
177
+ "screen and (max-width: 768px)": {
178
+ width: "16rem",
179
+ height: "16rem",
180
+ },
181
+ },
182
+ });
183
+
184
+ export const avatar = style({
185
+ position: "absolute",
186
+ display: "flex",
187
+ alignItems: "center",
188
+ justifyContent: "center",
189
+ textAlign: "center",
190
+ top: "50%",
191
+ left: "50%",
192
+ transform: "translate(-50%, -50%)",
193
+ width: "2rem",
194
+ height: "2rem",
195
+ borderRadius: "50%",
196
+ background: "rgba(5, 222, 250, 1)",
197
+ boxShadow: "0 0 10px rgba(5, 222, 250, 1)",
198
+ border: "2px solid transparent",
199
+ objectFit: "cover",
200
+ zIndex: 100,
201
+ animation: `${pulseWhite} 2s infinite`,
202
+ });
203
+
204
+ export const plusMinus = style({
205
+ position: "relative",
206
+ display: "flex",
207
+ justifyContent: "center",
208
+ alignItems: "center",
209
+ width: "2rem",
210
+ height: "2rem",
211
+ borderRadius: "50%",
212
+ background: "rgba(0, 0, 0, 0.5)",
213
+ boxShadow: "0 0 5px rgba(0, 0, 0, 0.5)",
214
+ transition: "all 0.5s ease-in",
215
+ cursor: "pointer",
216
+ border: "2px solid transparent",
217
+ ":hover": {
218
+ boxShadow: "0 0 10px rgba(0, 0, 0, 0.5)",
219
+ },
220
+ });
221
+
222
+ export const scale = style({
223
+ position: "absolute",
224
+ width: "13rem",
225
+ bottom: "-5rem",
226
+ left: "50%",
227
+ transform: "translateX(-50%)",
228
+ display: "flex",
229
+ alignItems: "center",
230
+ justifyContent: "space-between",
231
+ textAlign: "center",
232
+ fontSize: "1.2rem",
233
+ color: "white",
234
+ textShadow: "0 0 10px black",
235
+ padding: "0.5rem",
236
+ borderRadius: "0.5rem",
237
+ boxShadow: "0 0 10px black",
238
+ background: "rgba(0, 0, 0, 0.5)",
239
+ zIndex: 3,
240
+ WebkitBackdropFilter: "blur(2rem)",
241
+ backdropFilter: "blur(2rem)",
242
+ fontFamily: '"Open Sans", sans-serif',
243
+ fontWeight: 300,
244
+ });
245
+
246
+ export const text = style({
247
+ position: "relative",
248
+ fontSize: "1rem",
249
+ color: "black",
250
+ padding: "0.5rem",
251
+ borderRadius: "0.5rem",
252
+ background: "rgba(255, 255, 255, 0.5)",
253
+ boxShadow: "0 0 10px rgba(255, 255, 255, 0.5)",
254
+ zIndex: 3,
255
+ });
256
+
257
+ export const minimapObject = style({
258
+ position: "absolute",
259
+ display: "flex",
260
+ alignItems: "center",
261
+ justifyContent: "center",
262
+ textAlign: "center",
263
+ borderRadius: "2px",
264
+ background: "rgba(0, 0, 0, 0.3)",
265
+ });
266
+
267
+ export const imageObject = style({
268
+ position: "absolute",
269
+ display: "flex",
270
+ alignItems: "center",
271
+ justifyContent: "center",
272
+ textAlign: "center",
273
+ background: `
274
+ linear-gradient(to bottom, transparent 95%, rgba(0, 0, 0, 0.2) 20%) 0 0 / 100% 40px repeat-y,
275
+ linear-gradient(to right, transparent 38px, rgba(0, 0, 0, 0.2) 38px) 0 0 / 40px 100% repeat-x transparent
276
+ `,
277
+ });
278
+
279
+ export const textObject = style({
280
+ position: "absolute",
281
+ display: "flex",
282
+ alignItems: "center",
283
+ justifyContent: "center",
284
+ textAlign: "center",
285
+ });
286
+
287
+ const directionBase = style({
288
+ position: "absolute",
289
+ color: "white",
290
+ fontSize: "1.5rem",
291
+ zIndex: 2000,
292
+ });
293
+
294
+ export const east = style([
295
+ directionBase,
296
+ {
297
+ top: "50%",
298
+ right: 0,
299
+ },
300
+ ]);
301
+
302
+ export const west = style([
303
+ directionBase,
304
+ {
305
+ top: "50%",
306
+ left: 0,
307
+ },
308
+ ]);
309
+
310
+ export const south = style([
311
+ directionBase,
312
+ {
313
+ top: 0,
314
+ left: "50%",
315
+ },
316
+ ]);
317
+
318
+ export const north = style([
319
+ directionBase,
320
+ {
321
+ bottom: 0,
322
+ left: "50%",
323
+ },
324
+ ]);
325
+
326
+ ```
327
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaesup-world",
3
- "version": "0.9.58",
3
+ "version": "0.9.60",
4
4
  "type": "module",
5
5
  "main": "dist/index.ts",
6
6
  "types": "dist/index.d.ts",
@@ -15,7 +15,8 @@
15
15
  "prepare": "yarn clean && tsc -p tsconfig.build.json && yarn copy-files",
16
16
  "predeploy": "yarn build",
17
17
  "deploy": "gh-pages -d dist",
18
- "test": "jest"
18
+ "test": "jest",
19
+ "publish": "yarn prepare && yarn npm publish --access public"
19
20
  },
20
21
  "dependencies": {
21
22
  "@dimforge/rapier3d": "^0.14.0",
package/yarnrc.yml CHANGED
@@ -1 +1 @@
1
- nodeLinker: node-modules
1
+ nodeLinker: pnp
@@ -1,18 +0,0 @@
1
- import { style } from "@vanilla-extract/css";
2
-
3
- export const jumpPortal = style({
4
- display: "flex",
5
- justifyContent: "center",
6
- alignItems: "center",
7
- textAlign: "center",
8
- margin: "1rem",
9
- fontSize: "0.8rem",
10
- borderRadius: "50%",
11
- width: "5rem",
12
- height: "5rem",
13
- color: "white",
14
- background: "rgba(0, 0, 0, 0.6)",
15
- boxShadow: "0 0 5px 0 rgba(0, 0, 0, 0.6)",
16
- transition: "all 0.2s ease-in",
17
- cursor: "pointer",
18
- });