var container = FindNode("Lastground"); if (container == null) return; var existing = container.GetNodeOrNull("Live2DTestModel"); if (existing != null) return; var model = Cthangover.Live2D.Cubism.Services.Live2DService.CreateModel(container, "models/runtime/ren.model3.json", "Live2DTestModel", "live2d_test"); var dragPanelParent = FindNode("ModBeforeUIPanel") ?? container; var dragPanel = new Godot.ColorRect(); dragPanel.Name = "Live2DDragPanel"; dragPanel.MouseFilter = Godot.Control.MouseFilterEnum.Stop; dragPanel.Color = new Godot.Color(0, 1f, 0, 0f); dragPanel.Size = new Godot.Vector2(400, 400); dragPanel.AnchorLeft = 0.5f; dragPanel.AnchorRight = 0.5f; dragPanel.AnchorTop = 0.5f; dragPanel.AnchorBottom = 0.5f; dragPanel.OffsetLeft = -200f; dragPanel.OffsetRight = 200f; dragPanel.OffsetTop = -200f; dragPanel.OffsetBottom = 200f; dragPanelParent.AddChild(dragPanel); bool dragging = false; float mouseStartX = 0f; float mouseStartY = 0f; float baseValueX = 0f; float baseValueY = 0f; var targetParamX = model.FindParameter("ParamAngleX"); var targetParamY = model.FindParameter("ParamAngleY"); dragPanel.GuiInput += (Godot.InputEvent e) => { if (e is Godot.InputEventMouseButton mb) { if (mb.ButtonIndex == Godot.MouseButton.Left) { if (mb.Pressed) { dragging = true; mouseStartX = mb.GlobalPosition.X; mouseStartY = mb.GlobalPosition.Y; baseValueX = targetParamX?.Value ?? 0f; baseValueY = targetParamY?.Value ?? 0f; } else { if (dragging) { dragging = false; } } } } if (dragging && e is Godot.InputEventMouseMotion mm) { var deltaX = (mm.GlobalPosition.X - mouseStartX) / 30f; var deltaY = (mm.GlobalPosition.Y - mouseStartY) / 30f; if (targetParamX != null) { var newX = Math.Clamp(baseValueX + deltaX, targetParamX.MinimumValue, targetParamX.MaximumValue); model.SetLiveParameter("ParamAngleX", newX); } if (targetParamY != null) { var newY = Math.Clamp(baseValueY + deltaY, targetParamY.MinimumValue, targetParamY.MaximumValue); model.SetLiveParameter("ParamAngleY", newY); } } };