Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3 from CleanroomMC/mui
Browse files Browse the repository at this point in the history
ModularUI docs
  • Loading branch information
Rongmario authored Nov 5, 2023
2 parents 28c0a82 + f0a7f10 commit 22e8ad7
Show file tree
Hide file tree
Showing 13 changed files with 1,061 additions and 0 deletions.
Binary file added docs/mod-wiki/modularui/anchor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 92 additions & 0 deletions docs/mod-wiki/modularui/client_gui_tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
Here we want to create a UI that only exist on the client side and doesn't sync any data.

We will make the GUI as simple as possible

## 1. Creating the screen
First create a new class with a static method, which returns a `ModularScreen`.
````java
public class TutorialGUI {

public static ModularScreen createGUI() {
ModularPanel panel = ModularPanel.defaultPanel("tutorial_panel");
return new ModularScreen(panel);
}
}
````
This creates the most basic GUI with a 176 x 166 centered panel. Take a look at the constructor and method used
including their javadoc. The GUI's theme defines widgets backgrounds. By default, this gives panels the default vanilla
background. You can call `.background()` to set your own background. However, creating a new theme is recommended if
applicable.

For now lets put a title at the top of the panel. For that we'll use `.child()` and pass a widget to it. To create a
text widget we can use `IKey.str().asWidget`. (Note: You can create a translated string with `IKey.lang()`). We also
want to set the postion, for that we chain `.top()` and `.left()` on ANY widegt which implements `IPositioned`. We don't
need to set a size since `TextWidget` calculates it on its own. But you can limit the width for example and the text
will automatically wrap, if necessary.
```java
public static ModularScreen createGUI() {
ModularPanel panel = ModularPanel.defaultPanel("tutorial_panel");
panel.child(IKey.str("My first screen").asWidget()
.top(7).left(7));
return new ModularScreen(panel);
}
```

## 2. Opening the screen
We want to open the screen when the player right clicks with a diamond. We use a forge event for that and simply check
for client side and a diamond. Then we open the screen with `ClientGUI.open()`. Pass in a new screen instance with the
method we just created. Now let's boot up minecraft and test it.

```java
@Mod.EventBusSubscriber
public class TutorialGUI {

@SubscribeEvent
public static void onItemUse(PlayerInteractEvent.RightClickItem event) {
if (event.getEntityPlayer().getEntityWorld().isRemote && event.getItemStack().getItem() == Items.DIAMOND) {
ClientGUI.open(createGUI());
}
}

public static ModularScreen createGUI() {
...
}
}
```
Your screen should look like this, when you take a diamond and right click. The blurry background comes from the Blur
mod. It is not required, but it makes things look nicer in my opinion. You may notice the purple text in the bottom left
corner or a border on widgets when you hover them. That's the debug mode. Its enabled by default in a dev environment
and can be disabled via the config file or by pressing `CTRL + SHIFT + ALT + C` while in a ModularUI screen.
![grafik](https://user-images.githubusercontent.com/45517902/228584027-eaf4f49b-1967-4aa1-9cd3-416e5610f113.png)

## 3. Adding a button
Now let's add a button, that greets the player with a message. For that we will use the `ButtonWidget`. Here we do need
to set a size since the text on the button is not a widget, but a `IDrawable`, which doesnt size itself. It uses the
size of its widget. We don't need to set a background since its set by the current Theme. We center the button in the
panel using `.align(Alignment.Center)` and set a size with `.size(60, 16)`. We could also use `.width(60).height(16)`.
It's the same thing.
```java
public static ModularScreen createGui() {
ModularPanel panel = ModularPanel.defaultPanel("tutorial_panel");
panel.child(IKey.str("My first screen").asWidget()
.top(7).left(7))
.child(new ButtonWidget<>()
.align(Alignment.Center)
.size(60, 16)
.overlay(IKey.str("Say Hello"))
.onMousePressed(button -> {
EntityPlayer player = Minecraft.getMinecraft().player;
player.sendMessage(new TextComponentString("Hello " + player.getName()));
return true;
}));
return new ModularScreen(panel);
}
```
Let's see what it looks like.
![grafik](https://user-images.githubusercontent.com/45517902/228590064-108ae148-acc8-45ca-9d96-e91cbe0f2e4a.png)

Pressing the button greets the player in the chat.
![grafik](https://user-images.githubusercontent.com/45517902/228590312-24f6bd17-dd05-44ee-96bd-6ae7d00e59cc.png)

Simple, right?

72 changes: 72 additions & 0 deletions docs/mod-wiki/modularui/framework.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
This page is about some core classes of a Modular GUI.

## ModularScreen

This is the core of each GUI on the client side. It keeps track of all panels.
This is where the `GuiContext` is stored.

Useful methods are:

- `getOwner()` returns the owner of the screen (usually a mod id)
- `getName()` returns the name of the main panel
- `getContext()` returns the `GuiContext`
- `getWindowManager()` returns the `WindowManager`
- `getSyncManager()` returns the `GuiSyncManager`
- `isClientOnly()` returns if the screen is only open on client side
- `registerGuiActionListener()` register an interaction listener
- `registerFrameUpdateListener()` registers a listener which is called approximately 60 times per second
- `getCurrentTheme()` returns the active theme for the screen
- `useTheme()` tries to set the new theme (does nothing if theme is overridden by resource packs)

## GuiContext

This class keeps track of the current GUI state. For example pressed buttons and keys, focused widgets
dragging widgets, mouse position, JEI settings, themes and most importantly viewports and transformations.

Useful methods are:

- `isAbove()` returns if the mouse is above a widget
- all methods related to hovering
- all methods related to focusing
- `hasDraggable()` if the mouse is currently dragging an `IDraggable` (not including item stacks)
- `isMouseItemEmpty()` if the mouse is currently not dragging an `ItemStack`
- `getMouseX()` and `getMouseY()` returns the current mouse position with the current transformations applied to it.
That
means it is relative to the current widgets position
- `getMouseAbsX()` and `getMouseAbsY()` returns the true (absolute) mouse position
- `unTransformMouseX()` and `unTransformMouseY()` is like `getMouseX()` and `getMouseY()`, but the transformations are
inverted
- `getMouseButton()` returns the last pressed mouse button
- `getMouseWheel()` returns the last scroll wheel use
- `getKeyCode()` returns the last typed key code
- `getTypedChar()` returns the last typed character
- `getPartialTicks()` returns the partial ticks for the current frame
- `getTheme()` returns the current active theme
- `getJeiSettings()` returns the current modifiable JEI settings

## ModularPanel

This is the root of each widget tree. Panels are also [widgets](#widget).

## Widget

A widget is an element in the widget tree. It has a size and position and it can be rendered on screen.

This class has a lot of useful methods, too many to list them all. But you can take a look yourself. I did my best
to structure it and make it clean.

## WindowManager

Keeps track of all panels and the main panels. Handles opening and closing panels

## GuiSyncManager

Manages sync values. This is the only class (with `ModularContainer`) that exists on client and server side.

## GuiScreenWrapper

This is the minecraft `GuiContainer` class which wraps the `ModularScreen`. This is an internal class.

## ModularContainer

This is the minecraft `Container` class. This is an internal class.
68 changes: 68 additions & 0 deletions docs/mod-wiki/modularui/getting_started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Getting Started

## Adding ModularUI to your mod

Add the maven to the repositories (if not already present)

````groovy
maven {
name 'CurseMaven'
url 'https://cursemaven.com'
content {
includeGroup 'curse.maven'
}
}
````

and the dependency declaration to dependencies

````groovy
implementation 'curse.maven:modularui-624243:4786372-sources-4786373'
````

- `624243` is the Curseforge project id of ModularUI
- `4779301` is the `dev` file id (for version 2.2.3)
- `4779302` is the `sources` file id (for version 2.2.3)

By including the sources in your dependency declaration you'll get access to the real uncompiled code with javadocs.

Make sure to use the latest version!

## Development Tools

I highly recommend using IntelliJ in combination with the Single Hotswap plugin.

## Other documentation

As always, the code itself is the best documentation. Most API classes have lots of useful javadoc information.

## Creating a GUI

First you need to decide if you want a client only screen or a client-server synced gui.

### Client only GUI

Client only GUIs are easier to work with, but they can't communicate with the server.
You can open one by calling `ClientGUI.open(ModularScreen, JeiSettings)`.
`JeiSettings` can be omitted by an overloaded method. Client only GUIs don't display jei on the side by default.
You can change that by creating your own `JeiSettings` instance. The `ModularScreen` should be a new instance.

Go [here](client_gui_tutorial.md) to get started on creating a client GUI. Even if you are looking into making a synced
GUI, I still recommend
checking it out as it contains some information which is useful for both cases.

### Synced GUI

Synced GUIs are much more complicated to open. The most important thing is that you must only open synced GUIs
on server side. ModularUI (via Forge) automatically syncs to client. This means you need to supply enough information on
server side to find the GUI on client side. For example if the GUI is bound to a `TileEntity`, then you need to supply
at least a world instance and a block position. `GuiInfo`s take care of that information.
Not that Forge only syncs `EntityPlayer`, `World` and a `BlockPos`. For more specific data you need multiple `GuiInfo`s.
For example if a GUI is opened on right click with an item. The `GuiInfo` does not know with wich hand the GUI was
opened.
That's why ModularUI provides two `GuiInfo`s for that. One for main hand and one for the off hand.
ModularUI provides some default `GuiInfo`s at `GuiInfos`. If you want to create your own `GuiInfo`, take a look at
`GuiInfo.builder()`.
Now that you have your `GuiInfo`, simply call `open()` with your needed parameters.

Go [here](synced_gui_tutorial.md) to get started on creating a synced GUI.
3 changes: 3 additions & 0 deletions docs/mod-wiki/modularui/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--8<--
https://raw.githubusercontent.com/CleanroomMC/ModularUI/master/README.md
--8<--
34 changes: 34 additions & 0 deletions docs/mod-wiki/modularui/json/alignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Alignment is an object with an x and y component. Where 0.0 means start and 1.0 means end.

## Alignment by name

ModularUI has 9 default alignments.

- `top_left` or `tl`
- `top_center` or `tc`
- `top_right` or `tr`
- `center_left` or `cl`
- `center` or `c`
- `center_right` or `cr`
- `bottom_left` or `bl`
- `bottom_center` or `bc`
- `bottom_right` or `br`

!!! Example
```json
{
"alignment": "top_center"
}
```

You can also create a new alignment.

!!! Example
```json
{
"alignment": {
"x": 0.3,
"y": 0.6666666
}
}
```
100 changes: 100 additions & 0 deletions docs/mod-wiki/modularui/json/color.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
There are many different way to define color in JSON

## Hexadecimal number

The simplest way is by using hexadecimal numbers. You can do that be prefixing your number string with `0x`, `0X` or `#`.
The format is `AARRGGBB`. If `A` (alpha) is not set, it defaults to full opacity

!!! Example
```json
{
"color": "#FFFFFF"
}
```


The following formats can all have the `alpha` or `a` property, with a value from either 0.0 to 1.0 or from 0 to 255.
If you want to use the 0.0 to 1.0 range you need use a `.`. `1` will use the
0 to 255 range and is very low. `1.0` will use the 0.0 to 1.0 range and is full opacity.

## RGB

- `red` or `r`: The red value from 0 to 255
- `green` or `g`: The green value from 0 to 255
- `blue` or `b`: The blue value from 0 to 255

!!! Example
```json
{
"color": {
"r": 200,
"g": 0,
"b": 44,
"alpha": 1.0
}
}
```

Here you can see how alpha can be added.

## HSV

- `hue` or `h`: The hue value from 0 to 360 (wraps around) (default is 0)
- `saturation` or `s`: The saturation from 0.0 to 1.0 (default is 0.0)
- `value` or `v`: The value from 0.0 to 1.0 (default is 1.0)

If `value` is not defined, [HSL](#hsl) will be used.

!!! Example
```json
{
"color": {
"hue": 120,
"saturation": 0.5,
"value": 0.75
}
}
```

## HSL

- `hue` or `h`: The hue value from 0 to 360 (wraps around) (default is 0)
- `saturation` or `s`: The saturation from 0.0 to 1.0 (default is 0.0)
- `lightness` or `l`: The value from 0.0 to 1.0 (default is 0.5)

!!! Example
```json
{
"color": {
"hue": 120,
"saturation": 0.5,
"lightness": 0.75
}
}
```

!!! Note
The saturation is not the same from [HSV](#hsv) as from [HSL](#hsl) (they are calculated slightly different),
but the hue is.

## CMYK

- `cyan` or `c`: The cyan value from 0.0 to 1.0 (default is 1.0)
- `magenta` or `m`: The cyan value from 0.0 to 1.0 (default is 1.0)
- `yellow` or `y`: The cyan value from 0.0 to 1.0 (default is 1.0)
- `black` or `k`: The cyan value from 0.0 to 1.0 (default is 1.0)

!!! Example
```json
{
"color": {
"c": 1.0,
"m": 0.5,
"y": 0.75,
"k": 0.2
}
}
```

!!! Warning
You can NOT mix any of those formats! (except of course alpha)
Loading

0 comments on commit 22e8ad7

Please sign in to comment.