Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a world data RMB block editor to Unity DFU tools #2497

Merged
merged 15 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Assets/Game/Addons/RmbBlockEditor.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 106 additions & 0 deletions Assets/Game/Addons/RmbBlockEditor/Automap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Project: Daggerfall Tools For Unity
// Copyright: Copyright (C) 2009-2022 Daggerfall Workshop
// Web Site: http://www.dfworkshop.net
// License: MIT License (http://www.opensource.org/licenses/mit-license.php)
// Source Code: https://github.com/Interkarma/daggerfall-unity
// Original Author: Podleron (podleron@gmail.com)

using System;
using UnityEngine;

namespace DaggerfallWorkshop.Game.Addons.RmbBlockEditor
{
#if UNITY_EDITOR
[ExecuteInEditMode]
public class Automap : MonoBehaviour
{
public Byte[] automapData;
private MeshRenderer renderer;

public void CreateObject(Byte[] automapData)
{
this.automapData = automapData;
var groundPlane = GameObject.CreatePrimitive(PrimitiveType.Plane);
groundPlane.name = "plane";
groundPlane.transform.parent = transform;
groundPlane.transform.localScale = new Vector3(10.24f, 1f, 10.24f);
groundPlane.transform.position = new Vector3(51.2f, 0, -51.2f);
groundPlane.transform.rotation = Quaternion.Euler(0, 0, 0);
renderer = groundPlane.GetComponent<MeshRenderer>();
Update();
}

public void Update()
{
Texture2D tex = new Texture2D(64, 64, TextureFormat.ARGB32, false);
Color32[] colors = new Color32[64 * 64];
for (var i = 0; i < automapData.Length; i++)
{
var lineMax = (Math.Floor(i / 64f) + 1) * 64;
var previousLineMax = Math.Floor(i / 64f) * 64;
var colorIndex = (int)(lineMax - i - 1 + previousLineMax);
switch (automapData[i])
{
// guilds
case 12: // guildhall
case 15: // temple
colors[colorIndex] = DaggerfallUnity.Settings.AutomapTempleColor;
break;
// shops
case 1: // alchemist
case 3: // armorer
case 4: // bank
case 6: // bookseller
case 7: // clothing store
case 9: // gem store
case 10: // general store
case 11: // library
case 13: // pawn shop
case 14: // weapon smith
colors[colorIndex] = DaggerfallUnity.Settings.AutomapShopColor;
break;
case 16: // tavern
colors[colorIndex] = DaggerfallUnity.Settings.AutomapTavernColor;
break;
// common
case 2: // house for sale
case 5: // town4
case 8: // furniture store
case 17: // palace
case 18: // house 1
case 19: // house 2
case 20: // house 3
case 21: // house 4
case 22: // house 5 (hedge)
case 23: // house 6
case 24: // town23
colors[colorIndex] = DaggerfallUnity.Settings.AutomapHouseColor;
break;
case 25: // ship
case 117: // special 1
case 224: // special 2
case 250: // special 3
case 251: // special 4
break;
case 0:
colors[colorIndex].r = 0;
colors[colorIndex].g = 0;
colors[colorIndex].b = 0;
colors[colorIndex].a = 0;
break;
default: // unknown
colors[colorIndex].r = 255;
colors[colorIndex].g = 0;
colors[colorIndex].b = automapData[i];
colors[colorIndex].a = 255;
break;
}
}

tex.SetPixels32(0, 0, 64, 64, colors);
tex.Apply();
renderer.sharedMaterial.mainTexture = tex;
}
}
#endif
}
3 changes: 3 additions & 0 deletions Assets/Game/Addons/RmbBlockEditor/Automap.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

259 changes: 259 additions & 0 deletions Assets/Game/Addons/RmbBlockEditor/Building.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// Project: Daggerfall Tools For Unity
// Copyright: Copyright (C) 2009-2022 Daggerfall Workshop
// Web Site: http://www.dfworkshop.net
// License: MIT License (http://www.opensource.org/licenses/mit-license.php)
// Source Code: https://github.com/Interkarma/daggerfall-unity
// Original Author: Podleron (podleron@gmail.com)

using System;
using DaggerfallConnect;
using UnityEngine;
using DaggerfallConnect.Arena2;
using DaggerfallWorkshop.Utility.AssetInjection;
using UnityEditor;

