merge main into lua

This commit is contained in:
2025-04-12 14:55:42 +02:00
6 changed files with 138 additions and 86 deletions

View File

@@ -113,11 +113,16 @@ namespace SplashEdit.EditorCode
// Retrieve all PSXObjectExporter objects and create their PSX textures. // Retrieve all PSXObjectExporter objects and create their PSX textures.
PSXObjectExporter[] objects = FindObjectsByType<PSXObjectExporter>(FindObjectsSortMode.None); PSXObjectExporter[] objects = FindObjectsByType<PSXObjectExporter>(FindObjectsSortMode.None);
foreach (PSXObjectExporter exp in objects) for (int i = 0; i < objects.Length; i++)
{ {
EditorUtility.DisplayProgressBar($"{nameof(VRAMEditorWindow)}", $"Export {nameof(PSXObjectExporter)}", ((float)i) / objects.Length);
PSXObjectExporter exp = objects[i];
exp.CreatePSXTextures2D(); exp.CreatePSXTextures2D();
} }
EditorUtility.ClearProgressBar();
// Define framebuffer regions based on selected resolution and layout. // Define framebuffer regions based on selected resolution and layout.
(Rect buffer1, Rect buffer2) = Utils.BufferForResolution(selectedResolution, verticalLayout); (Rect buffer1, Rect buffer2) = Utils.BufferForResolution(selectedResolution, verticalLayout);
@@ -157,6 +162,7 @@ namespace SplashEdit.EditorCode
} }
} }
} }
} }
private void OnGUI() private void OnGUI()

145
README.md
View File

