ZScript "Standard Library" - Brainstorming

Post your example zscripts/ACS scripts/etc here.

Re: ZScript "Standard Library" - Brainstorming

Postby Nash » Fri Mar 24, 2017 7:53 pm

ZZYZX wrote:Hello so I made this https://github.com/jewalky/zgui

You can use it like so:
Code: Select allExpand view
class Doom3Element : Element
{
   TextureID mMouseCursor;
   
   override void OnCreate()
   {
      mRect = Rect.FromXYWH(0, 0, Screen.GetWidth(), Screen.GetHeight());
      mScale = 2;
   
      mMouseCursor = TexMan.CheckForTexture("graphics/D3Mouse.png", TexMan.Type_Any);
      AddChild(new('Doom3Doom').Init());
   }

   override void Draw()
   {
      Drawer d = GetDrawer();
      vector2 mouse = GetMouseXY();
      d.DrawTexture(mMouseCursor, false, mouse.x, mouse.y);
   }
}

class Doom3Menu : ListMenu
{
   Element e;

   override void Init(Menu parent, ListMenuDescriptor desc)
   {
      Super.Init(parent, desc);
      DontDim = true;
      
      e = new('Doom3Element').Init();
      e.OnCreate();
   }

   override bool OnUIEvent(UiEvent ev)
   {
      if (e) return e.OnProcessUi(ev);
      return false;
   }
   
   override bool OnInputEvent(InputEvent ev)
   {
      if (e) return e.OnProcessInput(ev);
      return false;
   }

   override void Drawer()
   {
      if (e) e.OnDraw();
   }

   override void Ticker()
   {
      if (e) e.OnTick();
   }
}

What it does: it allows you to have a WM-style hierarchy of Elements with automatic scaling, clipping, text align and wrapping.
Each Element can have a position inside the parent Element (mRect field), and scale of child elements (mScale field). The scale also affects perceived width/height of the Element (the client rect).
Topmost Element has mParent=null which means that it's using the real screen coordinates and scale of 1.0.

Functions exposed to the user are these:
Code: Select allExpand view
   virtual void OnCreate()
   {
      
   }
   
   virtual bool Process(ElementEvent ev)
   {
      return false;
   }
   
   virtual void Tick()
   {
      //
   }
   
   virtual void Draw()
   {
      //
   }

The preferred way of constructing Elements is calling "new ('Element').Init()", for example. That automatically sets certain fields to the initial values, otherwise you might end up with a wild null pointer error.
Unobviously enough, OnCreate is actually called when you add a child element, on the child. For a root element, you have to call OnCreate manually or it won't get a chance to initialize.

You can draw things by receiving an instance of Drawer class:
Code: Select allExpand view
Drawer d = GetDrawer();
And then using it's methods to draw things as opposed to directly using Screen.
Alternatively, you can instantiate a drawer by using
Code: Select allExpand view
Drawer d = Drawer.Create(self);
or even
Code: Select allExpand view
Drawer d = Drawer.CreateMod('Drawer', self);
The latter option is for custom Drawer classes if you want to do some fancy stuff.

Also, the system doesn't care about your input/rendering backend — you can provide OnProcessUi/OnProcessInput/OnTick by an event handler, and OnDraw by DrawPowerup (I blame Graf for consistently removing any ways to draw anything while playing the game and providing no alternative), or you can do all this in a menu.
The system is able to receive mouse input both from UiEvent and InputEvent — the elements will receive an uniform ElementEvent anyway. This means that it transparently supports both enabled and disabled mouse in menus.
ElementEvent is the same as UiEvent, except there is no information about pressed modifier keys (yet?)
Also, you can receive the current mouse coordinates relative to the current element (including all scaling) by using GetMouseXY() — which returns a vector2, see the example.

What it doesn't have yet is setting arbitrary clipping values in a Drawer. That'll be added eventually.
Added, actually.

The system is kinda new and untested, pls report bugs if anyone is actually going to use this.



ZZYZX: That needs to be on its own thread, and a simple user-runnable example please! Sounds awesome.
User avatar
Nash
Nash Muhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Postby Major Cooke » Fri Mar 24, 2017 8:23 pm

No it doesn't need it's own thread, this is perfect. He's giving it over here for ease of use in a library.
User avatar
Major Cooke
Slaughterer of Sewers
 
Joined: 28 Jan 2007
Discord: Major Cooke#0846

Re: ZScript "Standard Library" - Brainstorming

Postby Nash » Tue Mar 28, 2017 5:52 pm

Just an idea at this point, jotting it down so it doesn't get lost...

A replacement for ACS HudMessageOnActor.

Code: Select allExpand view

Vector2 ProjectToScreen
(Vector3 worldPos)
{
    Vector2 screenPos;
    return screenPos;
}

struct FDeproject
{
    Vector3 worldPos;
    Vector3 worldAng;
}

FDeproject DeprojectToWorld(Vector2 screenPos)
{
    FDeproject w;
    return w;
}


Method naming convention borrowed from Unreal Engine

These would most probably be status bar methods, except there's one problem... status bars are UI and DeprojectToWorld needs to be play because it will affect the world. I'm not sure how to solve this yet.

Also the pinhole projection calculations aren't in yet, I just prototyped these quickly in Notepad++ :V
User avatar
Nash
Nash Muhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Postby ZZYZX » Tue Mar 28, 2017 7:45 pm

I think this should be native and based on the active renderer, in Screen or StatusBar class. Probably sbar, since active statusbar affects viewport size.
Also, it probably should return a vector3 with -1..1 coordinates where 0 is the center of the screen, and Z coordinate would be the distance from the screen plane.

Might try making a PR later, but better if done by someone who knows the renderer (dp, for example).

We don't want to repeat the story with ACS misdetecting the renderer or proportions.
Last edited by ZZYZX on Wed Mar 29, 2017 2:18 am, edited 1 time in total.
User avatar
ZZYZX
le chat du rabbin
 
Joined: 14 Oct 2012
Location: Ukraine

Re: ZScript "Standard Library" - Brainstorming

Postby Nash » Wed Mar 29, 2017 12:04 am

ZZYZX wrote:I think this should be native and based on the active renderer


Agreed. The projection is vastly different between software Y-sheering and real 3D in OpenGL, so the engine is a better place to take care of that. There's also the issue of making the projections look correct in VR headsets, which user scripting just cannot resolve. It has to be done at the drawer-level.
User avatar
Nash
Nash Muhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Postby ZZYZX » Wed Mar 29, 2017 2:18 am

There's also the polygonal software renderer, now officially in GZDoom :D
Which detects as software, but is actually true 3D.

Also, for "deprojection" the renderer needs to return two values: horizontal and vertical effective FOV in relation to the visible area.
Knowing horizontal and vertical FOV, you can interpolate angles and calculate direction based on coordinates.

https://www.youtube.com/watch?v=ZB3Gj7CGjF8
Here I'm using GetScreenWidth/GetScreenHeight for aspect ratio, and assume vertical FOV to be ~67.5 (+33.75 above center, -33.75 below center), and 67.5*aspect for horizontal FOV (-45 to +45 for 4:3, -60 to +60 for 16:9).

Otherwise deprojection might as well simply return a vector3 pointing in the right direction based on the above data, this wouldn't be as universal (screen size wise), but works in most cases.
Just to clarify, I want the stuff to be returned as angles and -1..1 because this way it works with any size (of the same aspect ratio that is).
User avatar
ZZYZX
le chat du rabbin
 
Joined: 14 Oct 2012
Location: Ukraine

Re: ZScript "Standard Library" - Brainstorming

Postby Nash » Thu Mar 30, 2017 7:51 pm

