add console panel, still have scroll problem

This commit is contained in:
2022-07-21 00:23:20 +08:00
parent 7cdcaf1e2f
commit 2040afa34a
22 changed files with 558 additions and 119 deletions

View File

@ -7,28 +7,43 @@ public class GameRoot : Node {
StalkerCore mStalkerCore;
public override void _Ready() {
mMenuManager = GetNode<MenuManager>("UILayer/MenuManager");
mMenuManager = GetNode<MenuManager>("MenuManager");
mStalkerCore = GetNode<StalkerCore>("StalkerCore");
mMenuManager.Connect(nameof(MenuManager.SetMouseCapture), this, nameof(Proc_MenuManager_SetMouseCapture));
//mMenuManager.Connect(nameof(MenuManager.SetMouseCapture), this, nameof(Proc_MenuManager_SetMouseCapture));
mMenuManager.Connect(nameof(MenuManager.ExitGame), this, nameof(Proc_MenuManager_ExitGame));
// raw executing this func
// to set proper status
Proc_MenuManager_SetMouseCapture();
//// raw executing this func
//// to set proper status
//Proc_MenuManager_SetMouseCapture();
BallanceStalkerCore.StalkerManager.Singleton.EventControllerChanged += Proc_StalkerManager_EventControllerChanged;
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.None);
}
private void Proc_StalkerManager_EventControllerChanged(BallanceStalkerCore.EventControllerSource obj) {
switch (obj) {
case BallanceStalkerCore.EventControllerSource.None:
Input.SetMouseMode(Input.MouseMode.Captured);
break;
case BallanceStalkerCore.EventControllerSource.Menu:
case BallanceStalkerCore.EventControllerSource.Console:
case BallanceStalkerCore.EventControllerSource.Chat:
Input.SetMouseMode(Input.MouseMode.Visible);
break;
}
}
public override void _Input(InputEvent @event) {
}
private void Proc_MenuManager_SetMouseCapture() {
if (mMenuManager.Visible) {
Input.SetMouseMode(Input.MouseMode.Visible);
} else {
Input.SetMouseMode(Input.MouseMode.Captured);
}
}
//private void Proc_MenuManager_SetMouseCapture() {
// if (mMenuManager.Visible) {
// Input.SetMouseMode(Input.MouseMode.Visible);
// } else {
// Input.SetMouseMode(Input.MouseMode.Captured);
// }
//}
private void Proc_MenuManager_ExitGame() {
GetTree().Notification(MainLoop.NotificationWmQuitRequest);
}

View File

@ -0,0 +1,98 @@
using Godot;
using System;
using System.Collections.Generic;
public enum LabelConsoleMessageType {
Normal,
Highlight,
Error
}
public class ConsolePanel : Control {
private LineEdit mCmdInput;
private ScrollContainer mScrollbar;
private VBoxContainer mMessageContainer;
private PackedScene mTemplateLabelConsole;
private Queue<LabelConsole> mMessageQueue = new Queue<LabelConsole>();
private readonly int QUEUE_MAX_SIZE = 100;
public override void _Ready() {
mTemplateLabelConsole = ResourceLoader.Load<PackedScene>("res://scenes/user_interface/LabelConsole.tscn");
mCmdInput = GetNode<LineEdit>("CommandInput");
mScrollbar = GetNode<ScrollContainer>("ScrollSet/Scrollbar");
mMessageContainer = GetNode<VBoxContainer>("ScrollSet/Scrollbar/MessageContainer");
mCmdInput.Connect("text_entered", this, nameof(Proc_LineEdit_TextEntered));
BallanceStalkerCore.StalkerManager.Singleton.EventControllerChanged += Proc_StalkerManager_EventControllerChanged;
}
private void Proc_StalkerManager_EventControllerChanged(BallanceStalkerCore.EventControllerSource obj) {
if (obj == BallanceStalkerCore.EventControllerSource.Chat) {
this.Visible = true;
mCmdInput.GrabFocus();
} else if (obj == BallanceStalkerCore.EventControllerSource.Console) {
// same process of chat
// but only add a extra preset charcater in cmd input
this.Visible = true;
mCmdInput.Text = "/";
mCmdInput.CaretPosition = 1;
mCmdInput.GrabFocus();
} else {
this.Visible = false;
}
}
public override void _Input(InputEvent @event) {
if (!this.Visible) return;
if (@event.IsActionPressed("ballance_esc")) {
// clean input
mCmdInput.Text = "";
// back to camera
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.None);
// mark handled to prevent loop call
GetTree().SetInputAsHandled();
}
}
private void AddMessage(string strl, LabelConsoleMessageType t) {
LabelConsole target;
if (mMessageQueue.Count > QUEUE_MAX_SIZE) {
// popup last item and remove it from scene first
target = mMessageQueue.Dequeue();
mMessageContainer.RemoveChild(target);
} else {
target = mTemplateLabelConsole.Instance<LabelConsole>();
}
// add into scene and queue
mMessageQueue.Enqueue(target);
mMessageContainer.AddChild(target);
// set text
target.SetText(strl, t);
// scroll to bottom
//var bar = mScrollbar.GetVScrollbar();
//bar.Value = bar.MaxValue;
mScrollbar.ScrollVertical = (int)mScrollbar.GetVScrollbar().MaxValue;
}
private void Proc_LineEdit_TextEntered(string new_strl) {
if (new_strl != string.Empty) {
// todo: finish cmd parse
if (new_strl.StartsWith("/")) {
AddMessage(new_strl, LabelConsoleMessageType.Highlight);
} else if (new_strl.StartsWith("!")) {
AddMessage(new_strl, LabelConsoleMessageType.Error);
} else {
AddMessage(new_strl, LabelConsoleMessageType.Normal);
}
// clean cmd
mCmdInput.Text = "";
}
}
}