@@ -1,93 +1,110 @@
# SplashEdit Update: This readme was written by MrQuetch (Formally Quilt#6855 on Discord).
SplashEdit is a Unity Package that converts your Unity scenes into authentic PSX worlds by exporting binary data loadable in a PlayStation 1 as a binary fileformat called **SPLASHPACK**. It streamlines the export process for your scenes and offers additional tools for VRAM management and texture quantization. **Note: It does use some of Bandwidth's original readme plus my own additions.**
## Important: Instructions in this readme are writen terribly (PR welcome, please I suck at writing these) REFER TO THE VIDEO DOWN BELOW FOR USAGE ## SplashEdit
https://youtu.be/1JJFYptDTk0
## Features ``SplashEdit`` is a Unity package written by Bandwidth that converts a Unity scene to a binary format called ``SplashPack`` which will then be built into a PS1 executable. You will need a few things for this to work but I first want to point out these things:
- **Automatic Scene Exporting:** - Visual Studio Code
Export your scene with a single click using the PSX Scene Exporter component. This process automatically packs textures into the PSX's 2D VRAM. - PSYQo
- **Texture Packing & Quantization:** - PSXSplash
Convert and preview your textures in a PSX-compatible format with built-in quantization tools.
- **Light baking**
Prebakes any lights in the Scene into the output mesh data
- **Navmesh generation**
Generates a navmesh for FPS movement in your scene
## Installation Visual Studio Code is the IDE that will be used to write code for PS1 games (in C++) made with the PSYQo development kit and PSXSplash are the [base project files](https://github.com/psxsplash/psxsplash) that you will need to place in your project folder. Ultimately, the end goal is that what you see in Unity is exactly what you will see on the PS1.
Install SplashEdit directly from the Git repository using Unity's Package Manager: ## Installation:
Get the following:
- Unity 6 (For setting up your PS1 scene)
- Visual Studio Code (For writing your C++ code)
- Nicolas Noble's PSX Dev Extension for PS1 Development (Which includes a panel for PS1 templates and tools to build your project)
- A real PS1 or emulator (PCSX-Redux, Duckstation, etc.) to test your project
1. **Open Unity's Package Manager:** As far as models are concerned, any modeling program will do as long as you can import the file into Unity (and subsequently exported to the ``SplashPack`` binary format).
Go to `Window``Package Manager`. FBX is a very common model file format used for skinned meshes with animations. I do hope to implement this myself (unless someone else beats me to it).
2. **Add Package from Git URL:** Rather than having to git clone this repository to your machine, you can install it directly from within Unity:
Click the **+** button in the upper left corner and select **"Add package from git URL..."**. 1. **Open Unity's Package Manager:**
Enter the Git URL for SplashEdit: `https://github.com/psxsplash/splashedit.git`
Click **Add** and wait for the package to install.
## Usage Go to `Window` -> `Package Manager`.
### General Scene Exporting 2. **Add Package From Git URL:**
If you only need to export the scene, follow these steps: Click the + button in the upper left corner and select **"Add Package From Git URL"**.
1. **PSX Object Exporter:** Enter the Git URL for ``SplashEdit``: `https://github.com/psxsplash/splashedit.git`. Alternatively, if you want to install a different branch of ``SplashEdit``, such as ``lua``, you can use: `https://github.com/psxsplash/splashedit.git#lua`.
- Attach the **PSX Object Exporter** component to every GameObject you wish to export. For more information on using Git dependencies, you can take a look at [Unity's official documentation](https://docs.unity3d.com/6000.0/Documentation/Manual/upm-git.html).
- This GameObject **must** have a mesh filter on it with a viable mesh
- The GameObject **must** have a texture on it. Colored polygons are not yet supported
- Set the desired bit depth for each object's texture in the component settings.
2. **PSX Scene Exporter:** ## Helpful Videos:
- Add the **PSX Scene Exporter** component to a GameObject in your scene (using an empty GameObject is recommended for organization).
- Click the **Export** button in the PSX Scene Exporter. You will be prompted to choose an output file location for the splashpack.
- The exporter will automatically handle texture packing into the PSX's 2D VRAM.
3. **PSX Navmesh** Both Nicolas and Bandwidth have videos on setting up the PSX Dev Extension in Visual Studio Code and setting up a PS1 scene in Unity respectively. Some of the information is repeated from the above but is here for completeness. Here are the following links to those videos:
- Add the **PSX Navmesh** component to a GameObject in your scene.
- A Navmesh surface will get automatically generated and exported into your splashpack upon scene export.
- **Important:** a PSX Player component is required within the scene for Navmesh exporting to work correctly.
- **Important:** due to a scaling and overflow bug which is currently being worked on, you may encounter some Navmesh issues. To mitigate these, turn up the GTE scaling on the scene exporter to a higher value.
### Additional Features [Setting up the PS1 Development Extension.](https://www.youtube.com/watch?v=KbAv-Ao7lzU)
SplashEdit also includes extra tools to enhance your workflow: [Setting up a Scene in Unity 6 for SplashEdit.](https://youtu.be/1JJFYptDTk0)
1. **VRAM Editor:** ## PSX Components:
- Access the VRAM Editor via Unity's **Window** context menu.
- Set framebuffer locations and preview texture packing.
- **Important:** Click on **Save Settings** in the VRAM Editor to inform the PSX Scene Exporter where to pack textures.
- When you click **Pack Textures** in the VRAM Editor, a file selection dialog will appear.
- Selecting a file will save only the VRAM data.
- If you do not wish to save VRAM, simply close the dialog.
**Note:** This action only exports the VRAM. For a complete scene export (including VRAM), use the PSX Scene Exporter component.
2. **Quantized Texture Preview:** There are currently four custom Unity components for exporting your scenes to the PS1. These include:
- Preview how your textures will look after quantization before exporting.
## Texture Requirements **PSX Object Exporter**: Attach this to any GameObject that you want to be included in your scene. The GameObject must have a mesh component and a material applied to it and must have only a texture as colored polygons are not yet supported. Finally, you can select the bit depth for the texture in the component settings. Ensure that the texture applied to the material is marked as ``Read/Write``. To check this, click on your texture, look at the Inspector on the right, and under the **Advanced** section, you will find the box for it.
- **Power of Two:** **PSX Scene Exporter**: Attach this to an empty GameObject. Click the **Export** button in the **PSX Scene Exporter**. You will be prompted to choose the output file location for ``SplashPack``. It would be ideal to place this in your Visual Studio Code project and not your Unity project, as it will be built using Nicolas's PS1 Dev Extension.
All textures must have dimensions that are a power of two (e.g., 64x64, 128x128, 256x256) with a maximum size of **256x256**.
- **No Automatic Downscaling:**
SplashEdit does not automatically downscale textures that exceed these limits.
## Output Format **PSX Player**: Attach this to any GameObject that you want to act as the player. For now, it acts as a FPS / Free Camera template. The analogue does work for it if you have the option specified in your choice emulator.
You can use the [Imhex project file](https://github.com/psxsplash/splashedit/blob/main/tools/imhex.hexproj) file to learn about the binary format
## I have a splashpack file. What now? **PSX Nav Mesh**: Attach this to any GameObject that you want to apply collisions to. These collisions are rudimentary and currently only work in a top-down view. There must be at least one existing GameObject that uses the **PSX Player** component for this to work properly.
You can preview it using [psxsplash](https://github.com/psxsplash/psxsplash).
## Contributing ## Before Exporting:
Contributions are welcome! To contribute: Check the following:
**Player and Nav Meshes**: In case it wasn't clear already, a **PSX Player** component and **PSX Nav Mesh** component must coexist in the same scene for the player to walk on the collisions properly - as both rely on eachother to work.
**Scaling**: Ensure that your Geometry Transformation Engine (or GTE) scaling is set to a reasonable value, which can be found in your GameObject holding the component. Ideally, each object in your scene should be within the GTE bounds (or red wireframe bounding box). Bandwidth does mention that there is a scaling / overflow bug with Nav Meshes being worked on and the way to circumvent this is by scaling up the GTE value to be higher.
**Texture Requirements**:
- There is no automatic downscaling so you must scale your textures in advance.
- All textures must be in powers of two ``(64x64, 128x128, 256x256)`` with a maximum size of ``256x256`` being a full PS1 texture sheet.
## Current Features:
**Automatic Scene Exporting**:\
Export your scene with one click using the **PSX Scene Exporter** component. This will include all gameobjects that use: **PSX Object Exporter**, **PSX Player**, and **PSX Nav Mesh** components respectively. Unity will ask you where to specify the ``output.bin`` file. As mentioned earlier, you will want to put it in your PSYQo project folder so it can be built into the PS1 executable.
**Texture Packing & Quantization**:\
Convert and preview your textures in a PSX-compatible format.
**Light Baking**:\
Prebakes any lights in the scene into the vertex colors of the nearest triangles in the exported mesh data.
**Nav Mesh Generation**:\
Generates a new Nav Mesh for FPS movement in your scene.
**FPS / Free Camera Template**:\
Allows you to walk around in your scene or view it from different perspectives. It's really just the way **PSX Player** and **PSX Nav Mesh** components are setup right now.
## Additional Features:
**VRAM Editor**:
- Access the VRAM Editor with Unity's **Window** context menu.
- Setup the framebuffer locations and preview texture packing.
- Click on **Save Settings** in the VRAM Editor to inform the GameObject with **PSX Scene Exporter** component where to pack the textures.
- **Important:** The current psxsplash code expects dual-buffered 320x240 vertical vram buffers.
- When you click **Pack Textures** in the VRAM Editor, a file selection dialog will appear.
- Selecting a file will save only the VRAM data. If you do not wish to save the VRAM, simply close the dialog. This is more for debugging the layout of graphics. For a complete scene export (including VRAM), use the **PSX Scene Exporter** component attached to your GameObject that contains it.
**Quantized Texture Preview**:
- Preview how your textures will look after quantization before exporting. ``(4-bit, 8-bit, and 16-bit)``
## Features in The Works:
- Templates: Both for scripting scenarios and game types (first person, third person, etc.).
- Luascript: To script said scenarios and open doors for newcomers who don't have experience with C++ (take a look at the ``lua`` branch).
## How can I contribute?
1. Fork the repository. 1. Fork the repository.
3. Submit a pull request with your changes. 2. Submit a pull request with your changes.
Please use branches. Please git clone the branch you want to edit to your machine if possible. We don't want to upload major changes to the ``main`` branch as this can cause potential problems in the near future. If you do have any major changes, please open an issue first to discuss your ideas.
For major changes, please open an issue first to discuss your ideas.
Alternatively, you can join our Discord server ["PSX.Dev"](https://discord.gg/QByKPpH) and join Bandwidth's thread in **#showcase -> "Not Just Looks: Genuine PSX in Unity"**, and we can discuss them there. This is a fairly new project so we would love the help we can get!
Personally, I'm learning a lot myself about how Unity and PSYQo can be used to make PS1 games and it's a very excruciating yet exciting endeavor!

View File

@@ -1,32 +1,35 @@
using System.Collections.Generic; using System.Collections.Generic;
using Splashedit.RuntimeCode; using Splashedit.RuntimeCode;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
namespace SplashEdit.RuntimeCode namespace SplashEdit.RuntimeCode
{ {
[RequireComponent(typeof(Renderer))] [RequireComponent(typeof(Renderer))]
public class PSXObjectExporter : MonoBehaviour public class PSXObjectExporter : MonoBehaviour
{ {
public PSXBPP BitDepth = PSXBPP.TEX_8BIT; // Defines the bit depth of the texture (e.g., 4BPP, 8BPP)
public LuaFile luaFile; public LuaFile luaFile;
public List<PSXTexture2D> Textures { get; set; } = new List<PSXTexture2D>(); // Stores the converted PlayStation-style texture public List<PSXTexture2D> Textures { get; set; } = new List<PSXTexture2D>(); // Stores the converted PlayStation-style texture
public PSXMesh Mesh { get; set; } // Stores the converted PlayStation-style mesh public PSXMesh Mesh { get; set; } // Stores the converted PlayStation-style mesh
[Header("Export Settings")]
[FormerlySerializedAs("BitDepth")]
[SerializeField] private bool PreviewNormals = false; [SerializeField] private PSXBPP bitDepth = PSXBPP.TEX_8BIT; // Defines the bit depth of the texture (e.g., 4BPP, 8BPP)
[Header("Gizmo Settings")]
[FormerlySerializedAs("PreviewNormals")]
[SerializeField] private bool previewNormals = false;
[SerializeField] private float normalPreviewLength = 0.5f; // Length of the normal lines [SerializeField] private float normalPreviewLength = 0.5f; // Length of the normal lines
private readonly Dictionary<(int, PSXBPP), PSXTexture2D> cache = new();
private void OnDrawGizmos() private void OnDrawGizmos()
{ {
if (previewNormals)
if (PreviewNormals)
{ {
MeshFilter filter = GetComponent<MeshFilter>(); MeshFilter filter = GetComponent<MeshFilter>();
if (filter != null) if (filter != null)
{ {
Mesh mesh = filter.sharedMesh; Mesh mesh = filter.sharedMesh;
Vector3[] vertices = mesh.vertices; Vector3[] vertices = mesh.vertices;
Vector3[] normals = mesh.normals; Vector3[] normals = mesh.normals;
@@ -78,8 +81,17 @@ namespace SplashEdit.RuntimeCode
if (tex2D != null) if (tex2D != null)
{ {
PSXTexture2D tex = PSXTexture2D.CreateFromTexture2D(tex2D, BitDepth); PSXTexture2D tex;
tex.OriginalTexture = tex2D; // Store reference to the original texture if (cache.ContainsKey((tex2D.GetInstanceID(), bitDepth)))
{
tex = cache[(tex2D.GetInstanceID(), bitDepth)];
}
else
{
tex = PSXTexture2D.CreateFromTexture2D(tex2D, bitDepth);
tex.OriginalTexture = tex2D; // Store reference to the original texture
cache.Add((tex2D.GetInstanceID(), bitDepth), tex);
}
Textures.Add(tex); Textures.Add(tex);
} }
} }

View File

@@ -1,25 +1,28 @@
using UnityEngine; using UnityEngine;
using UnityEngine.AI; using UnityEngine.AI;
using UnityEngine.Serialization;
namespace SplashEdit.RuntimeCode namespace SplashEdit.RuntimeCode
{ {
public class PSXPlayer : MonoBehaviour public class PSXPlayer : MonoBehaviour
{ {
public float PlayerHeight; private const float LookOutDistance = 1000f;
[HideInInspector] [FormerlySerializedAs("PlayerHeight")]
public Vector3 CamPoint; [SerializeField] private float playerHeight;
private readonly float maxDistance = 1000f;
public float PlayerHeight => playerHeight;
public Vector3 CamPoint { get; protected set; }
public void FindNavmesh() public void FindNavmesh()
{ {
NavMeshHit hit; if (NavMesh.SamplePosition(transform.position, out NavMeshHit hit, LookOutDistance, NavMesh.AllAreas))
if (NavMesh.SamplePosition(transform.position, out hit, maxDistance, NavMesh.AllAreas))
{ {
CamPoint = hit.position + new Vector3(0, PlayerHeight, 0); CamPoint = hit.position + new Vector3(0, PlayerHeight, 0);
} }
} }
void OnDrawGizmos() void OnDrawGizmos()
{ {
FindNavmesh(); FindNavmesh();

View File

@@ -35,18 +35,24 @@ namespace SplashEdit.RuntimeCode
_psxData = DataStorage.LoadData(out selectedResolution, out dualBuffering, out verticalLayout, out prohibitedAreas); _psxData = DataStorage.LoadData(out selectedResolution, out dualBuffering, out verticalLayout, out prohibitedAreas);
_exporters = FindObjectsByType<PSXObjectExporter>(FindObjectsSortMode.None); _exporters = FindObjectsByType<PSXObjectExporter>(FindObjectsSortMode.None);
foreach (PSXObjectExporter exp in _exporters) for (int i = 0; i < _exporters.Length; i++)
{ {
PSXObjectExporter exp = _exporters[i];
EditorUtility.DisplayProgressBar($"{nameof(PSXSceneExporter)}", $"Export {nameof(PSXObjectExporter)}", ((float)i)/ _exporters.Length);
exp.CreatePSXTextures2D(); exp.CreatePSXTextures2D();
exp.CreatePSXMesh(GTEScaling); exp.CreatePSXMesh(GTEScaling);
} }
_navmeshes = FindObjectsByType<PSXNavMesh>(FindObjectsSortMode.None); _navmeshes = FindObjectsByType<PSXNavMesh>(FindObjectsSortMode.None);
foreach (PSXNavMesh navmesh in _navmeshes) for (int i = 0; i < _navmeshes.Length; i++)
{ {
PSXNavMesh navmesh = _navmeshes[i];
EditorUtility.DisplayProgressBar($"{nameof(PSXSceneExporter)}", $"Export {nameof(PSXNavMesh)}", ((float)i) / _navmeshes.Length);
navmesh.CreateNavmesh(GTEScaling); navmesh.CreateNavmesh(GTEScaling);
} }
EditorUtility.ClearProgressBar();
PackTextures(); PackTextures();
PSXPlayer player = FindObjectsByType<PSXPlayer>(FindObjectsSortMode.None).FirstOrDefault(); PSXPlayer player = FindObjectsByType<PSXPlayer>(FindObjectsSortMode.None).FirstOrDefault();

View File

@@ -342,16 +342,24 @@ namespace SplashEdit.RuntimeCode
} }
string assetPath = AssetDatabase.GetAssetPath(texture); string assetPath = AssetDatabase.GetAssetPath(texture);
var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter; var tImporter = AssetImporter.GetAtPath(assetPath) as TextureImporter;
bool needReimport = false;
if (tImporter != null) if (tImporter != null)
{ {
if (tImporter.maxTextureSize > MaxTextureSize) if (tImporter.maxTextureSize > MaxTextureSize)
{ {
tImporter.maxTextureSize = MaxTextureSize; tImporter.maxTextureSize = MaxTextureSize;
needReimport = true;
}
if (tImporter.isReadable != isReadable)
{
tImporter.isReadable = isReadable;
needReimport = true;
}
if (needReimport)
{
AssetDatabase.ImportAsset(assetPath);
AssetDatabase.Refresh();
} }
tImporter.isReadable = isReadable;
AssetDatabase.ImportAsset(assetPath);
AssetDatabase.Refresh();
} }
} }
} }