Crazy idea (and posting because I /do/ plan to use ZGUI:

Use Fill at the low level to create vector-ey widgets that can be exposed to high level methods. >8D Or event fonts?!?! OMG


EDIT: Ahhh Fill is a BaseStatusBar method, not Screen. Well scratch that idea then

Would have loved to at least make buttons and sliders and simple widgets without providing rasterized graphics at any rate
User avatar
Nash
Nash Muhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Postby ZZYZX » Thu Mar 30, 2017 8:21 pm

This is possible using Dim, I believe.
User avatar
ZZYZX
le chat du rabbin
 
Joined: 14 Oct 2012
Location: Ukraine

Re: ZScript "Standard Library" - Brainstorming

Postby Nash » Thu Mar 30, 2017 11:53 pm

I just remembered, there's Screen.Clear too. Maybe I'll try make some buttons with that.
User avatar
Nash
Nash Muhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Postby Nash » Sun Apr 02, 2017 5:11 am

ZZYZX can you make a runnable example of ZUI please... some people learn faster by runnable examples (I learned most of my EventHandler stuff from your ZSDemo.pk3 you posted).
User avatar
Nash
Nash Muhandes
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia

Re: ZScript "Standard Library" - Brainstorming

Postby Graf Zahl » Sun Apr 02, 2017 6:32 am

ZZYZX wrote:This is possible using Dim, I believe.



Fill is just a wrapper around Dim with coordinate transformation.
User avatar
Graf Zahl
Lead GZDoom Developer
 
Joined: 19 Jul 2003
Location: Germany

Re: ZScript "Standard Library" - Brainstorming

Postby ZZYZX » Sun Apr 02, 2017 7:13 am

I'll make a runnable example as soon as I understand why the hell half of the events goes to MenuEvent instead of OnUIEvent.
Actually, I might make it even without that, but it's really bad for certain complex UI things.

edit: okkkk take this http://www.mediafire.com/file/5bu5vclsl ... xample.pk3
Screenshot: http://imgur.com/a/lwf9A
This is a simple example of implementing your own GUI from scratch.
The scale of everything is specified in OnCreate of MMenuElement.
Note: use 2.5 devbuild.

Also, unless it's possible to prevent translation of UiEvents into MenuEvents, I'll probably have to add another input function to Element that'd take menu events and pretend they are instant UI keydown+keyup of specified key.

Oh, and if it looks too complicated or something...
Well, if you are simply making a statusbar (or RenderOverlay), you need only the first two calls from MMenuElement.OnCreate (set mRect, set mScale) and a Draw method. That's all.
I mainly split it in three classes so that I could have mouse, complex input and fancy hover animation.

Regarding mouse input: mouse WITHOUT m_use_mouse is only possible in fullscreen and is kinda half supported.
However, there's a large problem that I can't get my own mouse cursor to draw if m_use_mouse is enabled (it always draws the default Windows/SDL cursor). How to fix that? @Graf?
User avatar
ZZYZX
le chat du rabbin
 
Joined: 14 Oct 2012
Location: Ukraine

Re: ZScript "Standard Library" - Brainstorming

Postby Graf Zahl » Sun Apr 02, 2017 10:35 am

M_Responder does indeed perform some preprocessing on events and sends them as MenuEvents to the current menu.
User avatar
Graf Zahl
Lead GZDoom Developer
 
Joined: 19 Jul 2003
Location: Germany

Re: ZScript "Standard Library" - Brainstorming

Postby dpJudas » Thu Apr 13, 2017 1:26 am

ZZYZX wrote:I think this should be native and based on the active renderer, in Screen or StatusBar class. Probably sbar, since active statusbar affects viewport size.
Also, it probably should return a vector3 with -1..1 coordinates where 0 is the center of the screen, and Z coordinate would be the distance from the screen plane.

Assuming you're talking about eye/view space, the Z coordinate would always be 1. Getting from there to world space would mean multiplying with the inverse of the world to eye normal matrix (just doing the inverse rotate from Viewpoint is probably easier). To get the point the user clicked at requires a follow up ray shooting.

The code required to do the unproject and project looks like this (in pseudo C++):

Code: Select allExpand view
Vector3 DeprojectScreenToView(float tanHalfFovy, Vector2 viewportSize, Vector2 screenPos)
{
   float invFocalLenX = tanHalfFovy * viewportSize.X / viewportSize.Y;
   float invFocalLenY = tanHalfFovy;
   Vector2 screenToViewA(2.0f * invFocalLenX, 2.0f * invFocalLenY);
   Vector2 screenToViewB(-invFocalLenX, -invFocalLenY);
   return Vector3(screenToViewA * screenPos + screenToViewB, 1.0f);
}

Vector2 ProjectViewToScreen(float tanHalfFovy, Vector2 viewportSize, Vector3 viewPos)
{
   float focalLenY = 1.0f / tanHalfFovy;
   float focalLenX = focalLenY * viewportSize.Y / viewportSize.X;
   return Vector2(viewPos.X / viewPos.Z * focalLenX + viewportSize.X * 0.5f, viewPos.Y / viewPos.Z * focalLenY + viewportSize.Y * 0.5f);
}

The tricky part is finding tanHalfFovy and viewportSize. Theoretically, the math should be identical for all three renderers. The math used the poly renderer is as follows:

Code: Select allExpand view
float GetTanHalfFovY()
{
   float ratio = Viewwindow.WidescreenRatio;
   float fovratio = (Viewwindow.WidescreenRatio >= 1.3f) ? 1.333333f : ratio;
   float fovy = (float)(2 * DAngle::ToDegrees(atan(tan(Viewpoint.FieldOfView.Radians() / 2) / fovratio)).Degrees);
   return tan(fovy * M_PI / 360.0f);
}

I'm not entirely sure if that math covers all use cases, though. The code calculating it in the GL renderer is somewhat scattered and suffering from old times where it shared variables with the software renderer. In the SSAO pass I cheated and grabbed it out of the projection matrix:

Code: Select allExpand view
float GetTanHalfFovY()
{
   return 1.0f / gl_RenderState.mProjectionMatrix.get()[5];
}

As for calculating the viewport size, I am not sure what is the best way to deal with that part. Maybe querying the renderer for those things might be better, but I'm not sure if it is needed since I'm assuming the goal here is to get some screen coordinates in a virtual coordinate space. Last, there's also the problem with the VR support. I'm not sure what to do there as there's two eyes, with two independent world to eye matrices.
dpJudas
 
 
 
Joined: 28 May 2016

Re: ZScript "Standard Library" - Brainstorming

Postby ZZYZX » Thu Apr 13, 2017 4:14 am

dpJudas wrote:Assuming you're talking about eye/view space, the Z coordinate would always be 1. Getting from there to world space would mean multiplying with the inverse of the world to eye normal matrix (just doing the inverse rotate from Viewpoint is probably easier). To get the point the user clicked at requires a follow up ray shooting.

I'm actually talking about whatever coordinate that often gets stored in the shaders as W and means distance from screen plane to the point (it's just that there is no vector4 IIRC and just easier to store it as Z, as Z is unused otherwise).
That's needed so that user code can take the -1..1 coordinates and draw with corresponding virtual screen size to scale their pictures according to the distance to the point.

dpJudas wrote:As for calculating the viewport size, I am not sure what is the best way to deal with that part. Maybe querying the renderer for those things might be better, but I'm not sure if it is needed since I'm assuming the goal here is to get some screen coordinates in a virtual coordinate space. Last, there's also the problem with the VR support. I'm not sure what to do there as there's two eyes, with two independent world to eye matrices.

Well that's why I said that it should be in the engine. So that the current active renderer can decide what to return, based on current settings as well — any manual code would be completely forward incompatible and cover it only partially.

dpJudas wrote:Last, there's also the problem with the VR support. I'm not sure what to do there as there's two eyes, with two independent world to eye matrices.

What does the regular HUD code do in this case? Does it render twice? It's not supposed to work outside of the drawing hooks, so maybe just use whatever matrix that's active in currently drawn half? (this may as well make zero sense because I don't know how VR works really)
User avatar
ZZYZX
le chat du rabbin
 
Joined: 14 Oct 2012
Location: Ukraine

PreviousNext

Return to Script Library

Who is online

Users browsing this forum: No registered users and 1 guest