View File

@ -12,8 +12,8 @@ public class MenuManager : Control {
About
}
[Signal]
public delegate void SetMouseCapture();
//[Signal]
//public delegate void SetMouseCapture();
[Signal]
public delegate void ExitGame();
@ -28,18 +28,31 @@ public class MenuManager : Control {
mMenuMain.Connect(nameof(MenuMain.MenuMain_GotoPage), this, nameof(Proc_MenuMain_GotoPage));
mMenuMain.Connect(nameof(MenuMain.MenuMain_Back), this, nameof(Proc_MenuMain_Back));
mMenuMain.Connect(nameof(MenuMain.MenuMain_Exit), this, nameof(Proc_MenuMain_Exit));
BallanceStalkerCore.StalkerManager.Singleton.EventControllerChanged += Proc_StalkerManager_EventControllerChanged;
}
private void Proc_StalkerManager_EventControllerChanged(BallanceStalkerCore.EventControllerSource obj) {
if (obj == BallanceStalkerCore.EventControllerSource.Menu) {
this.Visible = true;
} else {
this.Visible = false;
}
}
public override void _Input(InputEvent @event) {
if (Input.IsActionJustPressed("ballance_esc")) {
if (!this.Visible) return;
if (@event.IsActionPressed("ballance_esc")) {
if (mCurrentPage == MenuPage.Main) {
// we are in main menu, we need switch visible
this.Visible = !this.Visible;
EmitSignal(nameof(SetMouseCapture));
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.None);
} else {
// otherwise, back from sub menu
RefreshMenuPage(MenuPage.Main);
}
// mark handled to prevent loop call
GetTree().SetInputAsHandled();
}
}
@ -52,8 +65,7 @@ public class MenuManager : Control {
RefreshMenuPage(menu_type);
}
private void Proc_MenuMain_Back() {
this.Visible = false;
EmitSignal(nameof(SetMouseCapture));
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.None);
}
private void Proc_MenuMain_Exit() {
EmitSignal(nameof(ExitGame));

View File

@ -3,22 +3,26 @@ using System;
// Reference: https://github.com/godotengine/godot-demo-projects/blob/master/3d/waypoints
public class PlayerBall : Spatial {
public enum ShadowBallType : UInt32 {
Stone,
Wood,
Paper
}
public class ShadowBall : Spatial {
static readonly float MARGIN = 16f; // set it as half of arrow image
static readonly float TEXT_RADIUS = MARGIN + 16f;
public string Playername {
get { return mPlayername.Text; }
set { mPlayername.Text = value; }
}
public bool AlwaysTracking { get; set; }
private bool mAlwaysTracking = true;
Control mCtl2D;
Spatial mTextArchor;
Spatial mTextArchor, mModelArchor;
TextureRect mPlayerArrow;
Label mPlayername;
Camera mSpectatorCamera = null;
MeshInstance mMeshWood, mMeshStone, mMeshPaper;
ShadowBallType mOldState = ShadowBallType.Wood;
public override void _Ready() {
mCtl2D = GetNode<Control>("TextArchor/Ctl2D");
@ -26,8 +30,45 @@ public class PlayerBall : Spatial {
mPlayerArrow = GetNode<TextureRect>("TextArchor/Ctl2D/PlayerArrow");
mPlayername = GetNode<Label>("TextArchor/Ctl2D/Playername");
AlwaysTracking = true;
Playername = "";
mModelArchor = GetNode<Spatial>("ModelArchor");
mMeshWood = GetNode<MeshInstance>("ModelArchor/Ball_Wood");
mMeshStone = GetNode<MeshInstance>("ModelArchor/Ball_Stone");
mMeshPaper = GetNode<MeshInstance>("ModelArchor/Ball_Paper");
}
public void SetPlayerName(string new_name) {
mPlayername.Text = new_name;
}
public void SetBallState(Vector3 pos, Quat quad, ShadowBallType btype) {
this.Translation = pos;
mModelArchor.Rotation = quad.GetEuler();
if (mOldState != btype) {
switch (mOldState) {
case ShadowBallType.Stone:
mMeshStone.Visible = false;
break;
case ShadowBallType.Wood:
mMeshWood.Visible = false;
break;
case ShadowBallType.Paper:
mMeshPaper.Visible = false;
break;
}
switch (btype) {
case ShadowBallType.Stone:
mMeshStone.Visible = true;
break;
case ShadowBallType.Wood:
mMeshWood.Visible = true;
break;
case ShadowBallType.Paper:
mMeshPaper.Visible = true;
break;
}
mOldState = btype;
}
}
public override void _Process(float delta) {
@ -63,7 +104,7 @@ public class PlayerBall : Spatial {
//var distance = camera_translation.DistanceTo(parent_translation);
//mCtl2D.Modulate.a = Godot.Mathf.Clamp(RangeLerp range_lerp(distance, 0, 2, 0, 1), 0, 1);
if (!AlwaysTracking) {
if (!mAlwaysTracking) {
// For non-sticky waypoints, we don't need to clamp and calculate
// the position if the waypoint goes off screen.
mCtl2D.RectPosition = unprojected_position;
@ -182,11 +223,6 @@ public class PlayerBall : Spatial {
}
//private static float AngelDiff(float from, float to) {
// var diff = (to - from) % Mathf.Tau;
// return ((2.0f * diff) % Mathf.Tau) - diff;
//}
private static float RangeLerp(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * (value - istart) / (istop - istart);
}

View File

@ -2,70 +2,43 @@ using Godot;
using System;
using System.Collections.Generic;
public class ShadowBall {
public UInt32 mIdentifier;
public string mName;
public PlayerBall mGodotNode;
}
public class ShadowBallManager : Spatial {
private Dictionary<UInt32, ShadowBall> mBallDict = new Dictionary<UInt32, ShadowBall>();
private Dictionary<Guid, ShadowBall> mBallDict = new Dictionary<Guid, ShadowBall>();
private PackedScene mTemplateShadowBall;
// Called when the node enters the scene tree for the first time.
public override void _Ready() {
mTemplateShadowBall = ResourceLoader.Load<PackedScene>("res://scenes/stages/PlayerBall.tscn");
mTemplateShadowBall = ResourceLoader.Load<PackedScene>("res://scenes/stages/ShadowBall.tscn");
int len = 10;
Quat quad = Quat.Identity;
Vector3 vec = new Vector3(0, 0, 0);
for (int x = 0; x < len; x++) {
for (int y = 0; y < len; y++) {
AddBall((uint)(x * len + y), $"Swung0x{x * len + y}");
vec.x = x * 50;
vec.z = y * 50;
SetBallState((uint)(x * len + y), vec, quad);
}
}
public Guid AddBall() {
var guid = Guid.NewGuid();
var instance = mTemplateShadowBall.Instance<ShadowBall>();
AddChild(instance);
mBallDict.Add(guid, instance);
return guid;
}
public void SetBallName(Guid ballid, string new_name) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
entity.SetPlayerName(new_name);
}
}
// // Called every frame. 'delta' is the elapsed time since the previous frame.
// public override void _Process(float delta)
// {
//
// }
public void AddBall(UInt32 ballid, string name) {
public void SetBallState(Guid ballid, Vector3 pos, Quat quad, ShadowBallType btype) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
// update old entity for alternative
entity.mName = name;
entity.mGodotNode.Playername = name;
} else {
entity = new ShadowBall() {
mIdentifier = ballid,
mName = name,
mGodotNode = mTemplateShadowBall.Instance<PlayerBall>()
};
mBallDict.Add(ballid, entity);
AddChild(entity.mGodotNode);
entity.mGodotNode.Playername = entity.mName;
entity.SetBallState(pos, quad, btype);
}
}
public void SetBallState(UInt32 ballid, Vector3 pos, Quat quad) {
public void RemoveBall(Guid ballid) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
entity.mGodotNode.Translation = pos;
entity.mGodotNode.Rotation = quad.GetEuler();
}
}
public void RemoveBall(UInt32 ballid) {
if (mBallDict.TryGetValue(ballid, out ShadowBall entity)) {
RemoveChild(entity.mGodotNode);
entity.mGodotNode.QueueFree();
RemoveChild(entity);
entity.QueueFree();
mBallDict.Remove(ballid);
}
}
}

View File

@ -1,49 +1,85 @@
using Godot;
using System;
public class StalkerCamera : Spatial
{
Spatial originFreeCam;
Camera freeCam;
public class StalkerCamera : Spatial {
Spatial mFreeCamOrigin = null, mSpecCam = null, mStaticCameraOrigin = null, mStaticCameraTracking = null;
Camera mFreeCam;
private static float BASIC_MOVEMENT = 0.2f;
private static float STATIC_MOVEMENT = 10f;
bool mEnableCamera = false;
object lockMotionMouse = new object();
Vector2 motionMouse = new Vector2(0, 0);
int movementScale = 1;
public override void _Ready() {
freeCam = GetNode<Camera>("FreeCam");
originFreeCam = GetNode<Spatial>("FreeCamOrigin");
mFreeCam = GetNode<Camera>("FreeCam");
mFreeCamOrigin = GetNode<Spatial>("FreeCamOrigin");
mStaticCameraOrigin = GetNode<Spatial>("StaticCamOrigin");
mStaticCameraTracking = GetNode<Spatial>("StaticCamOrigin/StaticCamTracking");
mSpecCam = null;
//Input.SetMouseMode(Input.MouseMode.Captured);
BallanceStalkerCore.StalkerManager.Singleton.EventControllerChanged += Proc_StalkerManager_EventControllerChanged;
}
private void Proc_StalkerManager_EventControllerChanged(BallanceStalkerCore.EventControllerSource obj) {
mEnableCamera = obj == BallanceStalkerCore.EventControllerSource.None;
}
public override void _Process(float delta) {
if (Input.GetMouseMode() != Input.MouseMode.Captured) return;
if (!mEnableCamera) return;
Vector3 motion3d = new Vector3(0, 0, 0);
if (Input.IsActionPressed("ballance_forward")) motion3d.z -= 1f;
if (Input.IsActionPressed("ballance_backward")) motion3d.z += 1f;
if (Input.IsActionPressed("ballance_left")) motion3d.x -= 1f;
if (Input.IsActionPressed("ballance_right")) motion3d.x += 1f;
if (Input.IsActionPressed("ballance_down")) motion3d.y -= 1f;
if (Input.IsActionPressed("ballance_up")) motion3d.y += 1f;
freeCam.Translate(motion3d * (BASIC_MOVEMENT * movementScale));
if (mSpecCam is null) {
Vector3 motion3d = new Vector3(0, 0, 0);
if (Input.IsActionPressed("ballance_forward")) motion3d.z -= 1f;
if (Input.IsActionPressed("ballance_backward")) motion3d.z += 1f;
if (Input.IsActionPressed("ballance_left")) motion3d.x -= 1f;
if (Input.IsActionPressed("ballance_right")) motion3d.x += 1f;
if (Input.IsActionPressed("ballance_down")) motion3d.y -= 1f;
if (Input.IsActionPressed("ballance_up")) motion3d.y += 1f;
Vector2 copiedMotion2d;
lock (lockMotionMouse) {
copiedMotion2d = motionMouse;
motionMouse = new Vector2(0, 0);
mFreeCam.Translate(motion3d * (BASIC_MOVEMENT * movementScale));
Vector2 copiedMotion2d;
lock (lockMotionMouse) {
copiedMotion2d = motionMouse;
motionMouse = new Vector2(0, 0);
}
var viewport_base_size = GetViewport().GetSizeOverride() > Vector2.Zero ? GetViewport().GetSizeOverride() : GetViewport().Size;
float window_x = viewport_base_size.x;
Vector3 camRot = mFreeCam.Rotation;
camRot.x = Mathf.Clamp(camRot.x - copiedMotion2d.y * 2 / window_x, -90f, 90f);
camRot.y = camRot.y - copiedMotion2d.x * 2 / window_x;
camRot.z = 0;
mFreeCam.Rotation = camRot;
} else {
mStaticCameraOrigin.Translation = mSpecCam.Translation;
mFreeCam.Transform = mFreeCam.Transform.InterpolateWith(mStaticCameraTracking.Transform, STATIC_MOVEMENT);
}
float window_x = GetViewport().GetVisibleRect().Size.x;
Vector3 camRot = freeCam.Rotation;
camRot.x = Mathf.Clamp(camRot.x - copiedMotion2d.y * 2 / window_x, -90f, 90f);
camRot.y = camRot.y - copiedMotion2d.x * 2 / window_x;
camRot.z = 0;
freeCam.Rotation = camRot;
}
public override void _Input(InputEvent @event) {
if (Input.GetMouseMode() != Input.MouseMode.Captured) return;
if (!mEnableCamera) return;
if (@event.IsActionPressed("ballance_esc")) {
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.Menu);
// mark handled to prevent loop call
GetTree().SetInputAsHandled();
}
if (@event.IsActionPressed("ballance_cmd")) {
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.Console);
// mark handled to prevent loop call
GetTree().SetInputAsHandled();
}
if (@event.IsActionPressed("ballance_chat")) {
BallanceStalkerCore.StalkerManager.Singleton.SetEventController(BallanceStalkerCore.EventControllerSource.Chat);
// mark handled to prevent loop call
GetTree().SetInputAsHandled();
}
// mouse wheel
if (@event is InputEventMouseButton) {
@ -67,4 +103,15 @@ public class StalkerCamera : Spatial
}
}
public void SetTrackingTarget(Spatial target) {
if (target is null) {
if (!(mSpecCam is null)) {
// shift off from a player archor, we need move free cam origin to target
mFreeCamOrigin.Translation = mSpecCam.Translation;
}
}
// set cam origin
mSpecCam = target;
}
}

View File

@ -7,15 +7,49 @@ using System.Threading.Tasks;
namespace BallanceStalkerCore {
public enum EventControllerSource {
/// <summary>
/// Default statue. It mean that we are now in camera mode.
/// </summary>
None,
/// <summary>
/// Menu take control of event input
/// </summary>
Menu,
/// <summary>
/// Console panel now take control of event input.
/// </summary>
Console,
/// <summary>
/// it is same as console, the only different is preset character
/// </summary>
Chat
}
public class StalkerManager {
public static StalkerManager Singleton = new StalkerManager();
private StalkerManager() {
mEventController = EventControllerSource.None;
mLogger = new LogManager();
mBmmoClient = new BmmoClient(mLogger);
}
public event Action<EventControllerSource> EventControllerChanged;
private EventControllerSource mEventController;
public BmmoClient mBmmoClient;
public LogManager mLogger;
public void SetEventController(EventControllerSource src) {
if (mEventController != src) {
mEventController = src;
}
EventControllerChanged?.Invoke(src);
}
public EventControllerSource GetEventController() {
return mEventController;
}
}
}

View File

@ -0,0 +1,38 @@
using Godot;
using System;
public class LabelConsole : Control {
Label mRealLabel;
// Called when the node enters the scene tree for the first time.
public override void _Ready() {
mRealLabel = GetNode<Label>("RealLabel");
mRealLabel.Connect("item_rect_changed", this, nameof(Proc_Label_ItemRectChanged));
}
public void SetText(string strl, LabelConsoleMessageType t) {
mRealLabel.Text = strl;
switch (t) {
case LabelConsoleMessageType.Normal:
mRealLabel.Modulate = Colors.White;
break;
case LabelConsoleMessageType.Highlight:
mRealLabel.Modulate = Colors.Yellow;
break;
case LabelConsoleMessageType.Error:
mRealLabel.Modulate = Colors.OrangeRed;
break;
}
}
private void Proc_Label_ItemRectChanged() {
this.RectMinSize = new Vector2(0, (mRealLabel.GetLineHeight() + mRealLabel.GetConstant("line_spacing")) * mRealLabel.GetLineCount());
}
// // Called every frame. 'delta' is the elapsed time since the previous frame.
// public override void _Process(float delta)
// {
//
// }
}