namespace DaggerfallWorkshop.Game.Addons.RmbBlockEditor
{
#if UNITY_EDITOR
[ExecuteInEditMode]
[SelectionBase]
[Serializable]
public class Building : MonoBehaviour
{

public ushort NameSeed;
public ushort FactionId;
public short Sector;
public ushort LocationId;
public DFLocation.BuildingTypes BuildingType;
public byte Quality;

public int YRotation;

public int XPos;
public int ZPos;
public int ModelsYPos;

private int yRotationOld;

private int xPosOld;
private int zPosOld;
private int yPosOld;

private DFBlock.RmbSubRecord SubRecord;

public void CreateObject(DFLocation.BuildingData buildingData, DFBlock.RmbSubRecord subRecord)
{
SubRecord = subRecord;

FactionId = buildingData.FactionId;
NameSeed = buildingData.NameSeed;
Sector = buildingData.Sector;
LocationId = buildingData.LocationId;
BuildingType = buildingData.BuildingType;
Quality = buildingData.Quality;

YRotation = subRecord.YRotation;

XPos = subRecord.XPos;
ZPos = subRecord.ZPos;
ModelsYPos = subRecord.Exterior.Block3dObjectRecords[0].YPos;

SaveOldRotation();
SaveOldPosition();

Add3DObjects();
AddFlatObjects();
AddPersonObjects();

UpdateScenePosition();
UpdateSceneRotation();
}

public DFBlock.RmbSubRecord GetSubRecord()
{
var record = new DFBlock.RmbSubRecord();
record.XPos = XPos;
record.ZPos = ZPos;
record.YRotation = YRotation;
record.Exterior = SubRecord.Exterior;
record.Interior = SubRecord.Interior;

return record;
}

public void SetSubRecord(DFBlock.RmbSubRecord subRecord)
{
SubRecord.Exterior = subRecord.Exterior;
SubRecord.Interior = subRecord.Interior;

// A new GameObject needs to be added to the scene with the new Exterior
var newGo = new GameObject(gameObject.name);
var newBuilding = newGo.AddComponent<Building>();
newBuilding.CreateObject(GetBuildingData(), GetSubRecord());
newGo.transform.parent = gameObject.transform.parent;
try
{
Selection.SetActiveObjectWithContext(newGo, null);
DestroyImmediate(gameObject);
}
catch (Exception error)
{
Debug.LogError(error);
}
}

public DFLocation.BuildingData GetBuildingData()
{
var record = new DFLocation.BuildingData();
record.NameSeed = NameSeed;
record.FactionId = FactionId;
record.Sector = Sector;
record.LocationId = LocationId;
record.BuildingType = BuildingType;
record.Quality = Quality;

return record;
}

public void Start()
{
SceneView.duringSceneGui += OnSceneGUI;
}

private void OnSceneGUI(SceneView sceneView)
{
// If rotation has been done on x or z, ignore it and go back to the old rotation
if (0 != transform.rotation.x || 0 != transform.rotation.z)
{
UpdateSceneRotation();
UpdateScenePosition();
return;
}

// Only update the values when the transformation is complete (when a mouseup is detected)
var mouseUp = Event.current.type == EventType.MouseUp;
if (!mouseUp) return;

// Calculate the new values, based on the scene rotation and position
var rotation = transform.rotation.eulerAngles;
YRotation = -(int)(rotation.y * BlocksFile.RotationDivisor);
XPos = (int)Math.Round(transform.position.x / MeshReader.GlobalScale);
ZPos = -(int)Math.Round(transform.position.z / MeshReader.GlobalScale);
ModelsYPos = -(int)Math.Round(transform.position.y / MeshReader.GlobalScale);

UpdateExteriorModelsYPos();
UpdateSceneRotation();
UpdateScenePosition();
}

public void Update()
{
// Object rotation has been changed in the editor fields
if (YRotation != yRotationOld)
{
SaveOldRotation();
UpdateSceneRotation();
return;
}

// Object position has been changed in the editor fields
if (XPos != xPosOld || ZPos != zPosOld || ModelsYPos != yPosOld)
{
SaveOldPosition();
UpdateExteriorModelsYPos();
UpdateScenePosition();
}
}

public void Export(string fileName)
{
BuildingReplacementData data = new BuildingReplacementData()
{
FactionId = FactionId,
BuildingType = (int)BuildingType,
Quality = Quality,
NameSeed = NameSeed,
RmbSubRecord = GetSubRecord()
};
RmbBlockHelper.SaveBuildingFile(data, fileName);
}

private void Add3DObjects()
{
var obj3D = RmbBlockHelper.AddBuilding3dObjects(SubRecord.Exterior.Block3dObjectRecords, ModelsYPos);
obj3D.transform.parent = transform;
}

private void AddFlatObjects()
{
var flats = new GameObject("Flats");
flats.transform.parent = transform;

foreach (var blockRecord in SubRecord.Exterior.BlockFlatObjectRecords)
{
var subRecordRotation =
Quaternion.AngleAxis(YRotation / BlocksFile.RotationDivisor, Vector3.up);
var go = RmbBlockHelper.AddFlatObject(blockRecord, subRecordRotation);
go.transform.parent = flats.transform;
}
}

private void AddPersonObjects()
{
var people = new GameObject("People");
people.transform.parent = transform;

foreach (var blockRecord in SubRecord.Exterior.BlockPeopleRecords)
{
var go = RmbBlockHelper.AddPersonObject(blockRecord);
go.transform.parent = people.transform;
}
}

private void SaveOldPosition()
{
xPosOld = XPos;
zPosOld = ZPos;
yPosOld = ModelsYPos;
}

private void SaveOldRotation()
{
yRotationOld = YRotation;
}

private void UpdateExteriorModelsYPos()
{
if (SubRecord.Exterior.Block3dObjectRecords.Length == 0)
{
return;
}

var main = SubRecord.Exterior.Block3dObjectRecords[0];

for (var i = 0; i < SubRecord.Exterior.Block3dObjectRecords.Length; i++)
{
SubRecord.Exterior.Block3dObjectRecords[i].YPos = ModelsYPos + (SubRecord.Exterior.Block3dObjectRecords[i].YPos - main.YPos);
}
}

private void UpdateScenePosition()
{
var vect = new Vector3(XPos, -ModelsYPos, -ZPos) * MeshReader.GlobalScale;
transform.position = vect;
}

private void UpdateSceneRotation()
{
var buildingRotation = new Vector3(0, -YRotation / BlocksFile.RotationDivisor, 0);
transform.rotation = Quaternion.Euler(buildingRotation);
}

private void OnDestroy()
{
SceneView.duringSceneGui -= OnSceneGUI;
}
}
#endif
}
3 changes: 3 additions & 0 deletions Assets/Game/Addons/RmbBlockEditor/Building.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading