Skip to content

Commit 31a482b

Browse files
committed
Start API design guide
1 parent 0d1f050 commit 31a482b

File tree

4 files changed

+244
-69
lines changed

4 files changed

+244
-69
lines changed
242 KB
Loading

Documentation/api-design-guide.md

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# API Design Guide
2+
3+
Cesium for Unreal aims to unlock geospatial capabilities in Unreal Engine, while also enabling developers to take advantage of in-engine features. As a result, people who use the plugin can often come with existing Unreal knowledge.
4+
5+
In order to make Cesium's integration as seamless as possible, we aim to mirror the paradigms and APIs of the engine where we can.
6+
7+
## Table of Contents
8+
9+
- [UObject Design](#uobject-design)
10+
- [Overview](#overview)
11+
- [Best Practices](#best-practices)
12+
- [Cheat Sheet](#cheat-sheet)
13+
- [Blueprints](#blueprints)
14+
15+
## UObject Design
16+
17+
`UObject` is the underlying base class of gameplay objects in Unreal Engine. Most classes in the Cesium for Unreal plugin inherit from `UObject`, such that they expose their functionality to the systems in Unreal Engine.
18+
19+
The [Overview](#overview) points out some of the components involved when designing `UObject`s. If you are already familiar with these, feel free to skip to the [Best Practices](#best-practices) section.
20+
21+
### Overview
22+
23+
#### `UObject`
24+
25+
> [Official Unreal Engine Documentation](https://dev.epicgames.com/documentation/en-us/unreal-engine/objects-in-unreal-engine)
26+
27+
The official documentation already contains a summary of `UObject`, so we won't duplicate that here. However, the [UObject Creation](https://dev.epicgames.com/documentation/en-us/unreal-engine/objects-in-unreal-engine#uobjectcreation) and [Destroying Objects](https://dev.epicgames.com/documentation/en-us/unreal-engine/objects-in-unreal-engine#destroyingobjects) sections have a few elements of note:
28+
29+
- `UObject`s may only use default constructors. In other words, a `UObject` cannot have a constructor with arguments.
30+
- For Actors or Actor Components, use the `BeginPlay()` method for specific initialization behavior.
31+
- `UObject`s are automatically garbage collected when they are no longer referenced. Therefore, be mindful of "strong references" that can keep them alive (e.g., UProperties, class instances, `TStrongObjectPtr`).
32+
33+
#### Properties
34+
35+
> [Official Unreal Engine Documentation](https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-uproperties)
36+
37+
`UObject`s often contain member variables (or properties) important to the object's gameplay logic. However, there is an extra step required to make Unreal Engine able to recognize and manipulate those variables. Once recognized, the properties can be acted upon, e.g., made accessible through Blueprints or the Editor UI.
38+
39+
The `UPROPERTY` macro identifies such properties. This macro should be put above a property that you wish to expose to Unreal Engine.
40+
41+
#### Functions
42+
43+
> [Official Unreal Engine Documentation](https://dev.epicgames.com/documentation/en-us/unreal-engine/ufunctions-in-unreal-engine)
44+
45+
`UFUNCTION` is the equivalent of `UPROPERTY` for C++ functions. By using this macro, a function can be made access to Blueprints, or even as a button in the Editor interface. It may also be used to enable event handlers and delegates.
46+
47+
#### Enums
48+
49+
`UENUM` (TODO, short)
50+
51+
#### Modifiers
52+
53+
Many `UObject` macros take arguments that influence their scope and behavior. For example, let's look at the `MaximumScreenSpaceError` property on `ACesium3DTileset`:
54+
55+
```c++
56+
UPROPERTY(
57+
EditAnywhere,
58+
BlueprintGetter = GetMaximumScreenSpaceError,
59+
BlueprintSetter = SetMaximumScreenSpaceError,
60+
Category = "Cesium|Level of Detail",
61+
meta = (ClampMin = 0.0))
62+
double MaximumScreenSpaceError = 16.0;
63+
```
64+
65+
- The `EditAnywhere` modifier allows the property to show up in the Details panel of the Unreal Editor. The user can thus modify the value directly.
66+
- The `BlueprintGetter` and `BlueprintSetter` define specific functions for getting and setting the value in Blueprints (see [UFunctions](#ufunctions)).
67+
- The `Category` indicates how the property should be organized in the Details panel. It appears under the "Level of Detail" category, which itself is under a larger "Cesium" category.
68+
- Finally, `meta` refers to additional metadata that can augment how the property functions or appears. Here, `ClampMin` prevents it from being set to an invalid value.
69+
70+
The official documentation for `UPROPERTY` explains the fundamentals, but it is not comprehensive. This [masterlist](https://benui.ca/unreal/uproperty/) of `UPROPERTY` modifiers by ben ui provides a more extensive look into what's possible.
71+
72+
The `UFUNCTION` macro also takes multiple arguments to influence its behavior. For instance,
73+
74+
```c++
75+
UFUNCTION(
76+
BlueprintPure,
77+
Category = "Cesium",
78+
meta = (ReturnDisplayName = "UnrealPosition"))
79+
FVector TransformLongitudeLatitudeHeightPositionToUnreal(
80+
const FVector& LongitudeLatitudeHeight) const;
81+
```
82+
83+
- The `BlueprintPure` modifier allows the function to be executed in a Blueprint graph. The `Pure` keyword indicates that the function will not affect the owning object (`ACesiumGeoreference`) in any way.
84+
- The `Category` indicates how the property should be organized in Blueprint selection panel, under "Cesium" category.
85+
- Finally, `meta` refers to additional metadata that can augment how the property functions or appears. Here, `ReturnDisplayName` specifies how the output will be labelled in the Blueprint node.
86+
87+
`UFUNCTION` must be used for any functions that are used for `BlueprintGetter` or `BlueprintSetter`. For `BlueprintSetter`, the function should be `public` and serve as the mechanism for setting the property from C++. A corresponding `BlueprintGetter` is usually needed for use by C++, even though it is often not needed for Blueprints.
88+
89+
Again, the official documentation for `UFUNCTION` explains the fundamentals, but this [masterlist](https://benui.ca/unreal/uproperty/) of `UFUNCTION` modifiers by ben ui is more extensive.
90+
91+
The [Cheat Sheet](#cheat-sheet) is included so you can focus on the most relevant ones.
92+
93+
### Best Practices
94+
95+
#### Change Detection
96+
97+
Many Cesium for Unreal classes manage an internal state that must be carefully maintained when modifying properties. For instance, when properties on the `ACesiumGeoreference` are changed, it must call `UpdateGeoreference()` immediately after to ensure that all other properties are synced in response.
98+
99+
As a result, `BlueprintReadWrite` is rarely used for properties in Cesium for Unreal. Much of the time, there is additional logic needed after a property is "set", and this change needs to be specifically detected.
100+
101+
We have settled on the following standards for properties that require post-change logic:
102+
103+
- Declare in the `private:` section of the class. This prevents the property from being get or set directly from outside the class in C++ (which is important, because there is no mechanism like `PostEditChangeProperty` or `BlueprintSetter` available in code).
104+
- Add `Meta = (AllowPrivateAccess)`.
105+
- Add `BlueprintGetter` and `BlueprintSetter` functions.
106+
- Overide the `PostEditChangeProperty` method to be notified of changes to the property in the Editor.
107+
108+
Perhaps there is a rare-case property where no action is necessary after setting a property from C++ (and it's unlikely to be needed in the future). In this case, the property can be declared in the `public:` section. Such a property is not likely to need a `PostEditChangeProperty` or `BlueprintSetter` either.
109+
110+
#### Details Panel
111+
112+
### Cheat Sheet
113+
114+
For convenience, here is a cheat sheet of some of the most relevant modifiers for each category.
115+
116+
#### `UPROPERTY`
117+
118+
| Name | How (and when) to use |
119+
| ---- | --------------------- |
120+
| `VisibleAnywhere` | Property is read-only in the Details panel. For editable properties, use `EditAnywhere`. Don't use this for variables that shouldn't be visible to the user (e.g., implementation details, internal state management). |
121+
| `EditAnywhere` | Property is editable in the Details panel. Use `VisibleAnywhere` for read-only variables. |
122+
| `BlueprintReadOnly` | Property is accessible in Blueprints but read-only. |
123+
| `BlueprintReadWrite` | Property is editable from Blueprints. Use when the "set" logic is simple enough that nothing additional must happen after the property is set. If additional logic is required, use `BlueprintSetter` instead. |
124+
125+
## Blueprints
126+
127+
Blueprints are a visual scripting option in Unreal Engine that many users use over C++ code. Thus, part of API design includes creating sensible Blueprints for less code-savvy users.
128+
129+
### Integrate with Existing Blueprints
130+
131+
Try to defer to Unreal Engine's naming schemes. For example, texture coordinates are referred to as "UV", so any parameters that represent texture coordinates should also be called UV.
132+
133+
![](Images/matchUnrealNaming.png)
134+
135+
## Materials
136+
137+
## Deprecation
138+
139+
## Backwards Compatibility

Documentation/developing-uobjects.md

-13
This file was deleted.

0 commit comments

Comments
 (0)