Compare commits

...
6 Commits
Author SHA1 Message Date
胡鑫 6478747fb6 fix: TMP textfield typeing 2025-04-01 11:39:01 +08:00
胡鑫 9176fdea5d fix: dep and puer 2025-04-01 11:14:24 +08:00
hypercross 3874f4e801 feat: include the unity prefab generator 2025-03-30 14:19:17 +08:00
hypercross 71b5d545bb feat: loader script & typecheck 2025-03-30 14:16:06 +08:00
hypercross 3796714238 fix: details 2025-03-30 12:49:39 +08:00
hypercross ea70047996 fix: lib 2025-03-30 12:46:56 +08:00
10 changed files with 559 additions and 6 deletions
+1 -1
View File
@@ -1,2 +1,2 @@
/node_modules/
/dist/
/Gen
+305 -1
View File
@@ -10,7 +10,8 @@
"license": "ISC",
"devDependencies": {
"@rspack/cli": "^1.3.0",
"@rspack/core": "^1.3.0"
"@rspack/core": "^1.3.0",
"@swc/register": "^0.1.10"
}
},
"node_modules/@discoveryjs/json-ext": {
@@ -387,6 +388,264 @@
"node": ">=16.0.0"
}
},
"node_modules/@swc/core": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.13.tgz",
"integrity": "sha512-9BXdYz12Wl0zWmZ80PvtjBWeg2ncwJ9L5WJzjhN6yUTZWEV/AwAdVdJnIEp4pro3WyKmAaMxcVOSbhuuOZco5g==",
"dev": true,
"hasInstallScript": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@swc/counter": "^0.1.3",
"@swc/types": "^0.1.19"
},
"engines": {
"node": ">=10"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/swc"
},
"optionalDependencies": {
"@swc/core-darwin-arm64": "1.11.13",
"@swc/core-darwin-x64": "1.11.13",
"@swc/core-linux-arm-gnueabihf": "1.11.13",
"@swc/core-linux-arm64-gnu": "1.11.13",
"@swc/core-linux-arm64-musl": "1.11.13",
"@swc/core-linux-x64-gnu": "1.11.13",
"@swc/core-linux-x64-musl": "1.11.13",
"@swc/core-win32-arm64-msvc": "1.11.13",
"@swc/core-win32-ia32-msvc": "1.11.13",
"@swc/core-win32-x64-msvc": "1.11.13"
},
"peerDependencies": {
"@swc/helpers": "*"
},
"peerDependenciesMeta": {
"@swc/helpers": {
"optional": true
}
}
},
"node_modules/@swc/core-darwin-arm64": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.13.tgz",
"integrity": "sha512-loSERhLaQ9XDS+5Kdx8cLe2tM1G0HLit8MfehipAcsdctpo79zrRlkW34elOf3tQoVPKUItV0b/rTuhjj8NtHg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"darwin"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-darwin-x64": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.13.tgz",
"integrity": "sha512-uSA4UwgsDCIysUPfPS8OrQTH2h9spO7IYFd+1NB6dJlVGUuR6jLKuMBOP1IeLeax4cGHayvkcwSJ3OvxHwgcZQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"darwin"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-arm-gnueabihf": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.13.tgz",
"integrity": "sha512-boVtyJzS8g30iQfe8Q46W5QE/cmhKRln/7NMz/5sBP/am2Lce9NL0d05NnFwEWJp1e2AMGHFOdRr3Xg1cDiPKw==",
"cpu": [
"arm"
],
"dev": true,
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.13.tgz",
"integrity": "sha512-+IK0jZ84zHUaKtwpV+T+wT0qIUBnK9v2xXD03vARubKF+eUqCsIvcVHXmLpFuap62dClMrhCiwW10X3RbXNlHw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-arm64-musl": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.13.tgz",
"integrity": "sha512-+ukuB8RHD5BHPCUjQwuLP98z+VRfu+NkKQVBcLJGgp0/+w7y0IkaxLY/aKmrAS5ofCNEGqKL+AOVyRpX1aw+XA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-x64-gnu": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.13.tgz",
"integrity": "sha512-q9H3WI3U3dfJ34tdv60zc8oTuWvSd5fOxytyAO9Pc5M82Hic3jjWaf2xBekUg07ubnMZpyfnv+MlD+EbUI3Llw==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-linux-x64-musl": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.13.tgz",
"integrity": "sha512-9aaZnnq2pLdTbAzTSzy/q8dr7Woy3aYIcQISmw1+Q2/xHJg5y80ZzbWSWKYca/hKonDMjIbGR6dp299I5J0aeA==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"linux"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-win32-arm64-msvc": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.13.tgz",
"integrity": "sha512-n3QZmDewkHANcoHvtwvA6yJbmS4XJf0MBMmwLZoKDZ2dOnC9D/jHiXw7JOohEuzYcpLoL5tgbqmjxa3XNo9Oow==",
"cpu": [
"arm64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-win32-ia32-msvc": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.13.tgz",
"integrity": "sha512-wM+Nt4lc6YSJFthCx3W2dz0EwFNf++j0/2TQ0Js9QLJuIxUQAgukhNDVCDdq8TNcT0zuA399ALYbvj5lfIqG6g==",
"cpu": [
"ia32"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/core-win32-x64-msvc": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.13.tgz",
"integrity": "sha512-+X5/uW3s1L5gK7wAo0E27YaAoidJDo51dnfKSfU7gF3mlEUuWH8H1bAy5OTt2mU4eXtfsdUMEVXSwhDlLtQkuA==",
"cpu": [
"x64"
],
"dev": true,
"license": "Apache-2.0 AND MIT",
"optional": true,
"os": [
"win32"
],
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@swc/counter": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true
},
"node_modules/@swc/register": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/@swc/register/-/register-0.1.10.tgz",
"integrity": "sha512-6STwH/q4dc3pitXLVkV7sP0Hiy+zBsU2wOF1aXpXR95pnH3RYHKIsDC+gvesfyB7jxNT9OOZgcqOp9RPxVTx9A==",
"deprecated": "Use @swc-node/register instead",
"dev": true,
"license": "(Apache-2.0 OR MIT)",
"dependencies": {
"lodash.clonedeep": "^4.5.0",
"pirates": "^4.0.1",
"source-map-support": "^0.5.13"
},
"bin": {
"swc-node": "bin/swc-node"
},
"peerDependencies": {
"@swc/core": "^1.0.46"
}
},
"node_modules/@swc/types": {
"version": "0.1.20",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.20.tgz",
"integrity": "sha512-/rlIpxwKrhz4BIplXf6nsEHtqlhzuNN34/k3kMAXH4/lvVoA3cdq+60aqVNnyvw2uITEaCi0WV3pxBe4dQqoXQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@swc/counter": "^0.1.3"
}
},
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -810,6 +1069,13 @@
"node": ">=8"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/bundle-name": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
@@ -1965,6 +2231,13 @@
"shell-quote": "^1.8.1"
}
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
"dev": true,
"license": "MIT"
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -2277,6 +2550,16 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pirates": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
"integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -2771,6 +3054,27 @@
"websocket-driver": "^0.7.4"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/spdy": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+3 -2
View File
@@ -4,13 +4,14 @@
"main": "index.js",
"scripts": {
"build": "rspack build",
"dev": "rspack dev"
"dev": "rspack --watch"
},
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@rspack/cli": "^1.3.0",
"@rspack/core": "^1.3.0"
"@rspack/core": "^1.3.0",
"@swc/register": "^0.1.10"
}
}
+2
View File
@@ -12,6 +12,8 @@ export default defineConfig({
unityengine: "CS.UnityEngine",
"unityengine/ui": "CS.UnityEngine.UI",
"system": "CS.System",
"tmpro": "CS.TMPro",
puerts: "puer",
},
output: {
path: resolve(__dirname, "Gen/Resources"),
+11 -1
View File
@@ -1 +1,11 @@
console.log("blah");
import { Debug } from "unityengine";
import { DefDatabase } from "hono/verse";
import { $typeof } from "puerts";
import { ItemDef } from "hono/demo3";
// what
async function main() {
Debug.Log(DefDatabase.GetByName("wood", $typeof(ItemDef)));
}
main();
+53
View File
@@ -0,0 +1,53 @@
import { $typeof } from "puerts";
import { Awaitable, GameObject, Resources } from "unityengine";
export async function loadPrefab<P extends keyof UnityPrefabs>(path: P) {
return await loadResource(path) as GameObject & { PREFAB_KEY: P };
}
export async function loadResource(path: string) {
const req = Resources.LoadAsync(path);
await asPromise(req);
return req.asset;
}
export function asPromise(awaiter: { GetAwaiter(): Awaitable.Awaiter }) {
return new Promise<void>((resolve) => {
awaiter.GetAwaiter().OnCompleted(resolve);
});
}
export type Constructor<T> = {
new(...args: any[]): T;
};
export type PrefabKeys = Exclude<keyof UnityPrefabs, number | symbol>;
export type PrefabChildKeys<K extends PrefabKeys> = Exclude<
keyof UnityPrefabs[K],
number | symbol
>;
export type PrefabComponentKeys<
K extends PrefabKeys,
C extends PrefabChildKeys<K>,
> = Exclude<keyof UnityPrefabs[K][C], string | symbol>;
export type PrefabComponent<
K extends PrefabKeys,
C extends PrefabChildKeys<K>,
CK extends PrefabComponentKeys<K, C>,
> = UnityPrefabs[K][C][CK];
export function getPrefabChild<
P extends PrefabKeys,
C extends PrefabChildKeys<P>,
>(p: GameObject & { PREFAB_KEY: P }, c: C) {
return c === "" ? p : p.transform.Find(c).gameObject as GameObject & {
PREFAB_KEY: P;
CHILD_KEY: C;
};
}
export function getPrefabComponent<
P extends PrefabKeys,
C extends PrefabChildKeys<P>,
B extends PrefabComponent<P, C, PrefabComponentKeys<P, C>>,
>(
p: GameObject & { PREFAB_KEY: P },
c: C,
b: Constructor<B>,
) {
const go = c === "" ? p : p.transform.Find(c).gameObject;
return go.GetComponent($typeof(b)) as B;
}
+8
View File
@@ -7,3 +7,11 @@ declare module "unityengine/ui" {
declare module "system" {
export = CS.System;
}
declare module "tmpro" {
export = CS.TMPro;
}
declare module "tmpro" {
interface TMP_Text {
text: string;
}
}
+47
View File
@@ -0,0 +1,47 @@
declare enum __Puerts_CSharpEnum { }
declare namespace puer {
function $ref<T>(x?: T): CS.$Ref<T>;
function $unref<T>(x: CS.$Ref<T>): T;
function $set<T>(x: CS.$Ref<T>, val: T): void;
function $promise<T>(x: CS.$Task<T>): Promise<T>;
function $generic<T extends new (...args: any[]) => any>(
genericType: T,
...genericArguments:
(typeof __Puerts_CSharpEnum | (new (...args: any[]) => any))[]
): T;
function $genericMethod(
genericType: new (...args: any[]) => any,
methodName: string,
...genericArguments:
(typeof __Puerts_CSharpEnum | (new (...args: any[]) => any))[]
): (...args: any[]) => any;
function $typeof(x: new (...args: any[]) => any): CS.System.Type;
function $extension(c: Function, e: Function): void;
function on(eventType: string, listener: Function, prepend?: boolean): void;
function off(eventType: string, listener: Function): void;
function emit(eventType: string, ...args: any[]): boolean;
function loadFile(name: string): { content: string; debugpath: string };
function evalScript(name: string): void;
function require(name: string): any;
}
import puerts = puer;
declare module "puerts" {
export = puerts;
}
+3 -1
View File
@@ -10,7 +10,9 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"lib": [
"ES2020"
], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "libReplacement": true, /* Enable lib replacement. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
@@ -0,0 +1,126 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace PuertsConfigs.Editor
{
public class PrefabStructureGenerator : EditorWindow
{
[MenuItem("Tools/Generate Prefab Structure Definition")]
public static void GeneratePrefabStructureDefinition()
{
StringBuilder tsDefinition = new StringBuilder();
tsDefinition.AppendLine("// Auto-generated by PrefabStructureGenerator");
tsDefinition.AppendLine("declare type UnityPrefabs = {");
// 查找所有Resources文件夹
string[] resourcesDirs = Directory.GetDirectories(Application.dataPath, "Resources", SearchOption.AllDirectories);
Dictionary<string, Dictionary<string, List<string>>> allPrefabs = new Dictionary<string, Dictionary<string, List<string>>>();
foreach (string resourcesDir in resourcesDirs)
{
// 获取Resources文件夹下的所有Prefab
string relativePath = resourcesDir.Replace(Application.dataPath, "Assets");
string[] prefabPaths = Directory.GetFiles(relativePath, "*.prefab", SearchOption.AllDirectories);
foreach (string prefabPath in prefabPaths)
{
// 获取Prefab的相对Resources路径(不带扩展名)
string resourcesRelativePath = prefabPath
.Replace(relativePath + Path.DirectorySeparatorChar, "")
.Replace(".prefab", "");
// 加载Prefab
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (prefab == null) continue;
// 记录Prefab结构
Dictionary<string, List<string>> prefabStructure = new Dictionary<string, List<string>>();
RecordGameObjectComponents(prefab, "", prefabStructure);
allPrefabs[resourcesRelativePath] = prefabStructure;
}
}
// 生成TypeScript定义
foreach (var kvp in allPrefabs)
{
tsDefinition.AppendLine($" \"{kvp.Key}\": {{");
foreach (var componentKvp in kvp.Value)
{
string path = componentKvp.Key;
List<string> components = componentKvp.Value;
if (string.IsNullOrEmpty(path))
{
tsDefinition.Append(" \"\": ");
}
else
{
tsDefinition.Append($" \"{path}\": ");
}
tsDefinition.Append("[");
for (int i = 0; i < components.Count; i++)
{
if (i > 0) tsDefinition.Append(", ");
tsDefinition.Append(components[i]);
}
tsDefinition.AppendLine("],");
}
tsDefinition.AppendLine(" },");
}
tsDefinition.AppendLine("}");
// 确保输出目录存在
string outputDir = Path.Combine(Application.dataPath, "Gen", "Prefabs");
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
// 写入文件
string outputPath = Path.Combine(outputDir, "index.d.ts");
File.WriteAllText(outputPath, tsDefinition.ToString());
AssetDatabase.Refresh();
Debug.Log($"Prefab structure definition generated at: {outputPath}");
}
private static void RecordGameObjectComponents(GameObject go, string currentPath, Dictionary<string, List<string>> structure)
{
// 记录当前GameObject的组件
Component[] components = go.GetComponents<Component>();
List<string> componentTypes = new List<string>();
foreach (Component component in components)
{
if (component == null) continue;
string typeName = $"CS.{component.GetType().FullName}";
componentTypes.Add(typeName);
}
if (componentTypes.Count > 0)
{
structure[currentPath] = componentTypes;
}
// 递归处理子对象
for (int i = 0; i < go.transform.childCount; i++)
{
Transform child = go.transform.GetChild(i);
string childPath = string.IsNullOrEmpty(currentPath)
? child.name
: $"{currentPath}/{child.name}";
RecordGameObjectComponents(child.gameObject, childPath, structure);
}
}
}
}