WIP: added basic path sprite rendering, fixed mirror bug for sprites, broke wall sprite rendering, added sprite viewer window.

This commit is contained in:
Bas
2020-07-08 22:00:41 +02:00
parent dc0fb5a2bb
commit 503c720481
40 changed files with 3142 additions and 183 deletions

View File

@@ -16,6 +16,9 @@ extern "C"
{
EXPORT void StartGame(const char* datapath, const char* rct2path, const char* rct1path)
{
if (context != nullptr)
return;
printf("(me) StartGame( %s )\n", datapath);
_log_levels[DIAGNOSTIC_LEVEL_VERBOSE] = true;

View File

@@ -86,6 +86,49 @@ extern "C"
}
// Flat path table, from Paint.Path.cpp
static constexpr const uint8_t byte_98D6E0[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 20, 4, 5, 6, 22, 8, 9, 10, 26, 12, 13, 14, 36,
0, 1, 2, 3, 4, 5, 21, 23, 8, 9, 10, 11, 12, 13, 33, 37, 0, 1, 2, 3, 4, 5, 6, 24, 8, 9, 10, 11, 12, 13, 14, 38,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 29, 30, 34, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 40,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 35, 41, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 42,
0, 1, 2, 3, 4, 5, 6, 7, 8, 25, 10, 27, 12, 31, 14, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 28, 12, 13, 14, 44,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 45, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 46,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 32, 14, 47, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 48,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 49, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 50
};
// Returns the sprite image index for a small scenery tile element.
// Inspired by: path_paint()
EXPORT uint32_t GetPathSurfaceImageIndex(const TileElement* tileElement)
{
PathElement* pathElement = tileElement->AsPath();
PathSurfaceEntry* footpathEntry = pathElement->GetSurfaceEntry();
uint32_t imageId;
if (tileElement->AsPath()->IsSloped())
{
imageId = 16; // We just take rotation 0. Always.
}
else
{
uint8_t edges = (pathElement->GetEdgesAndCorners());
imageId = byte_98D6E0[edges];
}
return (imageId + footpathEntry->image);
}
// Returns the sprite image index for a small scenery tile element.
// Inspired by: path_paint()
EXPORT uint32_t GetPathRailingImageIndex(const TileElement* tileElement)
{
return 0;
}
// Returns the sprite image index for a small scenery tile element.
EXPORT uint32_t GetSmallSceneryImageIndex(const TileElement* tileElement, uint8_t direction)
{
@@ -200,46 +243,31 @@ extern "C"
}
// Returns the image index of the tile element and its texture size.
EXPORT void GetTextureSize(uint32_t imageIndex, rct_size16* textureSize)
// Struct containing information about the sprite.
struct sprite_data
{
/*
uint32_t imageIndex = 0;
switch (tileElement->GetType())
int16_t width;
int16_t height;
int16_t x_offset;
int16_t y_offset;
};
// Returns the image index of the tile element and its texture size.
EXPORT void GetTextureData(uint32_t imageIndex, sprite_data* data)
{
const rct_g1_element* g1 = gfx_get_g1_element(imageIndex & 0x7FFFF);
if (g1 == nullptr)
{
case TILE_ELEMENT_TYPE_SURFACE:
imageIndex = GetSurfaceSprite(tileElement, 0, 0, direction);
break;
case TILE_ELEMENT_TYPE_PATH:
// path_paint(session, baseZ, tile_element);
break;
case TILE_ELEMENT_TYPE_TRACK:
// track_paint(session, direction, baseZ, tile_element);
break;
case TILE_ELEMENT_TYPE_SMALL_SCENERY:
imageIndex = GetSmallScenerySprite(tileElement, direction);
break;
case TILE_ELEMENT_TYPE_ENTRANCE:
// entrance_paint(session, direction, baseZ, tile_element);
break;
case TILE_ELEMENT_TYPE_WALL:
// fence_paint(session, direction, baseZ, tile_element);
break;
case TILE_ELEMENT_TYPE_LARGE_SCENERY:
// large_scenery_paint(session, direction, baseZ, tile_element);
break;
case TILE_ELEMENT_TYPE_BANNER:
// banner_paint(session, direction, baseZ, tile_element);
break;
printf("(me) Could not find g1 element for %i.\n", imageIndex);
return;
}
if (imageIndex == 0)
{
printf("(me) GetTileElementTextureInfo: image index = 0\n");
return 0;
}*/
*textureSize = gfx_get_sprite_size(imageIndex);
data->width = g1->width;
data->height = g1->height;
data->x_offset = g1->x_offset;
data->y_offset = g1->y_offset;
}

View File

@@ -23,6 +23,10 @@
# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*
# For temporary test stuff
/[Aa]ssets/Temp/
/[Aa]ssets/Temp.meta
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/

View File

@@ -0,0 +1,227 @@
#ifndef PathTransformer
#define PathTransformer
static const float2 aspect_ratio = float2(64, 31); // max pixel width+height of a tile.
static const float scale = 1 / 1.41421356237; // diagonal tile distance.
static const float radians = 0.785398163; // 45 degrees in radians.
static const float3x3 rotation_matrix = float3x3 // this is correct now for rotating in 3d
(
0.707107, -0.3535535, -0.6123725,
0.707107, 0.3535535, 0.6123725,
0., -0.8660253, 0.5
);
float2 uv_to_pixel(float2 uv, float2 size)
{
return (1. / size) * (uv - 0.5) + 0.5;
}
float2 pixel_to_uv(float2 pixel, float2 size)
{
return (pixel - 0.5) * aspect_ratio + 0.5;
//float2
//(
// (pixel.x * horizontal) + 0.5f,
// (pixel.y * vertical) + 0.5f
// //((pixel.x / size.x) / (size.x / horizontal)) + 0.5f,
// //((pixel.y / size.y) / (size.y / vertical)) + 0.5f
//);
}
void uv_to_pixel_float(float2 uv, float2 size, out float2 Out)
{
Out = uv_to_pixel(uv, size);
}
void pixel_to_uv_float(float2 uv, float2 size, out float2 Out)
{
Out = pixel_to_uv(uv, size);
}
/*
* Adds the sprite offsets to the uvs, as supplied by the .dat file.
*
* uv: the input uvs
* size: size in pixels, of the sprite.
* offset: the sprite offset, as supplied by the .dat file.
* returns: the output uvs.
*/
float2 sprite_add_offset(float2 uv, float2 size, float2 offset)
{
// Convert to rct coords and add offset.
float rct_x = (uv.x * size.x) + offset.x;
float rct_y = (uv.y * size.y) + offset.y;
// Convert back to uvs + scale by pixel size.
float x = (rct_x / (size.x)) / (size.x / aspect_ratio.x);
float y = (rct_y / (size.y)) / (size.y / aspect_ratio.y);
return float2(x, y);
}
void sprite_add_offset_float(float2 uv, float2 size, float2 offset, out float2 Out)
{
Out = sprite_add_offset(uv, size, offset);
}
/*
* Scales the sprite to fit the whole texture.
*
* uv: the input uvs
* returns: the output uvs.
*/
float2 sprite_scale_to_fit(float2 uv)
{
return (uv - 0.5f) * scale + 0.5f;
}
void sprite_scale_to_fit_float(float2 uv, out float2 Out)
{
Out = sprite_scale_to_fit(uv);
}
/*
* Clamps the texture in a way that does not create stretching outside the bounds.
*
* uv: the input uvs
* alpha: the alpha for this uv position.
* returns: the output uvs.
*/
float1 clamp_no_stretch(float2 uv, float1 alpha)
{
float2 s = step(float2(0, 0), uv) - step(float2(1, 1), uv);
return s.x * s.y * alpha;
}
void clamp_no_stretch_float(float2 uv, float1 alpha, out float1 Out)
{
Out = clamp_no_stretch(uv, alpha);
}
/*
* Rotates the sprite 45 degrees with the matrix.
*
* uv: the input uvs
* size: size in pixels, of the sprite.
* offset: the sprite offset, as supplied by the .dat file.
* returns: the output uvs.
*/
float2 sprite_rotate(float2 uv)
{
return mul(rotation_matrix, float3(uv, 0));
//return mul(rot_matrix, uv);;
}
void sprite_rotate_float(float2 uv, out float2 Out)
{
Out = sprite_rotate(uv);
}
/*
* Translates the center of the sprite.
*
* uv: the input uvs
* size: size in pixels, of the sprite.
* offset: the sprite offset, as supplied by the .dat file.
* returns: the output uvs.
*/
float2 sprite_translate_center(float2 uv, float2 size)
{
float diff_x = (0.5f * (size.x / aspect_ratio.x));
float diff_y = (0.5f * (size.y / aspect_ratio.y));
return float2
(
uv.x + diff_x,
uv.y + diff_y
);
}
void sprite_translate_center_float(float2 uv, float2 size, float2 offset, out float2 Out)
{
Out = sprite_translate_center(uv, size);
}
/*
* Converts the uvs of the path sprite so that the corners of the path are
* in the corners of the texture.
*
* uv: the input uvs
* size: size in pixels, of the sprite.
* offset: the sprite offset, as supplied by the .dat file.
* Out: the output uvs.
*/
void Rct_path_matrix_float(float2 uv, float2 size, float2 offset, out float2 Out)
{
//float2 rct_offset = sprite_add_offset(uv, size, offset);
//float2 scaled = sprite_scale_to_fit(rct_offset);
float3x3 a = float3x3
(
(uv.x - 0.5f) * size.x, 0, 0,
0, (uv.y - 0.5f) * size.y, 0,
0, 0, 1
);
float3x3 b = float3x3
(
(size.x * aspect_ratio.x) + 0.5f, 0, 0,
0, (size.y * aspect_ratio.y) + 0.5f, 0,
0, 0, 1
);
//float2 pixels = uv_to_pixel(uv, size);
//float2 rotated = sprite_rotate(pixels);
//float2 result = pixel_to_uv(rotated, size);
float3x3 m = mul(rotation_matrix, mul(a, b));
float3 result = float3(uv, 1);
Out = mul(m, result);
return;
float width_multiplier = (size.x / aspect_ratio.x);
float height_multiplier = (size.y / aspect_ratio.y);
float3 resized_uv = float3(uv.x / width_multiplier, uv.y / height_multiplier, 1);
float offset_x = (-offset.x / size.x);
float offset_y = (-offset.y / size.y);
float angle_cos = cos(radians) * scale;
float angle_sin = sin(radians) * scale;
float3x3 trs_matrix = float3x3
(
angle_cos, angle_sin, 0,
-angle_sin, angle_cos, 0,
0, 0, 1
);
Out = mul(trs_matrix, resized_uv);
}
#endif

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: c1557785be95be44db2f53c1f6035ee5
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8d0a638b1b5b09549a908e9cf9bb2afa
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}

View File

@@ -21,18 +21,26 @@ Material:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Path
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Shader: {fileID: -6465566751694194690, guid: 8d0a638b1b5b09549a908e9cf9bb2afa,
type: 3}
m_ShaderKeywords:
m_LightmapFlags: 4
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: 2050
stringTagMap:
RenderType: Opaque
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- Main:
m_Texture: {fileID: 2800000, guid: 364a5251bbabdac47bbcdc02c13d8f1f, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- Surface:
m_Texture: {fileID: 2800000, guid: 364a5251bbabdac47bbcdc02c13d8f1f, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BaseMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
@@ -62,6 +70,7 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- PixelToUnit: 0.022
- _AlphaClip: 0
- _Blend: 0
- _BumpScale: 1
@@ -84,7 +93,7 @@ Material:
- _WorkflowMode: 1
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.8396226, g: 0.8051061, b: 0.2653524, a: 1}
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}

View File

@@ -25,7 +25,7 @@ Material:
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- Wall:
m_Texture: {fileID: 0}
m_Texture: {fileID: 2800000, guid: 82bfab83fdf1f9a45ad41b3a55036bdc, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BaseMap:

View File

@@ -1,50 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fcf7219bab7fe46a1ad266029b2fee19, type: 3}
m_Name: Readme
m_EditorClassIdentifier:
icon: {fileID: 2800000, guid: 7801804018a7dcf42abb827444e18660, type: 3}
title: Universal Render Pipeline Template
sections:
- heading: Universal Render Pipeline
text: 'The Universal Project Template configures Project settings for Projects where performance, wide platform support, and ease of customizing graphics are the primary considerations.'
linkText:
url:
- heading:
text: 'This Template uses the Universal Render Pipeline (URP) and Shader Graph.'
linkText:
url:
- heading:
text: 'URP is prebuilt Scriptable Render Pipeline that is quick and easy to customize, and lets you create optimized graphics across a wide range of platforms. URP also includes an optimized 2D renderer complete with 2D lights and pixel perfect rendering, and an integrated post-processing solution.'
linkText:
url:
- heading:
text: 'Shader Graph is a tool that allows you to create shaders using a visual node editor instead of writing code.'
linkText:
url:
- heading:
text: 'This template contains a sample Scene that contains examples of how to configure lighting settings, Materials, Shaders, and post-processing effects in URP, several preconfigured Universal Render Pipeline Assets that let you quickly swap between graphics quality levels, and Presets that have been optimized for use with URP.'
linkText:
url:
- heading:
text: 'This template contains a sample Scene that contains examples of how to configure lighting settings, Materials, Shaders, and post-processing effects in URP, several preconfigured Universal Render Pipeline Assets that let you quickly swap between graphics quality levels, and Presets that have been optimized for use with URP.'
linkText:
url:
- heading:
text: 'To read more about URP and its built-in features, see the '
linkText: URP documentation.
url: https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@latest/index.html
- heading:
text: 'For more information about Shader Graph, see the '
linkText: Shader Graph documentation
url: https://docs.unity3d.com/Packages/com.unity.shadergraph@latest
loadedLayout: 1

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 83c2ed844a8c74b779a4c823d16594b1
timeCreated: 1484217493
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0055f5098c8f3d84b8aed26799aefc1b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
using System.Collections;
using UnityEditor;
using UnityEngine;
using Utilities;
namespace EditorExtensions
{
/// <summary>
/// Property drawer for the <see cref="ScriptSelectorAttribute"/>.
/// </summary>
[CustomPropertyDrawer(typeof(Matrix4x4))]
public class MatrixDrawer : PropertyDrawer
{
const int MatrixSize = 4;
bool foldout = true;
/// <summary>
/// Draws the GUI for a property with a <see cref="ScriptSelectorAttribute"/>.
/// </summary>
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
IEnumerator enumerator = property.GetEnumerator();
float spacing = EditorGUIUtility.standardVerticalSpacing;
float height = EditorGUIUtility.singleLineHeight;
Rect foldoutRect = position;
foldoutRect.height = height;
if ((foldout = EditorGUI.Foldout(foldoutRect, foldout, label, toggleOnLabelClick: true)))
{
for (int row = 0; row < MatrixSize; row++)
{
float sx = (position.x);
float sy = (position.y + height + spacing);
float width = ((position.width / MatrixSize) - spacing);
for (int col = 0; col < MatrixSize; col++)
{
// Draw a single matrix float field.
enumerator.MoveNext();
SerializedProperty matrixProp = (SerializedProperty)enumerator.Current;
float original = matrixProp.floatValue;
Rect fieldRect = new Rect
(
sx + col * (width + spacing),
sy + row * (height + spacing),
width,
height
);
float output = EditorGUI.FloatField(fieldRect, original);
if (output != original)
{
matrixProp.floatValue = output;
}
}
}
}
}
/// <summary>
/// Gets the height of the property.
/// </summary>
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!foldout)
return EditorGUIUtility.singleLineHeight;
return ((1 + MatrixSize) * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing));
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: b3398bfdcf5eb584089c9bfe3c5d0f82
guid: 4b5980b806815ea4089abc64312de22d
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -5,7 +5,7 @@ using UnityEditor;
using UnityEngine;
using Utilities;
namespace Lib
namespace EditorExtensions
{
/// <summary>
/// Property drawer for the <see cref="ScriptSelectorAttribute"/>.

View File

@@ -0,0 +1,91 @@
using Graphics;
using Lib;
using UnityEditor;
using UnityEngine;
namespace EditorExtensions
{
/// <summary>
/// Editor window that can browse the sprites in OpenRCT2.
/// Tip: sprites.h in the original source code has some example indices.
/// </summary>
public class SpriteViewerWindow : EditorWindow
{
int imageIndexOffset = 0;
int horizontalCount = 10;
int verticalCount = 10;
Vector2 scrollPosition;
[MenuItem("OpenRCT2/Sprite Viewer")]
static void ShowWindow()
{
// Get existing open window or if none, make a new one:
SpriteViewerWindow window = GetWindow<SpriteViewerWindow>("OpenRCT2 Sprite Viewer");
window.Show();
}
void OnGUI()
{
imageIndexOffset = Mathf.Clamp(EditorGUILayout.IntField("Image index offset", imageIndexOffset), 0, 0x7FFFE);
horizontalCount = EditorGUILayout.IntSlider("Horizontal sprite count", horizontalCount, 1, 20);
verticalCount = EditorGUILayout.IntSlider("Vertical sprite count", verticalCount, 1, 20);
GUILayout.BeginHorizontal();
if (GUILayout.Button("Previous page"))
imageIndexOffset -= (horizontalCount * verticalCount);
if (GUILayout.Button("Next page"))
imageIndexOffset += (horizontalCount * verticalCount);
GUILayout.EndHorizontal();
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
uint offset = (uint)imageIndexOffset;
for (int y = 0; y < verticalCount; y++)
{
EditorGUILayout.BeginHorizontal();
for (int x = 0; x < horizontalCount; x++)
{
Texture2D texture = GraphicsFactory
.ForImageIndex(offset)
.ToTexture2D();
SpriteData data = OpenRCT2.GetTextureData(offset);
string information = $"Index:\t{offset}\nSize:\t{data.width}x{data.height} px\nOffset:\t({data.offsetX}, {data.offsetY})";
GUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.ExpandHeight(true));
if (texture == null)
GUILayout.Box("Not found");
else
GUILayout.Box(texture);
GUILayout.Label(information, new GUIStyle { alignment = TextAnchor.LowerLeft }, GUILayout.ExpandHeight(true));
GUILayout.EndVertical();
offset++;
}
EditorGUILayout.EndHorizontal();
}
EditorGUILayout.EndScrollView();
}
void Awake()
{
OpenRCT2.StartGame();
}
void OnDestroy()
{
OpenRCT2.StopGame();
}
}
}

Some files were not shown because too many files have changed in this diff Show More