mirror of
https://github.com/moeru-ai/airi.git
synced 2026-07-10 00:08:33 +00:00
feat(stage-tamagotchi-godot): G1.3 default visual baseline (#1904)
Some checks failed
CI / Check Provenance (push) Has been cancelled
Update Nix pnpmDeps Hash / update (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Build Test (stage-tamagotchi) (push) Has been cancelled
CI / Build Test (stage-tamagotchi-godot) (push) Has been cancelled
CI / Build Test (stage-web) (push) Has been cancelled
CI / Build Test (ui-loading-screens) (push) Has been cancelled
CI / Build Test (ui-transitions) (push) Has been cancelled
CI / Unit Test (push) Has been cancelled
CI / Type Check (push) Has been cancelled
Cloudflare Workers / Deploy - stage-web (push) Has been cancelled
Some checks failed
CI / Check Provenance (push) Has been cancelled
Update Nix pnpmDeps Hash / update (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Build Test (stage-tamagotchi) (push) Has been cancelled
CI / Build Test (stage-tamagotchi-godot) (push) Has been cancelled
CI / Build Test (stage-web) (push) Has been cancelled
CI / Build Test (ui-loading-screens) (push) Has been cancelled
CI / Build Test (ui-transitions) (push) Has been cancelled
CI / Unit Test (push) Has been cancelled
CI / Type Check (push) Has been cancelled
Cloudflare Workers / Deploy - stage-web (push) Has been cancelled
## Summary Add the G1.3 default visual baseline for `stage-tamagotchi-godot`. This moves the Godot stage from a model-loading/runtime skeleton toward a default presentation stage: fixed sky environment, visual grid ground, centre marker, fixed lighting rig, camera ground constraint, and focused material/rendering verification. ## Changes - Add a fixed runtime visual preset for the Godot stage - WorldEnvironment with the existing stage-ui-three HDRI skybox - visual-only grid ground at world `Y=0` - centre `T` marker at the world origin - fixed directional light rig replacing the old single `OmniLight3D` - Reuse the existing three-stage HDRI asset - resolve `packages/stage-ui-three/src/components/Environment/assets/sky_linekotsi_23_HDRI.hdr` from a workspace checkout - do not copy or move the asset into Godot `assets/` - keep release packaging for the shared HDRI as a follow-up - Add camera ground constraint in view-state rules - clamp camera position `Y` during view-state normalisation / commit - applies uniformly to local input, settings-driven patches, and future remote/agent patches - Patch vendored Godot MToon shader behaviour - disable implicit WorldEnvironment ambient light for MToon materials - use Godot alpha scissor / alpha-to-coverage path for cutout MToon variants - document the local vendor patch and removal conditions in `docs/vendor-patches.md` - Improve Godot rendering defaults - enable 3D MSAA - render 3D at 2x scale to avoid low-DPI/viewport scaling aliasing - Add verification harnesses - C# engine-local checks for camera ground constraint and HDRI asset resolution - Godot material rendering check scene for AvatarSample A/B material import coverage - Clean stage root presentation - remove the old on-screen runtime status label - keep Electron bridge and scene/view runtime wiring intact ## Notes The HDRI path resolution is intentionally workspace-only in this PR. Release packaging for sharing the three-stage HDRI with the exported Godot sidecar remains a follow-up. The MToon shader changes are deliberate vendor patches, recorded in `docs/vendor-patches.md`, because `ambient_light_disabled`, `alpha_to_coverage`, and alpha scissor behaviour are shader-level changes rather than runtime material parameters. The material rendering check validates imported material structure, not visual golden output. --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
f2897f7663
commit
cb5c0783e7
20 changed files with 1114 additions and 83 deletions
3
engines/stage-tamagotchi-godot/.gitignore
vendored
3
engines/stage-tamagotchi-godot/.gitignore
vendored
|
|
@ -6,6 +6,9 @@
|
|||
bin/
|
||||
obj/
|
||||
|
||||
# Godot can scan verification test sources during project imports; these are not stage resources.
|
||||
tests/**/*.uid
|
||||
|
||||
# Developer-provided local VRM fixtures for editor preview scenes.
|
||||
assets/fixtures/vrm/*
|
||||
!assets/fixtures/vrm/.gitkeep
|
||||
|
|
|
|||
|
|
@ -139,6 +139,40 @@ Runtime import details live in [`docs/vrm-runtime-import.md`](docs/vrm-runtime-i
|
|||
Vendored add-on local patches and generated metadata differences are tracked in
|
||||
[`docs/vendor-patches.md`](docs/vendor-patches.md).
|
||||
|
||||
## Default Stage Visuals
|
||||
|
||||
G1.3 installs a fixed default presentation preset at runtime. It includes a sky
|
||||
environment, a large world-anchored grid ground at `Y=0`, a center `T` marker at
|
||||
the world origin, and a fixed directional light rig.
|
||||
|
||||
The sky environment reuses the existing stage-ui-three HDRI at
|
||||
`packages/stage-ui-three/src/components/Environment/assets/sky_linekotsi_23_HDRI.hdr`
|
||||
when the Godot stage runs from a workspace checkout. The HDRI is not copied into
|
||||
Godot `assets/`, and the release packaging path for this shared asset remains a
|
||||
separate follow-up.
|
||||
|
||||
The grid ground is visual-only. It does not move the avatar root away from
|
||||
`(0, 0, 0)`, and its shader fades distant grid lines into the horizon color
|
||||
without enabling volumetric fog.
|
||||
|
||||
## Material Rendering Check
|
||||
|
||||
G1.3 includes a focused runtime material verification scene for the committed
|
||||
AvatarSample A/B fixtures:
|
||||
|
||||
```powershell
|
||||
& $env:GODOT4 --headless --path . `
|
||||
--quit-after 5 `
|
||||
--log-file material-check.log `
|
||||
tests/material-rendering-check/materialRenderingCheck.tscn
|
||||
```
|
||||
|
||||
This check imports both samples through `VrmRuntimeImporter.gd` and verifies the
|
||||
runtime material surface covers MToon, alpha/cutout, transparent materials,
|
||||
outline passes, and mesh shadow casters. The current A/B fixtures do not contain
|
||||
unlit materials, so this check reports `unlit = 0` and does not treat that as a
|
||||
failure.
|
||||
|
||||
## Live Debugging From The Godot Editor
|
||||
|
||||
Use this path when Electron is the real host and the model is selected from the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
render_mode skip_vertex_transform;
|
||||
//render_mode specular_disabled,ambient_light_disabled;
|
||||
render_mode ambient_light_disabled;
|
||||
// Keep specular active while validating whether environment ambient/radiance is the washout source.
|
||||
// render_mode specular_disabled;
|
||||
|
||||
// VARIANTS:
|
||||
// DEFAULT_MODE:
|
||||
|
|
@ -326,7 +328,15 @@ void fragment() {
|
|||
#if defined(ALPHA_BLEND)
|
||||
ALPHA = alpha;
|
||||
#elif defined(ALPHA_CUTOUT)
|
||||
if (_AlphaCutoutEnable > 0.5 && alpha < _Cutoff) { discard; }
|
||||
if (_AlphaCutoutEnable > 0.5) {
|
||||
// NOTICE: Godot's alpha scissor path reads the sampled alpha from ALPHA.
|
||||
// This can route cutout shaders through the transparent pipeline; AIRI
|
||||
// accepts that tradeoff for alpha-to-coverage AA. See docs/vendor-patches.md.
|
||||
ALPHA = alpha;
|
||||
ALPHA_SCISSOR_THRESHOLD = _Cutoff;
|
||||
ALPHA_ANTIALIASING_EDGE = min(_Cutoff * 0.6, 0.3);
|
||||
ALPHA_TEXTURE_COORDINATE = mainUv * vec2(textureSize(_MainTex, 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
//METALLIC = metallic;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
shader_type spatial;
|
||||
render_mode alpha_to_coverage;
|
||||
|
||||
#define ALPHA_CUTOUT
|
||||
|
||||
#include "./mtoon_common.gdshaderinc"
|
||||
#include "./mtoon_common.gdshaderinc"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
shader_type spatial;
|
||||
render_mode cull_disabled;
|
||||
render_mode alpha_to_coverage;
|
||||
|
||||
#define ALPHA_CUTOUT
|
||||
|
||||
#include "./mtoon_common.gdshaderinc"
|
||||
#include "./mtoon_common.gdshaderinc"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
shader_type spatial;
|
||||
render_mode cull_front;
|
||||
render_mode alpha_to_coverage;
|
||||
|
||||
#define IS_OUTLINE
|
||||
#define ALPHA_CUTOUT
|
||||
|
||||
#include "./mtoon_common.gdshaderinc"
|
||||
#include "./mtoon_common.gdshaderinc"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,42 @@ whenever vendored add-on files differ from their upstream source.
|
|||
lookup fix or otherwise handles missing `secondary` nodes before parsing
|
||||
spring bones.
|
||||
|
||||
### MToon ambient and cutout shader patch
|
||||
|
||||
Files:
|
||||
|
||||
- `addons/Godot-MToon-Shader/mtoon_common.gdshaderinc`
|
||||
- `addons/Godot-MToon-Shader/mtoon_cutout.gdshader`
|
||||
- `addons/Godot-MToon-Shader/mtoon_cutout_cull_off.gdshader`
|
||||
- `addons/Godot-MToon-Shader/mtoon_outline_cutout.gdshader`
|
||||
|
||||
- Local change: enable `render_mode ambient_light_disabled` for the shared MToon
|
||||
shader include.
|
||||
- Local change: route MToon cutout materials through Godot's alpha scissor
|
||||
antialiasing path by writing `ALPHA`, setting `ALPHA_SCISSOR_THRESHOLD`,
|
||||
`ALPHA_ANTIALIASING_EDGE`, and `ALPHA_TEXTURE_COORDINATE`, and enabling
|
||||
`render_mode alpha_to_coverage`.
|
||||
- Reason: AIRI's stage preset owns sky, ground, and environment presentation, but
|
||||
avatar toon materials need stable character color. Godot's default ambient
|
||||
light and radiance contribution can wash out MToon avatars as the stage
|
||||
environment changes, so AIRI isolates avatar MToon materials from implicit
|
||||
WorldEnvironment ambient while keeping direct light handling in the shader.
|
||||
- Reason: VRM hair, lashes, accessories, and outline cutout passes use hard alpha
|
||||
edges. At distance, those edges collapse into visible stair-step or dashed
|
||||
pixels. Godot's alpha-to-coverage path works with 3D MSAA, and Godot's shader
|
||||
alpha scissor path requires `ALPHA` to receive the sampled texture alpha.
|
||||
Writing `ALPHA` may route these shaders through Godot's transparent pipeline,
|
||||
which can introduce sorting or shadow-casting regressions. AIRI accepts that
|
||||
tradeoff for the current visual baseline and should revisit it if those
|
||||
regressions appear or upstream exposes a cutout antialiasing path that
|
||||
preserves opaque shadow semantics.
|
||||
- Validation: `tests/material-rendering-check/materialRenderingCheck.tscn`
|
||||
imports AvatarSample A/B and still detects MToon, cutout, transparent,
|
||||
outline, and shadow-caster materials after the patch.
|
||||
- Removal condition: remove this patch if AIRI moves to an owned MToon shader
|
||||
variant, or if upstream exposes a supported way to opt MToon materials out of
|
||||
Godot environment ambient/radiance while preserving VRM import compatibility.
|
||||
|
||||
## Generated Metadata Differences
|
||||
|
||||
These files differ from the upstream commit after opening/importing the add-on
|
||||
|
|
|
|||
|
|
@ -29,5 +29,7 @@ enabled=PackedStringArray("res://addons/Godot-MToon-Shader/plugin.cfg", "res://a
|
|||
|
||||
[rendering]
|
||||
|
||||
anti_aliasing/quality/msaa_3d=2
|
||||
scaling_3d/scale=2.0
|
||||
rendering_device/driver.windows="d3d12"
|
||||
textures/vram_compression/import_etc2_astc=true
|
||||
|
|
|
|||
|
|
@ -12,8 +12,3 @@ script = ExtResource("1_k8kx6")
|
|||
[node name="Camera3D" type="Camera3D" parent="." unique_id=1342789791]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.93969274, 0.34201992, 0, -0.34201992, 0.93969274, 0, 1.2, 3.5)
|
||||
current = true
|
||||
|
||||
[node name="OmniLight3D" type="OmniLight3D" parent="." unique_id=1692990068]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2)
|
||||
light_color = Color(1, 0.956863, 0.909804, 1)
|
||||
omni_range = 12.0
|
||||
|
|
|
|||
|
|
@ -5,17 +5,7 @@ using Godot;
|
|||
|
||||
/// <summary>
|
||||
/// Root node for the Godot sidecar stage runtime.
|
||||
///
|
||||
/// Use when:
|
||||
/// - Running the desktop Godot stage through Electron main.
|
||||
/// - Receiving scene input from the current stage settings model selection.
|
||||
///
|
||||
/// Expects:
|
||||
/// - Electron launches Godot with <c>--airi-ws-url=<runtime-url></c>.
|
||||
/// - The scene contains or can create an avatar root node.
|
||||
///
|
||||
/// Returns:
|
||||
/// - A running stage process that reports ready/applied/error envelopes to Electron main.
|
||||
/// </summary>
|
||||
///
|
||||
/// Call stack:
|
||||
///
|
||||
|
|
@ -25,7 +15,6 @@ using Godot;
|
|||
/// -> <see cref="_Process"/>
|
||||
/// -> <see cref="StageBridge.Poll"/>
|
||||
/// -> <see cref="HandleMessage"/>
|
||||
/// </summary>
|
||||
public partial class StageRoot : Node3D
|
||||
{
|
||||
private const string AvatarRootNodeName = "AvatarRoot";
|
||||
|
|
@ -42,7 +31,6 @@ public partial class StageRoot : Node3D
|
|||
|
||||
private StageBridge _bridge = null!;
|
||||
private StageSceneController _sceneController = null!;
|
||||
private Label3D _statusLabel = null!;
|
||||
private StageViewController _viewController = null!;
|
||||
private StageCameraInputController _viewInputController = null!;
|
||||
private StageViewRuntime _viewRuntime = null!;
|
||||
|
|
@ -53,8 +41,7 @@ public partial class StageRoot : Node3D
|
|||
public override void _Ready()
|
||||
{
|
||||
HideEditorPreviewRoot();
|
||||
_statusLabel = CreateStatusLabel();
|
||||
AddChild(_statusLabel);
|
||||
StageVisualPreset.Apply(this);
|
||||
|
||||
var avatarRoot = ResolveAvatarRoot();
|
||||
_sceneController = new StageSceneController(avatarRoot, new VrmAvatarLoader());
|
||||
|
|
@ -63,7 +50,6 @@ public partial class StageRoot : Node3D
|
|||
var webSocketUrl = ResolveWebSocketUrl();
|
||||
if (string.IsNullOrWhiteSpace(webSocketUrl))
|
||||
{
|
||||
UpdateStatus("Missing Electron bridge URL.");
|
||||
GD.PushWarning("Godot stage missing --airi-ws-url argument.");
|
||||
return;
|
||||
}
|
||||
|
|
@ -76,13 +62,10 @@ public partial class StageRoot : Node3D
|
|||
var connectError = _bridge.Connect(webSocketUrl);
|
||||
if (connectError != Error.Ok)
|
||||
{
|
||||
UpdateStatus("Failed to connect to Electron main.");
|
||||
GD.PushError($"Godot stage failed to connect to Electron main: {connectError}.");
|
||||
GetTree().Quit();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateStatus("Connecting to Electron main...");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
@ -107,7 +90,6 @@ public partial class StageRoot : Node3D
|
|||
private void HandleBridgeOpened()
|
||||
{
|
||||
_bridge.SendEnvelope("stage.ready");
|
||||
UpdateStatus("Connected to Electron main.");
|
||||
}
|
||||
|
||||
private void HandleBridgeClosed(string message)
|
||||
|
|
@ -118,7 +100,6 @@ public partial class StageRoot : Node3D
|
|||
return;
|
||||
}
|
||||
|
||||
UpdateStatus(message);
|
||||
GD.PushWarning(message);
|
||||
GetTree().Quit();
|
||||
}
|
||||
|
|
@ -168,19 +149,6 @@ public partial class StageRoot : Node3D
|
|||
editorPreviewRoot.ProcessMode = ProcessModeEnum.Disabled;
|
||||
}
|
||||
|
||||
private static Label3D CreateStatusLabel()
|
||||
{
|
||||
return new Label3D
|
||||
{
|
||||
Billboard = BaseMaterial3D.BillboardModeEnum.Enabled,
|
||||
FontSize = 34,
|
||||
Modulate = new Color(0.95f, 0.98f, 1.0f),
|
||||
PixelSize = 0.0035f,
|
||||
Position = new Vector3(-1.45f, 1.75f, 0.0f),
|
||||
Text = "Godot Stage (experimental)",
|
||||
};
|
||||
}
|
||||
|
||||
private void HandleMessage(string rawMessage)
|
||||
{
|
||||
try
|
||||
|
|
@ -204,7 +172,6 @@ public partial class StageRoot : Node3D
|
|||
break;
|
||||
case "host.shutdown":
|
||||
_shutdownRequested = true;
|
||||
UpdateStatus("Shutdown requested by Electron main.");
|
||||
GetTree().Quit();
|
||||
break;
|
||||
}
|
||||
|
|
@ -212,7 +179,6 @@ public partial class StageRoot : Node3D
|
|||
catch (Exception error)
|
||||
{
|
||||
var message = $"Failed to parse Electron message: {error.Message}";
|
||||
UpdateStatus(message);
|
||||
SendSceneError(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -242,16 +208,14 @@ public partial class StageRoot : Node3D
|
|||
{
|
||||
// TODO:
|
||||
// Make avatar apply and view bootstrap one transaction. Today avatar apply commits
|
||||
// before bootstrap, so a bootstrap failure reports scene.error with the new avatar loaded.
|
||||
// before bootstrap. If bootstrap fails, scene.error is reported with the new
|
||||
// avatar already loaded.
|
||||
var avatar = _sceneController.Apply(payload);
|
||||
_viewController?.UseAvatar(avatar);
|
||||
_viewRuntime?.BootstrapForAvatar();
|
||||
_activeSceneModelId = payload.ModelId;
|
||||
}
|
||||
|
||||
var fileName = System.IO.Path.GetFileName(payload.Path);
|
||||
UpdateStatus($"Connected to Electron main.\nModel: {payload.Name}\nAsset: {fileName}");
|
||||
|
||||
_bridge.SendEnvelope("scene.applied", new
|
||||
{
|
||||
modelId = payload.ModelId,
|
||||
|
|
@ -260,7 +224,6 @@ public partial class StageRoot : Node3D
|
|||
catch (Exception error)
|
||||
{
|
||||
var message = $"Failed to apply scene input: {error.Message}";
|
||||
UpdateStatus(message);
|
||||
SendSceneError(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -334,7 +297,8 @@ public partial class StageRoot : Node3D
|
|||
var cameraController = new StageCameraPoseController(ResolveCamera());
|
||||
_viewController = new StageViewController(avatarRoot, cameraController);
|
||||
_viewRuntime = new StageViewRuntime(_viewController);
|
||||
_viewRuntime.SnapshotReady += payload => _bridge.SendEnvelope("stage.view.snapshot", payload);
|
||||
_viewRuntime.SnapshotReady += payload =>
|
||||
_bridge.SendEnvelope("stage.view.snapshot", payload);
|
||||
_viewRuntime.ErrorReady += payload => _bridge.SendEnvelope("stage.view.error", payload);
|
||||
_viewInputController = new StageCameraInputController(_viewRuntime, cameraController);
|
||||
}
|
||||
|
|
@ -346,7 +310,4 @@ public partial class StageRoot : Node3D
|
|||
message,
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateStatus(string message) =>
|
||||
_statusLabel.Text = $"Godot Stage (experimental)\n{message}";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ public static class StageViewStateRules
|
|||
public const double CameraMaxPitchDeg = 80;
|
||||
public const double CameraMinFovDeg = 10;
|
||||
public const double CameraMaxFovDeg = 120;
|
||||
public const double CameraMinPositionY = 0.05;
|
||||
|
||||
public static StageViewState CreateDefault() => new(
|
||||
1,
|
||||
|
|
@ -35,7 +36,11 @@ public static class StageViewStateRules
|
|||
|| patch.Camera?.FovDeg != null;
|
||||
}
|
||||
|
||||
public static StageViewState ApplyPatch(StageViewState current, StageViewPatch patch, long updatedAt)
|
||||
public static StageViewState ApplyPatch(
|
||||
StageViewState current,
|
||||
StageViewPatch patch,
|
||||
long updatedAt
|
||||
)
|
||||
{
|
||||
if (!HasMutation(patch))
|
||||
{
|
||||
|
|
@ -72,6 +77,7 @@ public static class StageViewStateRules
|
|||
SchemaVersion = 1,
|
||||
Camera = state.Camera with
|
||||
{
|
||||
Position = ClampCameraPosition(state.Camera.Position),
|
||||
YawDeg = NormalizeDegrees(state.Camera.YawDeg),
|
||||
PitchDeg = Clamp(state.Camera.PitchDeg, CameraMinPitchDeg, CameraMaxPitchDeg),
|
||||
FovDeg = Clamp(state.Camera.FovDeg, CameraMinFovDeg, CameraMaxFovDeg),
|
||||
|
|
@ -115,6 +121,15 @@ public static class StageViewStateRules
|
|||
return patch?.X != null || patch?.Y != null || patch?.Z != null;
|
||||
}
|
||||
|
||||
private static StageViewVec3 ClampCameraPosition(StageViewVec3 position)
|
||||
{
|
||||
return new StageViewVec3(
|
||||
position.X,
|
||||
Clamp(position.Y, CameraMinPositionY, double.PositiveInfinity),
|
||||
position.Z
|
||||
);
|
||||
}
|
||||
|
||||
private static double Clamp(double value, double min, double max)
|
||||
{
|
||||
return Math.Min(max, Math.Max(min, value));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Resolves presentation-stage environment assets that are owned outside the Godot project.
|
||||
///
|
||||
/// Use when:
|
||||
/// - The Godot stage is running from a workspace checkout and should reuse existing stage assets.
|
||||
/// - A fixed visual preset needs a local filesystem path instead of a Godot imported resource.
|
||||
///
|
||||
/// Expects:
|
||||
/// - <c>startDirectory</c> is inside or below the AIRI repository when workspace assets exist.
|
||||
///
|
||||
/// Returns:
|
||||
/// - Absolute filesystem paths for found assets, or an empty string when unavailable.
|
||||
/// </summary>
|
||||
public static class StageEnvironmentAssetResolver
|
||||
{
|
||||
private static readonly string[] ThreeStageSkyHdriPathSegments = new[]
|
||||
{
|
||||
"packages",
|
||||
"stage-ui-three",
|
||||
"src",
|
||||
"components",
|
||||
"Environment",
|
||||
"assets",
|
||||
"sky_linekotsi_23_HDRI.hdr",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the existing three-stage HDRI sky texture from a workspace directory.
|
||||
///
|
||||
/// Use when:
|
||||
/// - The Godot stage should reuse the stage-ui-three default skybox without copying it.
|
||||
///
|
||||
/// Expects:
|
||||
/// - <paramref name="startDirectory"/> is a filesystem directory path.
|
||||
///
|
||||
/// Returns:
|
||||
/// - Absolute path to the HDRI file, or <see cref="string.Empty"/> when it is unavailable.
|
||||
/// </summary>
|
||||
public static string ResolveThreeStageSkyHdriPath(string startDirectory)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startDirectory))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var currentDirectory = Path.GetFullPath(startDirectory);
|
||||
while (!string.IsNullOrWhiteSpace(currentDirectory))
|
||||
{
|
||||
var candidatePath = Path.GetFullPath(Path.Combine(
|
||||
currentDirectory,
|
||||
Path.Combine(ThreeStageSkyHdriPathSegments)
|
||||
));
|
||||
|
||||
if (File.Exists(candidatePath))
|
||||
{
|
||||
return candidatePath;
|
||||
}
|
||||
|
||||
// Walk upward from the Godot project directory until a repository root candidate matches.
|
||||
currentDirectory = Directory.GetParent(currentDirectory)?.FullName;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
using System;
|
||||
using Godot;
|
||||
using GodotEnvironment = Godot.Environment;
|
||||
|
||||
/// <summary>
|
||||
/// Installs the fixed G1.3 default stage visual baseline.
|
||||
///
|
||||
/// Use when:
|
||||
/// - The sidecar starts the default AIRI presentation stage.
|
||||
/// - Camera, lighting, sky, and ground references should be available without host settings.
|
||||
///
|
||||
/// Expects:
|
||||
/// - The stage root is a live <see cref="Node3D"/>.
|
||||
/// - Workspace runs can reach the existing stage-ui-three HDRI from the Godot project path.
|
||||
///
|
||||
/// Returns:
|
||||
/// - A single runtime-owned visual preset subtree with sky, ground references, and light rig.
|
||||
/// </summary>
|
||||
public static class StageVisualPreset
|
||||
{
|
||||
private const string VisualPresetRootNodeName = "DefaultStageVisualPreset";
|
||||
private const string WorldEnvironmentNodeName = "StageWorldEnvironment";
|
||||
private const string LightingRigNodeName = "StageLightingRig";
|
||||
private const string GroundPlaneNodeName = "StageGroundPlane";
|
||||
private const string CenterMarkerNodeName = "StageCenterT";
|
||||
|
||||
private const float GroundExtent = 180.0f;
|
||||
private const float LightShadowMaxDistance = 24.0f;
|
||||
private const float CenterMarkerElevation = 0.008f;
|
||||
private const string FadingGridShaderCode = """
|
||||
shader_type spatial;
|
||||
render_mode unshaded, cull_disabled, blend_mix;
|
||||
|
||||
uniform vec4 ground_color : source_color;
|
||||
uniform vec4 horizon_mist_color : source_color;
|
||||
uniform vec4 minor_grid_color : source_color;
|
||||
uniform vec4 major_grid_color : source_color;
|
||||
uniform vec4 center_grid_color : source_color;
|
||||
uniform float minor_spacing = 0.25;
|
||||
uniform float major_spacing = 1.0;
|
||||
uniform float fade_start = 8.0;
|
||||
uniform float fade_end = 22.0;
|
||||
uniform float minor_line_width = 0.34;
|
||||
uniform float major_line_width = 0.58;
|
||||
uniform float axis_width_world = 0.018;
|
||||
|
||||
varying vec3 world_position;
|
||||
|
||||
void vertex() {
|
||||
world_position = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
}
|
||||
|
||||
float grid_line(vec2 position, float spacing, float width) {
|
||||
vec2 coordinate = position / spacing;
|
||||
vec2 derivative = max(fwidth(coordinate), vec2(0.0001));
|
||||
vec2 grid = abs(fract(coordinate - 0.5) - 0.5) / derivative;
|
||||
return 1.0 - smoothstep(width, width + 1.0, min(grid.x, grid.y));
|
||||
}
|
||||
|
||||
float axis_line(float coordinate) {
|
||||
float derivative = max(fwidth(coordinate), 0.0001);
|
||||
return 1.0 - smoothstep(axis_width_world, axis_width_world + derivative, abs(coordinate));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
float distance_to_camera = distance(CAMERA_POSITION_WORLD.xz, world_position.xz);
|
||||
float horizon_fade = smoothstep(fade_start, fade_end, distance_to_camera);
|
||||
float grid_fade = pow(1.0 - horizon_fade, 3.2);
|
||||
|
||||
float minor_line = grid_line(world_position.xz, minor_spacing, minor_line_width);
|
||||
float major_line = grid_line(world_position.xz, major_spacing, major_line_width);
|
||||
float axis_line_alpha = max(axis_line(world_position.x), axis_line(world_position.z));
|
||||
|
||||
vec3 base_color = mix(
|
||||
ground_color.rgb,
|
||||
horizon_mist_color.rgb,
|
||||
horizon_fade * horizon_mist_color.a
|
||||
);
|
||||
vec3 grid_color = mix(minor_grid_color.rgb, major_grid_color.rgb, major_line);
|
||||
grid_color = mix(grid_color, center_grid_color.rgb, axis_line_alpha);
|
||||
|
||||
float line_alpha = max(
|
||||
minor_line * minor_grid_color.a,
|
||||
major_line * major_grid_color.a
|
||||
);
|
||||
line_alpha = max(line_alpha, axis_line_alpha * center_grid_color.a) * grid_fade;
|
||||
|
||||
ALBEDO = mix(base_color, grid_color, line_alpha);
|
||||
ALPHA = 1.0 - horizon_fade;
|
||||
ROUGHNESS = 0.88;
|
||||
}
|
||||
""";
|
||||
|
||||
private static readonly Color GroundColor = new(0.27f, 0.34f, 0.37f, 1.0f);
|
||||
private static readonly Color HorizonMistColor = new(0.62f, 0.73f, 0.76f, 0.82f);
|
||||
private static readonly Color MinorGridColor = new(1.0f, 1.0f, 1.0f, 0.20f);
|
||||
private static readonly Color MajorGridColor = new(1.0f, 1.0f, 1.0f, 0.38f);
|
||||
private static readonly Color CenterGridColor = new(1.0f, 1.0f, 1.0f, 0.72f);
|
||||
private static readonly Color CenterMarkerColor = new(0.72f, 0.94f, 1.0f, 0.92f);
|
||||
|
||||
/// <summary>
|
||||
/// Applies the stage visual preset under the provided root node.
|
||||
///
|
||||
/// Use when:
|
||||
/// - A stage scene should install its default visual baseline during startup.
|
||||
///
|
||||
/// Expects:
|
||||
/// - <paramref name="stageRoot"/> is not null.
|
||||
///
|
||||
/// Returns:
|
||||
/// - Existing preset subtree is replaced with a fresh fixed visual preset.
|
||||
/// </summary>
|
||||
public static void Apply(Node3D stageRoot)
|
||||
{
|
||||
if (stageRoot == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stageRoot));
|
||||
}
|
||||
|
||||
RemoveExistingPreset(stageRoot);
|
||||
|
||||
var visualRoot = new Node3D
|
||||
{
|
||||
Name = VisualPresetRootNodeName,
|
||||
};
|
||||
stageRoot.AddChild(visualRoot);
|
||||
|
||||
visualRoot.AddChild(CreateWorldEnvironment());
|
||||
visualRoot.AddChild(CreateGroundPlane());
|
||||
visualRoot.AddChild(CreateCenterMarker());
|
||||
visualRoot.AddChild(CreateLightingRig());
|
||||
}
|
||||
|
||||
private static void RemoveExistingPreset(Node stageRoot)
|
||||
{
|
||||
var existingPreset = stageRoot.GetNodeOrNull<Node>(VisualPresetRootNodeName);
|
||||
if (existingPreset == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stageRoot.RemoveChild(existingPreset);
|
||||
existingPreset.QueueFree();
|
||||
}
|
||||
|
||||
private static WorldEnvironment CreateWorldEnvironment()
|
||||
{
|
||||
var skyMaterial = new PanoramaSkyMaterial
|
||||
{
|
||||
EnergyMultiplier = 1.0f,
|
||||
Panorama = LoadSkyTexture(),
|
||||
};
|
||||
var sky = new Sky
|
||||
{
|
||||
ProcessMode = Sky.ProcessModeEnum.Quality,
|
||||
SkyMaterial = skyMaterial,
|
||||
};
|
||||
var environment = new GodotEnvironment
|
||||
{
|
||||
AmbientLightEnergy = 0.26f,
|
||||
AmbientLightSkyContribution = 0.48f,
|
||||
AmbientLightSource = GodotEnvironment.AmbientSource.Sky,
|
||||
BackgroundEnergyMultiplier = 1.06f,
|
||||
BackgroundMode = GodotEnvironment.BGMode.Sky,
|
||||
ReflectedLightSource = GodotEnvironment.ReflectionSource.Sky,
|
||||
Sky = sky,
|
||||
// Keep MToon/NPR avatars out of filmic tone mapping, then apply a small
|
||||
// stylized display grade. The VRM materials already use source_color
|
||||
// texture inputs; the remaining gap to three-stage is presentation color,
|
||||
// not importer-side texture conversion.
|
||||
// Three-stage disables tone mapping per MToon material; Godot applies
|
||||
// environment tone mapping globally, so filmic curves wash avatar colors out.
|
||||
AdjustmentContrast = 1.03f,
|
||||
AdjustmentEnabled = true,
|
||||
AdjustmentSaturation = 1.24f,
|
||||
TonemapExposure = 1.0f,
|
||||
TonemapMode = GodotEnvironment.ToneMapper.Linear,
|
||||
};
|
||||
|
||||
return new WorldEnvironment
|
||||
{
|
||||
Name = WorldEnvironmentNodeName,
|
||||
Environment = environment,
|
||||
};
|
||||
}
|
||||
|
||||
private static Texture2D LoadSkyTexture()
|
||||
{
|
||||
var skyHdriPath = StageEnvironmentAssetResolver.ResolveThreeStageSkyHdriPath(
|
||||
ProjectSettings.GlobalizePath("res://")
|
||||
);
|
||||
if (string.IsNullOrWhiteSpace(skyHdriPath))
|
||||
{
|
||||
GD.PushWarning("Default stage HDR skybox could not be found in stage-ui-three assets.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var image = Image.LoadFromFile(skyHdriPath);
|
||||
if (image == null || image.GetWidth() <= 0 || image.GetHeight() <= 0)
|
||||
{
|
||||
GD.PushWarning($"Default stage HDR skybox could not be loaded: {skyHdriPath}.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return ImageTexture.CreateFromImage(image);
|
||||
}
|
||||
|
||||
private static MeshInstance3D CreateGroundPlane()
|
||||
{
|
||||
var shader = new Shader
|
||||
{
|
||||
Code = FadingGridShaderCode,
|
||||
};
|
||||
var material = new ShaderMaterial
|
||||
{
|
||||
Shader = shader,
|
||||
};
|
||||
material.SetShaderParameter("ground_color", GroundColor);
|
||||
material.SetShaderParameter("horizon_mist_color", HorizonMistColor);
|
||||
material.SetShaderParameter("minor_grid_color", MinorGridColor);
|
||||
material.SetShaderParameter("major_grid_color", MajorGridColor);
|
||||
material.SetShaderParameter("center_grid_color", CenterGridColor);
|
||||
|
||||
return new MeshInstance3D
|
||||
{
|
||||
CastShadow = GeometryInstance3D.ShadowCastingSetting.Off,
|
||||
MaterialOverride = material,
|
||||
Mesh = new PlaneMesh
|
||||
{
|
||||
Orientation = PlaneMesh.OrientationEnum.Y,
|
||||
Size = new Vector2(GroundExtent * 2.0f, GroundExtent * 2.0f),
|
||||
SubdivideDepth = 24,
|
||||
SubdivideWidth = 24,
|
||||
},
|
||||
Name = GroundPlaneNodeName,
|
||||
};
|
||||
}
|
||||
|
||||
private static Node3D CreateCenterMarker()
|
||||
{
|
||||
var root = new Node3D
|
||||
{
|
||||
Name = CenterMarkerNodeName,
|
||||
};
|
||||
var material = new StandardMaterial3D
|
||||
{
|
||||
AlbedoColor = CenterMarkerColor,
|
||||
ShadingMode = BaseMaterial3D.ShadingModeEnum.Unshaded,
|
||||
};
|
||||
|
||||
root.AddChild(CreateCenterMarkerBar(
|
||||
"Top",
|
||||
new Vector3(0.0f, CenterMarkerElevation, 0.15f),
|
||||
new Vector3(0.36f, 0.012f, 0.0275f),
|
||||
material
|
||||
));
|
||||
root.AddChild(CreateCenterMarkerBar(
|
||||
"Stem",
|
||||
new Vector3(0.0f, CenterMarkerElevation, -0.02f),
|
||||
new Vector3(0.0275f, 0.012f, 0.34f),
|
||||
material
|
||||
));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private static MeshInstance3D CreateCenterMarkerBar(
|
||||
string name,
|
||||
Vector3 position,
|
||||
Vector3 size,
|
||||
Material material
|
||||
)
|
||||
{
|
||||
return new MeshInstance3D
|
||||
{
|
||||
CastShadow = GeometryInstance3D.ShadowCastingSetting.Off,
|
||||
MaterialOverride = material,
|
||||
Mesh = new BoxMesh
|
||||
{
|
||||
Size = size,
|
||||
},
|
||||
Name = name,
|
||||
Position = position,
|
||||
};
|
||||
}
|
||||
|
||||
private static Node3D CreateLightingRig()
|
||||
{
|
||||
var rig = new Node3D
|
||||
{
|
||||
Name = LightingRigNodeName,
|
||||
};
|
||||
|
||||
rig.AddChild(CreateDirectionalLight(
|
||||
"KeyLight",
|
||||
new Vector3(-48.0f, -34.0f, 0.0f),
|
||||
new Color(1.0f, 1.0f, 1.0f),
|
||||
0.76f,
|
||||
1.1f,
|
||||
true
|
||||
));
|
||||
rig.AddChild(CreateDirectionalLight(
|
||||
"FillLight",
|
||||
new Vector3(-20.0f, 122.0f, 0.0f),
|
||||
new Color(1.0f, 1.0f, 1.0f),
|
||||
0.06f,
|
||||
0.0f,
|
||||
false
|
||||
));
|
||||
rig.AddChild(CreateDirectionalLight(
|
||||
"RimLight",
|
||||
new Vector3(-18.0f, 205.0f, 0.0f),
|
||||
new Color(1.0f, 1.0f, 1.0f),
|
||||
0.20f,
|
||||
0.0f,
|
||||
false
|
||||
));
|
||||
|
||||
return rig;
|
||||
}
|
||||
|
||||
private static DirectionalLight3D CreateDirectionalLight(
|
||||
string name,
|
||||
Vector3 rotationDegrees,
|
||||
Color color,
|
||||
float energy,
|
||||
float angularDistance,
|
||||
bool shadowEnabled
|
||||
)
|
||||
{
|
||||
return new DirectionalLight3D
|
||||
{
|
||||
DirectionalShadowMaxDistance = LightShadowMaxDistance,
|
||||
LightAngularDistance = angularDistance,
|
||||
LightColor = color,
|
||||
LightEnergy = energy,
|
||||
Name = name,
|
||||
RotationDegrees = rotationDegrees,
|
||||
ShadowEnabled = shadowEnabled,
|
||||
SkyMode = DirectionalLight3D.SkyModeEnum.LightOnly,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -5,4 +5,9 @@
|
|||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
<RootNamespace>StageTamagotchiGodot</RootNamespace>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<!-- Keep generated sources and verification harnesses out of the game assembly. -->
|
||||
<Compile Remove=".godot\**\*.cs" />
|
||||
<Compile Remove="tests\**\*.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<ArtifactsRoot>$(MSBuildThisFileDirectory)..\..\.godot\mono\temp\tests\</ArtifactsRoot>
|
||||
<ArtifactsRoot>$([System.IO.Path]::GetFullPath('$(ArtifactsRoot)'))</ArtifactsRoot>
|
||||
<BaseOutputPath>$(ArtifactsRoot)bin\</BaseOutputPath>
|
||||
<BaseIntermediateOutputPath>$(ArtifactsRoot)obj\</BaseIntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,191 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
/// <summary>
|
||||
/// Runs focused engine-local regression checks that do not require the Godot editor.
|
||||
///
|
||||
/// Call stack:
|
||||
///
|
||||
/// dotnet run --project tests/StageTamagotchiGodot.Tests
|
||||
/// -> <see cref="Main"/>
|
||||
/// -> <see cref="CameraGroundConstraint"/>
|
||||
/// -> <see cref="StageViewStateRules"/>
|
||||
/// -> <see cref="StageEnvironmentAssets"/>
|
||||
/// -> <see cref="StageEnvironmentAssetResolver"/>
|
||||
/// </summary>
|
||||
internal static class Program
|
||||
{
|
||||
private const double ExpectedCameraMinY = 0.05;
|
||||
private const string ThreeStageSkyHdriRelativePath =
|
||||
"packages/stage-ui-three/src/components/Environment/assets/sky_linekotsi_23_HDRI.hdr";
|
||||
|
||||
private static int Main()
|
||||
{
|
||||
try
|
||||
{
|
||||
CameraGroundConstraint.ApplyPatchClampsCameraYToStageGround();
|
||||
CameraGroundConstraint.NormalizeClampsCameraYToStageGround();
|
||||
CameraGroundConstraint.NormalizePreservesCameraYAboveStageGround();
|
||||
StageEnvironmentAssets.ResolvesThreeStageSkyHdriFromGodotProjectDirectory();
|
||||
StageEnvironmentAssets.ReturnsEmptyPathWhenThreeStageSkyHdriIsUnavailable();
|
||||
Console.WriteLine("StageTamagotchiGodot.Tests passed.");
|
||||
return 0;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Console.Error.WriteLine(error.Message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StageEnvironmentAssets
|
||||
{
|
||||
public static void ResolvesThreeStageSkyHdriFromGodotProjectDirectory()
|
||||
{
|
||||
var projectDirectory = FindGodotProjectDirectory();
|
||||
|
||||
var skyHdriPath = StageEnvironmentAssetResolver.ResolveThreeStageSkyHdriPath(
|
||||
projectDirectory
|
||||
);
|
||||
|
||||
AssertEqual(
|
||||
NormalizePath(FindRepositoryRootFrom(projectDirectory), ThreeStageSkyHdriRelativePath),
|
||||
skyHdriPath,
|
||||
"three-stage sky HDRI path"
|
||||
);
|
||||
}
|
||||
|
||||
public static void ReturnsEmptyPathWhenThreeStageSkyHdriIsUnavailable()
|
||||
{
|
||||
var missingRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
|
||||
|
||||
var skyHdriPath = StageEnvironmentAssetResolver.ResolveThreeStageSkyHdriPath(missingRoot);
|
||||
|
||||
AssertEqual(string.Empty, skyHdriPath, "missing three-stage sky HDRI path");
|
||||
}
|
||||
}
|
||||
|
||||
private static class CameraGroundConstraint
|
||||
{
|
||||
public static void ApplyPatchClampsCameraYToStageGround()
|
||||
{
|
||||
var current = StageViewStateRules.CreateDefault();
|
||||
var patch = new StageViewPatch(
|
||||
Camera: new StageCameraPosePatch(
|
||||
Position: new StageViewVec3Patch(Y: -2)
|
||||
)
|
||||
);
|
||||
|
||||
var next = StageViewStateRules.ApplyPatch(current, patch, 123);
|
||||
|
||||
AssertEqual(ExpectedCameraMinY, next.Camera.Position.Y, "remote patch camera Y");
|
||||
AssertEqual(1, next.Revision, "revision after camera ground clamp");
|
||||
AssertEqual(123, next.UpdatedAt, "updatedAt after camera ground clamp");
|
||||
}
|
||||
|
||||
public static void NormalizeClampsCameraYToStageGround()
|
||||
{
|
||||
var state = StageViewStateRules.CreateDefault() with
|
||||
{
|
||||
Camera = StageViewStateRules.CreateDefault().Camera with
|
||||
{
|
||||
Position = new StageViewVec3(0, -100, 3.5),
|
||||
},
|
||||
};
|
||||
|
||||
var normalized = StageViewStateRules.Normalize(state);
|
||||
|
||||
AssertEqual(ExpectedCameraMinY, normalized.Camera.Position.Y, "normalized camera Y");
|
||||
}
|
||||
|
||||
public static void NormalizePreservesCameraYAboveStageGround()
|
||||
{
|
||||
var state = StageViewStateRules.CreateDefault() with
|
||||
{
|
||||
Camera = StageViewStateRules.CreateDefault().Camera with
|
||||
{
|
||||
Position = new StageViewVec3(0, 2.5, 3.5),
|
||||
},
|
||||
};
|
||||
|
||||
var normalized = StageViewStateRules.Normalize(state);
|
||||
|
||||
AssertEqual(2.5, normalized.Camera.Position.Y, "above-ground camera Y");
|
||||
}
|
||||
}
|
||||
|
||||
private static void AssertEqual(double expected, double actual, string label)
|
||||
{
|
||||
if (Math.Abs(expected - actual) <= 0.000001)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Expected {label} to be {expected}, got {actual}."
|
||||
);
|
||||
}
|
||||
|
||||
private static void AssertEqual(long expected, long actual, string label)
|
||||
{
|
||||
if (expected == actual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Expected {label} to be {expected}, got {actual}."
|
||||
);
|
||||
}
|
||||
|
||||
private static void AssertEqual(string expected, string actual, string label)
|
||||
{
|
||||
if (string.Equals(expected, actual, StringComparison.Ordinal))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Expected {label} to be '{expected}', got '{actual}'."
|
||||
);
|
||||
}
|
||||
|
||||
private static string FindGodotProjectDirectory()
|
||||
{
|
||||
var currentDirectory = AppContext.BaseDirectory;
|
||||
while (!string.IsNullOrWhiteSpace(currentDirectory))
|
||||
{
|
||||
if (File.Exists(Path.Combine(currentDirectory, "project.godot")))
|
||||
{
|
||||
return currentDirectory;
|
||||
}
|
||||
|
||||
currentDirectory = Directory.GetParent(currentDirectory)?.FullName;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Could not find Godot project directory.");
|
||||
}
|
||||
|
||||
private static string FindRepositoryRootFrom(string startDirectory)
|
||||
{
|
||||
var currentDirectory = startDirectory;
|
||||
while (!string.IsNullOrWhiteSpace(currentDirectory))
|
||||
{
|
||||
var gitMarkerPath = Path.Combine(currentDirectory, ".git");
|
||||
// Git worktrees store .git as a file that points to the real common directory.
|
||||
if (Directory.Exists(gitMarkerPath) || File.Exists(gitMarkerPath))
|
||||
{
|
||||
return currentDirectory;
|
||||
}
|
||||
|
||||
currentDirectory = Directory.GetParent(currentDirectory)?.FullName;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Could not find repository root.");
|
||||
}
|
||||
|
||||
private static string NormalizePath(string root, string relativePath) =>
|
||||
Path.GetFullPath(
|
||||
Path.Combine(root, relativePath.Replace('/', Path.DirectorySeparatorChar))
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ProjectDirInput>$(MSBuildThisFileDirectory)..\..</ProjectDirInput>
|
||||
<GodotProjectDir>$([System.IO.Path]::GetFullPath('$(ProjectDirInput)'))</GodotProjectDir>
|
||||
<GodotDir>$([MSBuild]::EnsureTrailingSlash('$(GodotProjectDir)'))</GodotDir>
|
||||
<GodotProjectDir>$(GodotDir)</GodotProjectDir>
|
||||
<GodotProjectDirBase64>$([MSBuild]::ConvertToBase64('$(GodotDir)'))</GodotProjectDirBase64>
|
||||
<ImplicitUsings>false</ImplicitUsings>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<CompilerVisibleProperty Include="GodotProjectDir" />
|
||||
<CompilerVisibleProperty Include="GodotProjectDirBase64" />
|
||||
<CompilerVisibleProperty Include="GodotSourceGenerators" />
|
||||
<CompilerVisibleProperty Include="IsGodotToolsProject" />
|
||||
<ProjectReference Include="..\..\stage-tamagotchi-godot.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
extends Node
|
||||
|
||||
const vrm_runtime_importer = preload("res://scripts/vrm/VrmRuntimeImporter.gd")
|
||||
|
||||
const SAMPLE_PATHS := [
|
||||
"res://../../packages/stage-ui/src/assets/vrm/models/AvatarSample-A/AvatarSample_A.vrm",
|
||||
"res://../../packages/stage-ui/src/assets/vrm/models/AvatarSample-B/AvatarSample_B.vrm",
|
||||
]
|
||||
|
||||
func _ready() -> void:
|
||||
var failures: Array[String] = []
|
||||
|
||||
for sample_path in SAMPLE_PATHS:
|
||||
var summary := _inspect_sample(sample_path)
|
||||
print("Material check: %s" % summary)
|
||||
_collect_sample_failures(summary, failures)
|
||||
|
||||
for failure in failures:
|
||||
push_error(failure)
|
||||
|
||||
get_tree().quit(1 if failures.size() > 0 else 0)
|
||||
|
||||
|
||||
func _inspect_sample(sample_path: String) -> Dictionary:
|
||||
var importer: RefCounted = vrm_runtime_importer.new()
|
||||
var native_path := ProjectSettings.globalize_path(sample_path)
|
||||
var avatar: Node = importer.import_vrm(native_path)
|
||||
var summary := {
|
||||
"sample": sample_path.get_file(),
|
||||
"mtoon": 0,
|
||||
"cutout": 0,
|
||||
"transparent": 0,
|
||||
"outline": 0,
|
||||
"shadowCasters": 0,
|
||||
"unlit": 0,
|
||||
"error": "",
|
||||
}
|
||||
|
||||
if avatar == null:
|
||||
summary["error"] = importer.get_last_error()
|
||||
return summary
|
||||
|
||||
_scan_node(avatar, summary)
|
||||
avatar.free()
|
||||
return summary
|
||||
|
||||
|
||||
func _scan_node(node: Node, summary: Dictionary) -> void:
|
||||
if node is MeshInstance3D:
|
||||
_scan_mesh_instance(node, summary)
|
||||
|
||||
for child in node.get_children():
|
||||
_scan_node(child, summary)
|
||||
|
||||
|
||||
func _scan_mesh_instance(mesh_instance: MeshInstance3D, summary: Dictionary) -> void:
|
||||
if mesh_instance.cast_shadow != GeometryInstance3D.SHADOW_CASTING_SETTING_OFF:
|
||||
summary["shadowCasters"] += 1
|
||||
|
||||
if mesh_instance.mesh == null:
|
||||
return
|
||||
|
||||
for surface_index in range(mesh_instance.mesh.get_surface_count()):
|
||||
var material := mesh_instance.get_surface_override_material(surface_index)
|
||||
if material == null:
|
||||
material = mesh_instance.mesh.surface_get_material(surface_index)
|
||||
|
||||
_scan_material(material, summary)
|
||||
|
||||
|
||||
func _scan_material(material: Material, summary: Dictionary) -> void:
|
||||
if material == null:
|
||||
return
|
||||
|
||||
if material is StandardMaterial3D:
|
||||
if material.shading_mode == BaseMaterial3D.SHADING_MODE_UNSHADED:
|
||||
summary["unlit"] += 1
|
||||
return
|
||||
|
||||
if material is not ShaderMaterial or material.shader == null:
|
||||
return
|
||||
|
||||
var shader_path: String = material.shader.resource_path
|
||||
if shader_path.find("mtoon") == -1:
|
||||
return
|
||||
|
||||
summary["mtoon"] += 1
|
||||
|
||||
if shader_path.find("_cutout") != -1:
|
||||
summary["cutout"] += 1
|
||||
|
||||
if shader_path.find("_trans") != -1:
|
||||
summary["transparent"] += 1
|
||||
|
||||
if material.next_pass is ShaderMaterial and material.next_pass.shader != null:
|
||||
var outline_path: String = material.next_pass.shader.resource_path
|
||||
if outline_path.find("mtoon_outline") != -1:
|
||||
summary["outline"] += 1
|
||||
|
||||
|
||||
func _collect_sample_failures(summary: Dictionary, failures: Array[String]) -> void:
|
||||
if not summary["error"].is_empty():
|
||||
failures.push_back("%s import failed: %s" % [summary["sample"], summary["error"]])
|
||||
return
|
||||
|
||||
if summary["mtoon"] == 0:
|
||||
failures.push_back("%s did not import MToon materials." % summary["sample"])
|
||||
|
||||
if summary["cutout"] == 0:
|
||||
failures.push_back("%s did not import alpha/cutout MToon materials." % summary["sample"])
|
||||
|
||||
if summary["transparent"] == 0:
|
||||
failures.push_back("%s did not import transparent MToon materials." % summary["sample"])
|
||||
|
||||
if summary["outline"] == 0:
|
||||
failures.push_back("%s did not import MToon outline passes." % summary["sample"])
|
||||
|
||||
if summary["shadowCasters"] == 0:
|
||||
failures.push_back("%s did not expose any mesh shadow casters." % summary["sample"])
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://tests/material-rendering-check/materialRenderingCheck.gd" id="1_n1afi"]
|
||||
|
||||
[node name="MaterialRenderingCheck" type="Node"]
|
||||
script = ExtResource("1_n1afi")
|
||||
264
pnpm-lock.yaml
generated
264
pnpm-lock.yaml
generated
|
|
@ -1495,7 +1495,7 @@ importers:
|
|||
version: 3.0.2(electron@41.2.1)
|
||||
'@electron-toolkit/tsconfig':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(@types/node@25.6.0)
|
||||
version: 2.0.0(@types/node@24.12.2)
|
||||
'@electron-toolkit/utils':
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0(electron@41.2.1)
|
||||
|
|
@ -1534,7 +1534,7 @@ importers:
|
|||
version: 3.1.0
|
||||
'@intlify/unplugin-vue-i18n':
|
||||
specifier: ^11.0.7
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@modelcontextprotocol/sdk':
|
||||
specifier: 'catalog:'
|
||||
version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)
|
||||
|
|
@ -1570,10 +1570,10 @@ importers:
|
|||
version: link:../../packages/ui-transitions
|
||||
'@proj-airi/unplugin-fetch':
|
||||
specifier: 'catalog:'
|
||||
version: 0.2.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 0.2.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
'@proj-airi/unplugin-live2d-sdk':
|
||||
specifier: ^0.1.7
|
||||
version: 0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
version: 0.1.7(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
'@types/audioworklet':
|
||||
specifier: 'catalog:'
|
||||
version: 0.0.97
|
||||
|
|
@ -1600,7 +1600,7 @@ importers:
|
|||
version: 2.10.3
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^6.0.6
|
||||
version: 6.0.6(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 6.0.6(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/volar':
|
||||
specifier: ^3.1.2
|
||||
version: 3.1.2(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
|
|
@ -1633,7 +1633,7 @@ importers:
|
|||
version: 6.8.3
|
||||
electron-vite:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 5.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
get-port-please:
|
||||
specifier: 'catalog:'
|
||||
version: 3.2.0
|
||||
|
|
@ -1654,31 +1654,31 @@ importers:
|
|||
version: 2.2.6
|
||||
unocss-preset-scrollbar:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0(unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)))
|
||||
version: 4.0.0(unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)))
|
||||
unplugin-info:
|
||||
specifier: ^1.3.2
|
||||
version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
unplugin-yaml:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0(@nuxt/kit@3.20.2(magicast@0.5.2))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite:
|
||||
specifier: 'catalog:'
|
||||
version: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
version: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-bundle-visualizer:
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1(rolldown@1.0.0-rc.16)(rollup@4.60.1)
|
||||
vite-plugin-mkcert:
|
||||
specifier: 'catalog:'
|
||||
version: 2.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
version: 2.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite-plugin-vue-devtools:
|
||||
specifier: ^8.1.1
|
||||
version: 8.1.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 8.1.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))
|
||||
vite-plugin-vue-layouts:
|
||||
specifier: ^0.11.0
|
||||
version: 0.11.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 0.11.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
vue-macros:
|
||||
specifier: ^3.1.2
|
||||
version: 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
version: 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
vue-tsc:
|
||||
specifier: ^3.2.6
|
||||
version: 3.2.6(typescript@5.9.3)
|
||||
|
|
@ -19998,9 +19998,9 @@ snapshots:
|
|||
dependencies:
|
||||
electron: 41.2.1
|
||||
|
||||
'@electron-toolkit/tsconfig@2.0.0(@types/node@25.6.0)':
|
||||
'@electron-toolkit/tsconfig@2.0.0(@types/node@24.12.2)':
|
||||
dependencies:
|
||||
'@types/node': 25.6.0
|
||||
'@types/node': 24.12.2
|
||||
|
||||
'@electron-toolkit/utils@4.0.0(electron@41.2.1)':
|
||||
dependencies:
|
||||
|
|
@ -20912,6 +20912,31 @@ snapshots:
|
|||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1))
|
||||
'@intlify/bundle-utils': 11.0.7(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))
|
||||
'@intlify/shared': 11.3.2
|
||||
'@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.3.2)(@vue/compiler-dom@3.5.32)(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
'@typescript-eslint/scope-manager': 8.58.1
|
||||
'@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3)
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
fast-glob: 3.3.3
|
||||
pathe: 2.0.3
|
||||
picocolors: 1.1.1
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vue-i18n: 11.3.2(vue@3.5.32(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- '@vue/compiler-dom'
|
||||
- eslint
|
||||
- rollup
|
||||
- supports-color
|
||||
- typescript
|
||||
|
||||
'@intlify/unplugin-vue-i18n@11.0.7(@vue/compiler-dom@3.5.32)(eslint@10.2.1(jiti@2.6.1))(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-i18n@11.3.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.9.1(eslint@10.2.1(jiti@2.6.1))
|
||||
|
|
@ -22910,11 +22935,35 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@proj-airi/unplugin-fetch@0.2.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
'@proj-airi/unplugin-fetch@0.2.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
'@proj-airi/unplugin-live2d-sdk@0.1.7(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
yauzl: 3.3.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- '@vitejs/devtools'
|
||||
- esbuild
|
||||
- jiti
|
||||
- less
|
||||
- sass
|
||||
- sass-embedded
|
||||
- stylus
|
||||
- sugarss
|
||||
- terser
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
'@proj-airi/unplugin-live2d-sdk@0.1.7(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)':
|
||||
dependencies:
|
||||
ofetch: 1.5.1
|
||||
|
|
@ -23815,6 +23864,7 @@ snapshots:
|
|||
'@types/node@25.6.0':
|
||||
dependencies:
|
||||
undici-types: 7.19.2
|
||||
optional: true
|
||||
|
||||
'@types/nprogress@0.2.3': {}
|
||||
|
||||
|
|
@ -24480,6 +24530,12 @@ snapshots:
|
|||
vite: 6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
|
||||
'@vitejs/plugin-vue@6.0.6(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.13
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
|
||||
'@vitejs/plugin-vue@6.0.6(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.13
|
||||
|
|
@ -24560,9 +24616,9 @@ snapshots:
|
|||
obug: 2.1.1
|
||||
std-env: 4.1.0
|
||||
tinyrainbow: 3.1.0
|
||||
vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1(@noble/hashes@2.0.1)(canvas@3.2.3))(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vitest: 4.1.4(@opentelemetry/api@1.9.1)(@types/node@24.12.2)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@4.1.4)(jsdom@29.1.1(@noble/hashes@2.0.1)(canvas@3.2.3))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
optionalDependencies:
|
||||
'@vitest/browser': 4.1.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)
|
||||
'@vitest/browser': 4.1.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vitest@4.1.4)
|
||||
|
||||
'@vitest/eslint-plugin@1.6.15(@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.1(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.1(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.1(jiti@2.6.1))(typescript@5.9.3)(vitest@4.1.4)':
|
||||
dependencies:
|
||||
|
|
@ -24782,6 +24838,15 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
'@vue-macros/devtools@3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
sirv: 3.0.2
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
optionalDependencies:
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- typescript
|
||||
|
||||
'@vue-macros/devtools@3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))':
|
||||
dependencies:
|
||||
sirv: 3.0.2
|
||||
|
|
@ -26923,7 +26988,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
electron-vite@5.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
electron-vite@5.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0)
|
||||
|
|
@ -26931,7 +26996,7 @@ snapshots:
|
|||
esbuild: 0.25.12
|
||||
magic-string: 0.30.21
|
||||
picocolors: 1.1.1
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
@ -32847,7 +32912,8 @@ snapshots:
|
|||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
undici-types@7.19.2: {}
|
||||
undici-types@7.19.2:
|
||||
optional: true
|
||||
|
||||
undici@6.24.1: {}
|
||||
|
||||
|
|
@ -32959,11 +33025,6 @@ snapshots:
|
|||
'@unocss/preset-mini': 66.6.8
|
||||
unocss: 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
unocss-preset-scrollbar@4.0.0(unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))):
|
||||
dependencies:
|
||||
'@unocss/preset-mini': 66.6.8
|
||||
unocss: 66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
unocss@66.6.8(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vite@6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@unocss/cli': 66.6.8
|
||||
|
|
@ -33060,6 +33121,14 @@ snapshots:
|
|||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rolldown: 1.0.0-rc.16
|
||||
rollup: 4.60.1
|
||||
unplugin: 2.3.11
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-combine@2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
|
|
@ -33094,6 +33163,19 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
unplugin-info@1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ci-info: 4.4.0
|
||||
git-url-parse: 16.1.0
|
||||
simple-git: 3.36.0
|
||||
unplugin: 2.3.11
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rollup: 4.60.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
unplugin-info@1.3.2(esbuild@0.27.2)(rollup@4.60.1)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ci-info: 4.4.0
|
||||
|
|
@ -33203,6 +33285,17 @@ snapshots:
|
|||
rollup: 4.60.1
|
||||
vite: 6.4.2(@types/node@25.6.0)(jiti@2.6.1)(less@4.6.4)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin-yaml@4.1.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.60.1)
|
||||
unplugin: 3.0.0
|
||||
yaml: 2.8.3
|
||||
optionalDependencies:
|
||||
esbuild: 0.27.2
|
||||
rolldown: 1.0.0-rc.16
|
||||
rollup: 4.60.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
unplugin@2.3.11:
|
||||
dependencies:
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
|
|
@ -33434,12 +33527,22 @@ snapshots:
|
|||
- rollup
|
||||
- supports-color
|
||||
|
||||
vite-dev-rpc@1.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
birpc: 2.9.0
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-hot-client: 2.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
vite-dev-rpc@1.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
birpc: 2.9.0
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-hot-client: 2.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
|
||||
vite-hot-client@2.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
vite-hot-client@2.1.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
vite: 8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
|
@ -33485,6 +33588,21 @@ snapshots:
|
|||
- tsx
|
||||
- yaml
|
||||
|
||||
vite-plugin-inspect@11.3.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ansis: 4.2.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
error-stack-parser-es: 1.0.5
|
||||
ohash: 2.0.11
|
||||
open: 10.2.0
|
||||
perfect-debounce: 2.1.0
|
||||
sirv: 3.0.2
|
||||
unplugin-utils: 0.3.1
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-dev-rpc: 1.1.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-inspect@11.3.3(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
ansis: 4.2.0
|
||||
|
|
@ -33516,6 +33634,13 @@ snapshots:
|
|||
- typescript
|
||||
- ws
|
||||
|
||||
vite-plugin-mkcert@2.0.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
supports-color: 10.2.2
|
||||
undici: 8.1.0
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
|
||||
vite-plugin-mkcert@2.0.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -33534,6 +33659,20 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-devtools@8.1.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-core': 8.1.1(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue/devtools-kit': 8.1.1
|
||||
'@vue/devtools-shared': 8.1.1
|
||||
sirv: 3.0.2
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vite-plugin-inspect: 11.3.3(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
vite-plugin-vue-inspector: 5.3.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
transitivePeerDependencies:
|
||||
- '@nuxt/kit'
|
||||
- supports-color
|
||||
- vue
|
||||
|
||||
vite-plugin-vue-devtools@8.1.1(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-core': 8.1.1(vue@3.5.32(typescript@5.9.3))
|
||||
|
|
@ -33548,6 +33687,21 @@ snapshots:
|
|||
- supports-color
|
||||
- vue
|
||||
|
||||
vite-plugin-vue-inspector@5.3.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.29.0)
|
||||
'@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0)
|
||||
'@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0)
|
||||
'@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.29.0)
|
||||
'@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.29.0)
|
||||
'@vue/compiler-dom': 3.5.32
|
||||
kolorist: 1.8.0
|
||||
magic-string: 0.30.21
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-inspector@5.3.2(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
|
|
@ -33563,6 +33717,16 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-layouts@0.11.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
fast-glob: 3.3.3
|
||||
vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3)
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
vue-router: 5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-vue-layouts@0.11.0(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-router@5.0.4(@pinia/colada@1.2.1(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(@vue/compiler-sfc@3.5.32)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
|
|
@ -33829,6 +33993,54 @@ snapshots:
|
|||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
vue-macros@3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/boolean-prop': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/chain-call': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/common': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/config': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-emit': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-models': 3.1.2(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-prop': 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-props': 3.1.2(@vue-macros/reactivity-transform@3.1.2(vue@3.5.32(typescript@5.9.3)))(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-props-refs': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-render': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-slots': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/define-stylex': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/devtools': 3.1.2(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
'@vue-macros/export-expose': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/export-props': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/export-render': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/hoist-static': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/jsx-directive': 3.1.2(typescript@5.9.3)
|
||||
'@vue-macros/named-template': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/reactivity-transform': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/script-lang': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-block': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-component': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/setup-sfc': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-bind': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-emits': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/short-vmodel': 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
'@vue-macros/volar': 3.1.2(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3))
|
||||
unplugin: 2.3.11
|
||||
unplugin-combine: 2.3.0(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(unplugin@2.3.11)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))
|
||||
unplugin-vue-define-options: 3.1.2(vue@3.5.32(typescript@5.9.3))
|
||||
vue: 3.5.32(typescript@5.9.3)
|
||||
transitivePeerDependencies:
|
||||
- '@emnapi/core'
|
||||
- '@emnapi/runtime'
|
||||
- '@rspack/core'
|
||||
- '@vueuse/core'
|
||||
- esbuild
|
||||
- rolldown
|
||||
- rollup
|
||||
- typescript
|
||||
- vite
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
vue-macros@3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@vueuse/core@14.2.1(vue@3.5.32(typescript@5.9.3)))(esbuild@0.27.2)(rolldown@1.0.0-rc.16)(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@25.6.0)(esbuild@0.27.2)(jiti@2.6.1)(less@4.6.4)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.32(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 3.1.2(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(vue@3.5.32(typescript@5.9.3))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue