Skip to content

Commit

Permalink
[Robust] implement UI system and most everything it depends on. (#339)
Browse files Browse the repository at this point in the history
* Add `set opendream_unimplemented`

* Add weighted pick()

* It's uh, something

* Adds score and medal procs (#331)

Co-authored-by: ike709 <[email protected]>

* Fix PostIncrement/PostDecrement expressions

* Support for for-loops without initializer or incrementor (#332)

* Support for for-loops without initializer or incrementor

* Update OpenDreamRuntime.Tests/UnitTest1.cs

Co-authored-by: wixoa <[email protected]>

Co-authored-by: wixoa <[email protected]>

* Use StateRoot for UI root instead.

* Set control name in UpdateElementDescriptor()

* Fix ControlChild vert/horizontal being swapped

* Implement ControlWindow properly.

* Fix atom transform rendering

* Implemented most matrix operations (#333)

* Implemented most matrix operations

* fixed turn

* Specify startup branding in GameControllerOptions.

* Implement enough UI stuff to show the map.

* Make ControlChild children have expand set so that initial size of the splitter is correct-ish.

* Implement a bunch of stuff like DreamConnection to get stat panels working.

* Fix MsgUpdateStatPanels.ReadFromBuffer error

* Show time in stat panel.

For testing.

* Verbs and output work now.

* Implement alert()

* Implement most of input().

* Implement << output()

* Implement browse_rsc()

* Implement browse_rsc() and browse().

This means ControlBrowser works too now.

* Use a dictionary for MIME type mapping

* Clean up ControlBrowser a bit.

* Implement Topic(), refids.

* Set `net.tickrate` CVar instead of `IGameTiming.TickRate` directly.

This is important so that the config system can replicate the CVar correctly.

* Fix server Update() to only be PreEngine.

So that repeating commands and such don't run twice.

* Implement some more missing functions like oviewers().

* Implement winset().

I didn't test but I assume it works.

* Implement screenshots.

* Open browse() popups later to avoid initial about:blank page navigation.

* Implement JS output.

* Oops

* implement ref()

* Revert resource system back to master.

This fixes resource loading so it works and we can load into TG.

Also some misc fixes.

* Implement IconStates through icon_states (#346)

* Disable net.predict.

* More TestGame stuff I was messing around with.

* path fix for linux (#337)

Co-authored-by: mumencoder <[email protected]>

* Fix how delimiters are parsed within call arguments/switch cases

* Made OpenDreamServer output UTF-8 to the console (#352)

* Implement isicon() (#348)

* Implement isicon()

* Update OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs

Co-authored-by: wixoa <[email protected]>

Co-authored-by: wixoa <[email protected]>

* Implement cal()() FFI. (#355)

Man modern C# makes this so damn easy.

* Mentions the new wiki page in the readme (#354)

* Make `spawn()` parantheses optional
Apparently you can use `spawn` without any parentheses

* Add a default stat panel

* Set `usr` when calling `/mob.Login()` or `/mob.Logout()`

* Update submodule

* Associative lists will no longer be allocated for non-associative lists (#343)

* Associative lists will no longer be allocated for non-associative lists

* Update OpenDreamRuntime/Objects/DreamList.cs

Co-authored-by: Pieter-Jan Briers <[email protected]>

* Update OpenDreamRuntime/Objects/DreamList.cs

Co-authored-by: Pieter-Jan Briers <[email protected]>

* Cleanup

* wrapper

Co-authored-by: Pieter-Jan Briers <[email protected]>

* Some work into making the styling better.

* Implement menu bars.

* Fix map viewports missing mouse filter stop.

* Increase resource download timeout, clean code up a little.

CVars have been moved to shared.

* Remove cruft from code.dm

* Remove bad compile directive from .csproj file.

Co-authored-by: wixoaGit <[email protected]>
Co-authored-by: ike709 <[email protected]>
Co-authored-by: ike709 <[email protected]>
Co-authored-by: DamianX <[email protected]>
Co-authored-by: TiviPlus <[email protected]>
Co-authored-by: mumencoder <[email protected]>
Co-authored-by: mumencoder <[email protected]>
  • Loading branch information
8 people authored Sep 2, 2021
1 parent c20a918 commit ef9d8b5
Show file tree
Hide file tree
Showing 115 changed files with 4,946 additions and 1,114 deletions.
3 changes: 3 additions & 0 deletions Content.Client/ClientContentIoC.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using Content.Client.Input;
using Content.Client.Interface;
using Content.Client.Resources;
using Robust.Shared.IoC;

namespace Content.Client {
internal static class ClientContentIoC {
public static void Register() {
IoCManager.Register<IDreamInterfaceManager, DreamInterfaceManager>();
IoCManager.Register<DreamInterfaceManager, DreamInterfaceManager>();
IoCManager.Register<IDreamMacroManager, DreamMacroManager>();
IoCManager.Register<IDreamResourceManager, DreamResourceManager>();
}
}
}
1 change: 1 addition & 0 deletions Content.Client/Content.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
<ProjectReference Include="..\RobustToolbox\Lidgren.Network\Lidgren.Network.csproj" />
<ProjectReference Include="..\RobustToolbox\Robust.Client.CEF\Robust.Client.CEF.csproj" />
<ProjectReference Include="..\RobustToolbox\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
<ProjectReference Include="..\RobustToolbox\Robust.Shared\Robust.Shared.csproj" />
<ProjectReference Include="..\RobustToolbox\Robust.Client\Robust.Client.csproj" />
Expand Down
46 changes: 43 additions & 3 deletions Content.Client/EntryPoint.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
using System.Globalization;
using Content.Client.Interface;
using Content.Client.Rendering;
using Robust.Client;
using Content.Client.Resources;
using Robust.Client.CEF;
using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Shared;
using Robust.Shared.Configuration;
using Robust.Shared.ContentPack;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Timing;
using Robust.Shared.Utility;

namespace Content.Client {
public class EntryPoint : GameClient {
public class EntryPoint : GameClient
{
[Dependency]
private readonly IDreamInterfaceManager _dreamInterface = default!;
[Dependency]
private readonly IDreamResourceManager _dreamResource = default!;
[Dependency]
private readonly CefManager _cef = default!;

public override void Init() {
IComponentFactory componentFactory = IoCManager.Resolve<IComponentFactory>();
componentFactory.DoAutoRegistrations();
Expand All @@ -25,21 +37,49 @@ public override void Init() {
cast.ClientBeforeIoC?.Invoke();
}

IoCManager.Register<CefManager>();

IoCManager.BuildGraph();
IoCManager.InjectDependencies(this);

_cef.Initialize();

componentFactory.GenerateNetIds();

_dreamResource.Initialize();

// Load localization. Needed for some engine texts, such as the ones in Robust ViewVariables.
IoCManager.Resolve<ILocalizationManager>().LoadCulture(new CultureInfo("en-US"));

IoCManager.Resolve<IClyde>().SetWindowTitle("OpenDream");
IoCManager.Resolve<IUserInterfaceManager>().Stylesheet = DreamStylesheet.Make();

// Game logic runs all single threaded, disable prediction to reduce CPU load and lag.
var cfg = IoCManager.Resolve<IConfigurationManager>();
cfg.SetCVar(CVars.NetPredict, false);
}

public override void PostInit() {
IoCManager.Resolve<ILightManager>().Enabled = false;

IoCManager.Resolve<IOverlayManager>().AddOverlay(new DreamMapOverlay());
IoCManager.Resolve<IDreamInterfaceManager>().LoadDMF(new ResourcePath("/Game/interface.dmf")); //TODO: Don't hardcode interface.dmf
_dreamInterface.Initialize();
}

protected override void Dispose(bool disposing)
{
_dreamResource.Shutdown();
_cef.Shutdown();
}

public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs)
{
if (level == ModUpdateLevel.FramePostEngine)
{
_dreamInterface.FrameUpdate(frameEventArgs);

_cef.Update();
}
}
}
}
30 changes: 27 additions & 3 deletions Content.Client/Input/DreamCommandSystem.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
using Content.Shared.Input;
using Content.Client.Interface;
using Content.Shared.Input;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Network;

namespace Content.Client.Input {
class DreamCommandSystem : SharedDreamCommandSystem {
public void RunCommand(string command) {
//TODO: Local client commands (.quit, .winset, .screenshot, etc)
RaiseNetworkEvent(new CommandEvent(command));
string[] split = command.Split(" ");
string verb = split[0];

switch (verb) {
case ".quit":
IoCManager.Resolve<IClientNetManager>().ClientDisconnect(".quit used");
break;

case ".screenshot":
var interfaceMgr = IoCManager.Resolve<IDreamInterfaceManager>();
interfaceMgr.SaveScreenshot(split.Length == 1 || split[1] != "auto"); break;
default: {
if (split.Length > 1)
{
Logger.Error("Verb argument parsing is not implemented yet.");
return;
}

RaiseNetworkEvent(new CommandEvent(command));
break;
}
}
}

public void StartRepeatingCommand(string command) {
Expand Down
16 changes: 13 additions & 3 deletions Content.Client/Input/DreamMacroManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Robust.Shared.IoC;
using System;
using System.Collections.Generic;
using Robust.Shared.Log;
using Key = Robust.Client.Input.Keyboard.Key;

namespace Content.Client.Input {
Expand All @@ -28,6 +29,9 @@ public void LoadMacroSets(List<MacroSetDescriptor> macroSets) {
BoundKeyFunction function = new BoundKeyFunction(macro.Id);
KeyBindingRegistration binding = CreateMacroBinding(function, macro.Name);

if (binding == null)
continue;

context.AddFunction(function);
_inputManager.RegisterBinding(in binding);
_inputManager.SetInputCommand(function, InputCmdHandler.FromDelegate(_ => OnMacroPress(macro), _ => OnMacroRelease(macro)));
Expand All @@ -50,7 +54,7 @@ private void OnMacroPress(MacroDescriptor macro) {
commandSystem.RunCommand(macro.Command);
}
}

}

private void OnMacroRelease(MacroDescriptor macro) {
Expand All @@ -74,8 +78,14 @@ private KeyBindingRegistration CreateMacroBinding(BoundKeyFunction function, str
macroName = macroName.Replace("+REP", String.Empty);

//TODO: modifiers
var key = KeyNameToKey(macroName);
if (key == Key.Unknown)
{
Logger.Warning($"Unknown key: {macroName}");
return null;
}
return new KeyBindingRegistration() {
BaseKey = KeyNameToKey(macroName),
BaseKey = key,
Function = function
};
}
Expand Down Expand Up @@ -157,7 +167,7 @@ private static Key KeyNameToKey(string keyName) {
"SHIFT" => Key.Shift,
"CTRL" => Key.Control,
"ALT" => Key.Alt,
_ => throw new Exception("Invalid key name \"" + keyName + "\"")
_ => Key.Unknown
};
}
}
Expand Down
57 changes: 57 additions & 0 deletions Content.Client/Interface/BrowsePopup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using Content.Client.Interface.Controls;
using Content.Shared.Interface;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.IoC;

namespace Content.Client.Interface
{
class BrowsePopup {
public event Action Closed;

public ControlBrowser Browser;
public ControlWindow WindowElement;

private OSWindow _window;

public BrowsePopup(
DreamInterfaceManager manager,
string name,
System.Drawing.Size size,
IClydeWindow ownerWindow) {
WindowDescriptor popupWindowDescriptor = new WindowDescriptor(name, new() {
new ControlDescriptorMain("main") {
Size = size
},
new ControlDescriptorBrowser("browser") {
Size = size,
Anchor1 = new System.Drawing.Point(0, 0),
Anchor2 = new System.Drawing.Point(100, 100)
}
});

WindowElement = new ControlWindow(popupWindowDescriptor);
WindowElement.CreateChildControls(IoCManager.Resolve<DreamInterfaceManager>());

_window = WindowElement.CreateWindow();
_window.StartupLocation = WindowStartupLocation.CenterOwner;
_window.Owner = ownerWindow;
_window.Closed += OnWindowClosed;

Browser = (ControlBrowser)WindowElement.ChildControls[0];
}

public void Open() {
_window.Show();
// _window.Focus();
}

public void Close() {
_window.Close();
}

private void OnWindowClosed() {
Closed?.Invoke();
}
}}
144 changes: 144 additions & 0 deletions Content.Client/Interface/Controls/ControlBrowser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Web;
using Content.Shared.Interface;
using Content.Shared.Network.Messages;
using Robust.Client.CEF;
using Robust.Client.UserInterface;
using Robust.Shared.Console;
using Robust.Shared.ContentPack;
using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Network;
using Robust.Shared.Utility;

namespace Content.Client.Interface.Controls
{
class ControlBrowser : InterfaceControl
{
private static readonly Dictionary<string, string> FileExtensionMimeTypes = new Dictionary<string, string>
{
{ "html", "text/html" },
{ "htm", "text/html" },
{ "png", "image/png" },
{ "svg", "image/svg+xml" },
{ "jpeg", "image/jpeg" },
{ "jpg", "image/jpeg" },
{ "js", "application/javascript" },
{ "json", "application/json" },
{ "ttf", "font/ttf" },
{ "txt", "text/plain" }
};

[Dependency] private readonly IResourceManager _resourceManager = default!;
[Dependency] private readonly IClientNetManager _netManager = default!;

private ISawmill _sawmill = Logger.GetSawmill("opendream.browser");

private BrowserControl _webView;

public ControlBrowser(ControlDescriptor controlDescriptor, ControlWindow window)
: base(controlDescriptor, window)
{
IoCManager.InjectDependencies(this);
}

protected override Control CreateUIElement() {
_webView = new BrowserControl();

_webView.AddResourceRequestHandler(RequestHandler);
_webView.AddBeforeBrowseHandler(BeforeBrowseHandler);

return _webView;
}

public override void Output(string value, string jsFunction) {
if (jsFunction == null) return;

value = HttpUtility.UrlDecode(value);
value = value.Replace("\"", "\\\"");
_webView.ExecuteJavaScript(jsFunction + "(\"" + value + "\")");
}

public void SetFileSource(ResourcePath filepath, bool userData) {
_webView.Url = (userData ? "usr://" : "res://") + filepath;
}

private void BeforeBrowseHandler(BeforeBrowseContext context)
{
if (string.IsNullOrEmpty(_webView.Url))
return;

Uri oldUri = new Uri(_webView.Url);
Uri newUri = new Uri(context.Url);

if (newUri.Scheme == "byond" || (newUri.AbsolutePath == oldUri.AbsolutePath && newUri.Query != String.Empty)) {
context.DoCancel();

var msg = _netManager.CreateNetMessage<MsgTopic>();
msg.Query = newUri.Query;
_netManager.ClientSendMessage(msg);
}
}

private void RequestHandler(RequestHandlerContext context)
{
Uri newUri = new Uri(context.Url);

if (newUri.Scheme == "usr")
{
Stream stream;
HttpStatusCode status;
var path = new ResourcePath(newUri.AbsolutePath);
try
{
stream = _resourceManager.UserData.OpenRead(path);
status = HttpStatusCode.OK;
}
catch (FileNotFoundException)
{
stream = Stream.Null;
status = HttpStatusCode.NotFound;
}
catch (Exception e)
{
_sawmill.Error($"Exception while loading file from usr://:\n{e}");
stream = Stream.Null;
status = HttpStatusCode.InternalServerError;
}

if (!FileExtensionMimeTypes.TryGetValue(path.Extension, out var mimeType))
mimeType = "application/octet-stream";

context.DoRespondStream(stream, mimeType, status);
return;
}
}
}

public sealed class BrowseWinCommand : IConsoleCommand
{
public string Command => "browsewin";
public string Description => "";
public string Help => "";

public void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (args.Length != 1)
{
shell.WriteError("Incorrect amount of arguments! Must be a single one.");
return;
}

var parameters = new BrowserWindowCreateParameters(1280, 720)
{
Url = args[0]
};

var cef = IoCManager.Resolve<CefManager>();
cef.CreateBrowserWindow(parameters);
}
}
}
Loading

0 comments on commit ef9d8b5

Please sign in to comment.