mirror of
https://github.com/riperiperi/Simitone.git
synced 2025-01-22 09:11:52 -05:00
[UI] Skin/Pet Selector
This commit is contained in:
parent
4ac38452dc
commit
00f8cd6727
8 changed files with 532 additions and 7 deletions
|
@ -75,6 +75,7 @@
|
|||
<Compile Include="UI\Panels\LiveSubpanels\UISubpanel.cs" />
|
||||
<Compile Include="UI\Panels\LotControls\UIArchTouchHelper.cs" />
|
||||
<Compile Include="UI\Panels\LotControls\UICallNeighborAlert.cs" />
|
||||
<Compile Include="UI\Panels\LotControls\UISelectSkinAlert.cs" />
|
||||
<Compile Include="UI\Panels\UIClockPanel.cs" />
|
||||
<Compile Include="UI\Panels\UICutawayPanel.cs" />
|
||||
<Compile Include="UI\Panels\UIHouseSelectPanel.cs" />
|
||||
|
@ -111,6 +112,7 @@
|
|||
<ProjectReference Include="..\..\..\FreeSO\Other\libs\FSOMonoGame\MonoGame.Framework\MonoGame.Framework.Windows.csproj">
|
||||
<Project>{7de47032-a904-4c29-bd22-2d235e8d91ba}</Project>
|
||||
<Name>MonoGame.Framework.Windows</Name>
|
||||
<Private>False</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\FreeSO\TSOClient\FSO.UI\FSO.UI.csproj">
|
||||
<Project>{73e2ad5b-720b-4ef3-9b7c-55931d0ec693}</Project>
|
||||
|
|
|
@ -8,7 +8,6 @@ using System;
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System.Threading;
|
||||
using LogThis;
|
||||
using FSO.Common.Rendering.Framework;
|
||||
using FSO.LotView;
|
||||
using FSO.HIT;
|
||||
|
@ -98,10 +97,11 @@ namespace Simitone.Client
|
|||
|
||||
FSO.LotView.WorldConfig.Current = new FSO.LotView.WorldConfig()
|
||||
{
|
||||
LightingMode = 3,
|
||||
LightingMode = settings.LightingMode,
|
||||
SmoothZoom = settings.SmoothZoom,
|
||||
SurroundingLots = settings.SurroundingLotMode,
|
||||
AA = settings.AntiAlias
|
||||
AA = settings.AntiAlias,
|
||||
Directional = settings.DirectionalLight3D
|
||||
};
|
||||
|
||||
OperatingSystem os = Environment.OSVersion;
|
||||
|
@ -123,7 +123,11 @@ namespace Simitone.Client
|
|||
GameFacade.GraphicsDevice = GraphicsDevice;
|
||||
GameFacade.GraphicsDeviceManager = Graphics;
|
||||
GameFacade.Cursor = new CursorManager(GraphicsDevice);
|
||||
if (!GameFacade.Linux) GameFacade.Cursor.Init(GlobalSettings.Default.TS1HybridPath, true);
|
||||
if (!GameFacade.Linux)
|
||||
{
|
||||
CurLoader.BmpLoaderFunc = ImageLoader.BaseFunction;
|
||||
GameFacade.Cursor.Init(GlobalSettings.Default.TS1HybridPath, true);
|
||||
}
|
||||
|
||||
/** Init any computed values **/
|
||||
GameFacade.Init();
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
using FSO.Client;
|
||||
using FSO.Client.UI.Framework;
|
||||
using FSO.Common;
|
||||
using FSO.Common.Rendering.Framework;
|
||||
using FSO.Common.Rendering.Framework.Camera;
|
||||
using FSO.Common.Rendering.Framework.Model;
|
||||
using FSO.Common.Utils;
|
||||
using FSO.Content;
|
||||
using FSO.Content.TS1;
|
||||
using FSO.LotView.Model;
|
||||
using FSO.SimAntics;
|
||||
using FSO.SimAntics.Engine.TSOTransaction;
|
||||
using FSO.SimAntics.NetPlay;
|
||||
using FSO.SimAntics.NetPlay.Drivers;
|
||||
using FSO.SimAntics.NetPlay.Model;
|
||||
using FSO.Vitaboy;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Simitone.Client.UI.Controls;
|
||||
using Simitone.Client.UI.Panels.WorldUI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Simitone.Client.UI.Panels.LotControls
|
||||
{
|
||||
public class UISelectSkinAlert : UIMobileDialog
|
||||
{
|
||||
public UISelectSkinPanel NPanel;
|
||||
/*
|
||||
public short SelectedNeighbour
|
||||
{
|
||||
get
|
||||
{
|
||||
return NPanel.SelectedNeighbour;
|
||||
}
|
||||
}*/
|
||||
|
||||
public event Action<short> OnResult;
|
||||
|
||||
public UISelectSkinAlert(VMAvatar target, string type, VM vm)
|
||||
{
|
||||
var pet = type == "cat" || type == "dog";
|
||||
Caption = pet ? "Adopt a Pet" : "Please Select Outfit";
|
||||
SetHeight(600);
|
||||
NPanel = new UISelectSkinPanel(target, type, vm);
|
||||
NPanel.Position = new Microsoft.Xna.Framework.Vector2((Width - 1030) / 2, 110);
|
||||
NPanel.OnResult += (res) => { OnResult?.Invoke(res); Close(); };
|
||||
Add(NPanel);
|
||||
}
|
||||
|
||||
public override void GameResized()
|
||||
{
|
||||
base.GameResized();
|
||||
NPanel.Position = new Microsoft.Xna.Framework.Vector2((Width - 1030) / 2, 110);
|
||||
}
|
||||
}
|
||||
|
||||
public class UISelectSkinPanel : UIContainer{
|
||||
public FSO.SimAntics.VM vm { get; set; }
|
||||
public BasicCamera Camera;
|
||||
|
||||
public uint BaseGUID = 0x7FD96B54; //all of our templates should be of this kind.
|
||||
public string CurrentCode;
|
||||
public string CurrentSkin; //
|
||||
|
||||
public VMAvatar[] BodyAvatars;
|
||||
public List<string> ActiveBodies;
|
||||
public List<string> ActiveHandgroupTex;
|
||||
public List<string> ActiveBodyTex;
|
||||
|
||||
public float HeadPosition = -9f;
|
||||
public float BodyPosition = -9f;
|
||||
|
||||
public float HeadSpeed = 0f;
|
||||
public float BodySpeed = 0f;
|
||||
public float XLast = -1f;
|
||||
|
||||
public int HeadPositionLast = 0;
|
||||
public int BodyPositionLast = 0;
|
||||
public bool Pet;
|
||||
|
||||
public _3DTargetScene Scene;
|
||||
public string CollectionType = "b";
|
||||
|
||||
public event Action<short> OnResult;
|
||||
public UIBigButton OKButton;
|
||||
public UIBigButton CancelButton;
|
||||
|
||||
public short ResultInd
|
||||
{
|
||||
get
|
||||
{
|
||||
var i = (int)DirectionUtils.PosMod(Math.Round(BodyPosition + 8), ActiveBodies.Count);
|
||||
return (short)i;
|
||||
}
|
||||
}
|
||||
|
||||
public string ResultBody
|
||||
{
|
||||
get
|
||||
{
|
||||
var i = (int)DirectionUtils.PosMod(Math.Round(BodyPosition + 8), ActiveBodies.Count);
|
||||
return ActiveBodies[i] + ",BODY=" + ActiveBodyTex[i];
|
||||
}
|
||||
}
|
||||
|
||||
public UISelectSkinPanel(VMAvatar target, string type, VM vm) {
|
||||
this.vm = vm;
|
||||
if (target != null)
|
||||
{
|
||||
BaseGUID = target.Object.OBJ.GUID;
|
||||
CollectionType = type;
|
||||
var bodyStrings = target.Object.Resource.Get<FSO.Files.Formats.IFF.Chunks.STR>(target.Object.OBJ.BodyStringID);
|
||||
type = bodyStrings.GetString(1).Substring(4);
|
||||
type = type.Substring(0, type.IndexOf('_'));
|
||||
|
||||
CurrentSkin = bodyStrings.GetString(14);
|
||||
} else
|
||||
{
|
||||
Pet = true;
|
||||
if (type == "cat") BaseGUID = 0x7BEA0977;
|
||||
else if (type == "dog") BaseGUID = 0x4A70DF92;
|
||||
}
|
||||
Camera = new BasicCamera(GameFacade.GraphicsDevice, new Vector3(5, 1, 0), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
|
||||
Camera.NearPlane = 0.001f;
|
||||
Scene = new _3DTargetScene(GameFacade.GraphicsDevice, Camera, new Point(1030, 500), GlobalSettings.Default.AntiAlias?8:0);
|
||||
Scene.Initialize(GameFacade.Scenes);
|
||||
|
||||
InitializeLot();
|
||||
PopulateSimType(type);
|
||||
|
||||
OKButton = new UIBigButton(true);
|
||||
OKButton.Caption = GameFacade.Strings.GetString("142", "0");
|
||||
OKButton.Position = new Microsoft.Xna.Framework.Vector2((515 + 300)-137, 370);
|
||||
OKButton.OnButtonClick += (btn) => { OnResult?.Invoke(ResultInd); };
|
||||
OKButton.Width = 275;
|
||||
Add(OKButton);
|
||||
|
||||
CancelButton = new UIBigButton(true);
|
||||
CancelButton.Caption = GameFacade.Strings.GetString("142", "1");
|
||||
CancelButton.Position = new Microsoft.Xna.Framework.Vector2((515 - 300) - 137, 370);
|
||||
CancelButton.OnButtonClick += (btn) => { OnResult?.Invoke(-1); };
|
||||
CancelButton.Width = 275;
|
||||
Add(CancelButton);
|
||||
}
|
||||
|
||||
public override void PreDraw(UISpriteBatch batch)
|
||||
{
|
||||
base.PreDraw(batch);
|
||||
Camera.Position = new Vector3(10f, 4f, 0);
|
||||
Camera.Target = new Vector3(4f, Pet?0f:0.8f, 0);
|
||||
GameFacade.GraphicsDevice.RasterizerState = Microsoft.Xna.Framework.Graphics.RasterizerState.CullCounterClockwise;
|
||||
Scene.Draw(GameFacade.GraphicsDevice);
|
||||
GameFacade.GraphicsDevice.RasterizerState = Microsoft.Xna.Framework.Graphics.RasterizerState.CullNone;
|
||||
}
|
||||
|
||||
public override void Draw(UISpriteBatch batch)
|
||||
{
|
||||
base.Draw(batch);
|
||||
DrawLocalTexture(batch, Scene.Target, new Vector2(0, 0));
|
||||
}
|
||||
|
||||
public override void Update(UpdateState state)
|
||||
{
|
||||
base.Update(state);
|
||||
UpdateCarousel(state);
|
||||
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
var relPos = BodyPosition + i - 9;
|
||||
relPos = (float)DirectionUtils.PosMod(relPos, 18);
|
||||
if (relPos > 9) relPos += 6;
|
||||
var angle = (relPos / 24) * (Math.PI * 2);
|
||||
|
||||
var pos = new Vector3(0 + 4.5f * (float)Math.Cos(angle), 0, 0 + 4.5f * (float)Math.Sin(angle));
|
||||
BodyAvatars[i].Avatar.RotationY = -(float)angle + (float)Math.PI / 2;
|
||||
var ang2 = (float)Math.Abs(DirectionUtils.PosMod(angle + Math.PI, Math.PI*2) - Math.PI);
|
||||
//if (ang2 > Math.PI * 2) ang2 = 255;
|
||||
var ava = BodyAvatars[i].Avatar;
|
||||
ava.AmbientLight = Vector4.One * Math.Max(0, Math.Min(1, 2-ang2));
|
||||
if (i != DirectionUtils.PosMod(-Math.Round(BodyPosition + 9), 18)) ava.AmbientLight *= 0.5f;
|
||||
else ava.AmbientLight *= 1.1f;
|
||||
ava.Position = pos;
|
||||
ava.Scale = Vector3.One * (Pet ? 1 : 1 / 2f);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateSimType(string simtype) // cat / dog / (ma/fa/mc/fc/uc) + (fit/fat/skn/chd)
|
||||
{
|
||||
CurrentCode = simtype;
|
||||
var col = Content.Get().BCFGlobal.CollectionsByName[CollectionType];
|
||||
var bodies = col.ClothesByAvatarType[simtype];
|
||||
|
||||
var tex = (TS1AvatarTextureProvider)Content.Get().AvatarTextures;
|
||||
var texnames = tex.GetAllNames();
|
||||
ActiveBodies = bodies;
|
||||
|
||||
ActiveBodyTex = bodies.Select(x => RemoveExt(texnames.FirstOrDefault(y => y.StartsWith(ExtractID(x, CurrentSkin))))).ToList();
|
||||
ActiveHandgroupTex = bodies.Select(x => (RemoveExt(texnames.FirstOrDefault(y => y == "huao" + FindHG(x))) ?? "huao" + CurrentSkin).Substring(4)).ToList();
|
||||
|
||||
for (int i = 0; i < ActiveBodies.Count; i++)
|
||||
{
|
||||
if (ActiveBodyTex[i] == null)
|
||||
{
|
||||
ActiveBodyTex.RemoveAt(i);
|
||||
ActiveHandgroupTex.RemoveAt(i);
|
||||
ActiveBodies.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
|
||||
BodyPositionLast = 0;
|
||||
PopulateReal();
|
||||
}
|
||||
|
||||
private string FindHG(string item)
|
||||
{
|
||||
var ind = item.IndexOf('_');
|
||||
if (ind != -1) item = item.Substring(ind);
|
||||
return item;
|
||||
}
|
||||
|
||||
private string RemoveExt(string item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
var ind = item.LastIndexOf('.');
|
||||
if (ind != -1) return item.Substring(0, ind);
|
||||
return item;
|
||||
}
|
||||
|
||||
private string ExtractID(string item, string skncol)
|
||||
{
|
||||
var ind = item.IndexOf('_');
|
||||
if (ind != -1) item = item.Substring(0, ind);
|
||||
return item + skncol;
|
||||
}
|
||||
|
||||
private string InsertSkinColor(string name, string skncol)
|
||||
{
|
||||
var ind = name.IndexOf('_');
|
||||
if (ind != -1) name = name.Insert(ind, skncol);
|
||||
return name;
|
||||
}
|
||||
|
||||
private void UpdateCarousel(UpdateState state)
|
||||
{
|
||||
var frac = 60f / FSOEnvironment.RefreshRate;
|
||||
var minSpeed = (Math.PI / 240f) * frac;
|
||||
var mult = (float)Math.Pow(0.95, frac);
|
||||
|
||||
var moving = 0;
|
||||
|
||||
if (state.MouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
|
||||
{
|
||||
var pos = GlobalPoint(state.MouseState.Position.ToVector2());
|
||||
if (XLast == -1)
|
||||
{
|
||||
if (pos.Y > -100)
|
||||
XLast = state.MouseState.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos.Y > 0 && pos.Y < 375)
|
||||
{
|
||||
BodySpeed = ((XLast - state.MouseState.X) / 200f) * frac;
|
||||
moving = 1;
|
||||
}
|
||||
XLast = state.MouseState.X;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XLast = -1;
|
||||
}
|
||||
|
||||
BodySpeed = BodySpeed * mult;
|
||||
if (Math.Abs(BodySpeed) < minSpeed && moving != 1)
|
||||
{
|
||||
var targInt = (int)Math.Round(BodyPosition);
|
||||
BodySpeed = (float)Math.Max(-minSpeed, Math.Min(minSpeed, targInt - BodyPosition));
|
||||
}
|
||||
|
||||
HeadSpeed = HeadSpeed * mult;
|
||||
if (Math.Abs(HeadSpeed) < minSpeed && moving != 2)
|
||||
{
|
||||
var targInt = (int)Math.Round(HeadPosition);
|
||||
HeadSpeed = (float)Math.Max(-minSpeed, Math.Min(minSpeed, targInt - HeadPosition));
|
||||
}
|
||||
|
||||
HeadPosition += HeadSpeed;
|
||||
BodyPosition += BodySpeed;
|
||||
|
||||
var room = 0;// vm.Context.GetRoomAt(LotTilePos.FromBigTile(28, 21, 1));
|
||||
foreach (var body in BodyAvatars) body.SetRoom(65534);
|
||||
|
||||
var curbody = (int)BodyPosition;
|
||||
if (curbody != BodyPositionLast)
|
||||
{
|
||||
FSO.HIT.HITVM.Get().PlaySoundEvent(FSO.Client.UI.Model.UISounds.Click);
|
||||
int replacePos = (int)DirectionUtils.PosMod((-BodyPositionLast), 18);
|
||||
int increment = 1;
|
||||
if (curbody < BodyPositionLast) //start adding after last position's compliment position
|
||||
{
|
||||
increment = -1;
|
||||
replacePos = (int)DirectionUtils.PosMod((-BodyPositionLast), 18);
|
||||
}
|
||||
var total = Math.Abs(curbody - BodyPositionLast);
|
||||
for (int i = 0; i < total; i++)
|
||||
{
|
||||
if (increment == -1)
|
||||
{
|
||||
SetBody(BodyAvatars[replacePos], BodyPositionLast - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetBody(BodyAvatars[replacePos], BodyPositionLast + 17);
|
||||
}
|
||||
BodyPositionLast += increment;
|
||||
replacePos = ((replacePos - increment) + 18) % 18;
|
||||
|
||||
}
|
||||
BodyPositionLast = curbody;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBody(VMAvatar body, int i)
|
||||
{
|
||||
i = (int)DirectionUtils.PosMod(i, ActiveBodies.Count);
|
||||
var oft = new Outfit() { TS1AppearanceID = ActiveBodies[i] + ".apr", TS1TextureID = ActiveBodyTex[i] };
|
||||
|
||||
if (!Pet)
|
||||
{
|
||||
var code = CurrentCode[0];
|
||||
if (CurrentCode[1] != 'a') code = 'u';
|
||||
var hg = ActiveHandgroupTex[i];
|
||||
oft.LiteralHandgroup = new HandGroup()
|
||||
{
|
||||
TS1HandSet = true,
|
||||
LightSkin = new HandSet()
|
||||
{
|
||||
LeftHand = new Hand()
|
||||
{
|
||||
Idle = new Gesture() { Name = "h" + code + "lo.apr", TexName = "huao" + hg },
|
||||
Pointing = new Gesture() { Name = "h" + code + "lp.apr", TexName = "huap" + hg },
|
||||
Fist = new Gesture() { Name = "h" + code + "lc.apr", TexName = "huac" + hg }
|
||||
},
|
||||
RightHand = new Hand()
|
||||
{
|
||||
Idle = new Gesture() { Name = "h" + code + "ro.apr", TexName = "huao" + hg },
|
||||
Pointing = new Gesture() { Name = "h" + code + "rp.apr", TexName = "huap" + hg },
|
||||
Fist = new Gesture() { Name = "h" + code + "rc.apr", TexName = "huac" + hg }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
body.BodyOutfit = new FSO.SimAntics.Model.VMOutfitReference(oft);
|
||||
}
|
||||
|
||||
private void PopulateReal()
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var body in BodyAvatars)
|
||||
{
|
||||
SetBody(body, 17 - i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
#region Lot Content Stuff
|
||||
public void CleanupLastWorld()
|
||||
{
|
||||
if (vm == null) return;
|
||||
|
||||
foreach (var body in BodyAvatars)
|
||||
{
|
||||
body.Delete(true, vm.Context);
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeLot()
|
||||
{
|
||||
BodyAvatars = new VMAvatar[18];
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
BodyAvatars[i] = (VMAvatar)vm.Context.CreateObjectInstance(BaseGUID, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true).BaseObject;
|
||||
BodyAvatars[i].SetValue(FSO.SimAntics.Model.VMStackObjectVariable.Hidden, 1);
|
||||
Scene.Add(BodyAvatars[i].Avatar);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -261,6 +261,27 @@ namespace Simitone.Client.UI.Panels
|
|||
BlockingDialog = null;
|
||||
};
|
||||
return;
|
||||
|
||||
case VMDialogType.TS1PetChoice:
|
||||
case VMDialogType.TS1Clothes:
|
||||
var ts1categories = new string[] { "b", "f", "s", "l", "w", "h" };
|
||||
var pet = type == VMDialogType.TS1PetChoice;
|
||||
var stackObj = info.Caller.Thread.Stack.Last().StackObject;
|
||||
|
||||
var skin = new UISelectSkinAlert(pet?null:(info.Caller as VMAvatar), pet?((stackObj as VMAvatar).IsCat?"cat":"dog"):ts1categories[info.Caller.Thread.TempRegisters[0]], vm);
|
||||
BlockingDialog = skin;
|
||||
UIScreen.GlobalShowDialog(skin, true);
|
||||
skin.OnResult += (result) =>
|
||||
{
|
||||
vm.SendCommand(new VMNetDialogResponseCmd
|
||||
{
|
||||
ActorUID = info.Caller.PersistID,
|
||||
ResponseCode = (byte)((result > -1)?1:0),
|
||||
ResponseText = result.ToString()
|
||||
});
|
||||
BlockingDialog = null;
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
var alert = new UIMobileAlert(options);
|
||||
|
@ -432,7 +453,15 @@ namespace Simitone.Client.UI.Panels
|
|||
{
|
||||
obj = GotoObject;
|
||||
}
|
||||
if (obj != null)
|
||||
if (obj is VMAvatar && state.CtrlDown)
|
||||
{
|
||||
//debug switch to avatar
|
||||
vm.SendCommand(new VMNetChangeControlCmd()
|
||||
{
|
||||
TargetID = obj.ObjectID
|
||||
});
|
||||
}
|
||||
else if (obj != null)
|
||||
{
|
||||
obj = obj.MultitileGroup.GetInteractionGroupLeader(obj);
|
||||
if (obj is VMGameObject && ((VMGameObject)obj).Disabled > 0)
|
||||
|
|
|
@ -31,6 +31,7 @@ using Simitone.Client.UI.Panels;
|
|||
using FSO.Client.UI.Controls;
|
||||
using Simitone.Client.Utils;
|
||||
using FSO.SimAntics.Utils;
|
||||
using FSO.SimAntics.Model.TS1Platform;
|
||||
|
||||
namespace Simitone.Client.UI.Screens
|
||||
{
|
||||
|
@ -970,7 +971,7 @@ namespace Simitone.Client.UI.Screens
|
|||
{
|
||||
var marshal = new FSO.SimAntics.Marshals.VMMarshal();
|
||||
marshal.Deserialize(file);
|
||||
|
||||
marshal.PlatformState = new VMTS1LotState();
|
||||
vm.Load(marshal);
|
||||
vm.Reset();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@ using FSO.LotView;
|
|||
using Simitone.Client;
|
||||
using Simitone.Windows.GameLocator;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
|
@ -61,6 +64,9 @@ namespace Simitone.Windows
|
|||
|
||||
#endregion
|
||||
|
||||
FSO.Files.ImageLoaderHelpers.BitmapFunction = BitmapReader;
|
||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||
|
||||
FSOEnvironment.SoftwareDepth = false;
|
||||
FSOEnvironment.UseMRT = true;
|
||||
|
||||
|
@ -80,6 +86,7 @@ namespace Simitone.Windows
|
|||
GlobalSettings.Default.TS1HybridEnable = true;
|
||||
GlobalSettings.Default.TS1HybridPath = gameLocator.FindTheSims1();
|
||||
GlobalSettings.Default.ClientVersion = "0";
|
||||
GlobalSettings.Default.LightingMode = 3;
|
||||
GlobalSettings.Default.AntiAlias = true;
|
||||
|
||||
GameFacade.DirectX = useDX;
|
||||
|
@ -99,6 +106,91 @@ namespace Simitone.Windows
|
|||
{
|
||||
e.Cancel = !(GameFacade.Screens.CurrentUIScreen?.CloseAttempt() ?? true);
|
||||
}
|
||||
|
||||
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
var exception = e.ExceptionObject;
|
||||
if (exception is OutOfMemoryException)
|
||||
{
|
||||
MessageBox.Show(e.ExceptionObject.ToString(), "Out of Memory! FreeSO needs to close.");
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show(e.ExceptionObject.ToString(), "A fatal error occured! Screenshot this dialog and post it on Discord.");
|
||||
}
|
||||
}
|
||||
|
||||
public static Tuple<byte[], int, int> BitmapReader(Stream str)
|
||||
{
|
||||
Bitmap image = (Bitmap)Bitmap.FromStream(str);
|
||||
try
|
||||
{
|
||||
// Fix up the Image to match the expected format
|
||||
image = (Bitmap)image.RGBToBGR();
|
||||
|
||||
var data = new byte[image.Width * image.Height * 4];
|
||||
|
||||
BitmapData bitmapData = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
|
||||
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
if (bitmapData.Stride != image.Width * 4)
|
||||
throw new NotImplementedException();
|
||||
Marshal.Copy(bitmapData.Scan0, data, 0, data.Length);
|
||||
image.UnlockBits(bitmapData);
|
||||
|
||||
return new Tuple<byte[], int, int>(data, image.Width, image.Height);
|
||||
}
|
||||
finally
|
||||
{
|
||||
image.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// RGB to BGR convert Matrix
|
||||
private static float[][] rgbtobgr = new float[][]
|
||||
{
|
||||
new float[] {0, 0, 1, 0, 0},
|
||||
new float[] {0, 1, 0, 0, 0},
|
||||
new float[] {1, 0, 0, 0, 0},
|
||||
new float[] {0, 0, 0, 1, 0},
|
||||
new float[] {0, 0, 0, 0, 1}
|
||||
};
|
||||
|
||||
|
||||
internal static Image RGBToBGR(this Image bmp)
|
||||
{
|
||||
Image newBmp;
|
||||
if ((bmp.PixelFormat & System.Drawing.Imaging.PixelFormat.Indexed) != 0)
|
||||
{
|
||||
newBmp = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to clone so the call to Clear() below doesn't clear the source before trying to draw it to the target.
|
||||
newBmp = (Image)bmp.Clone();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
System.Drawing.Imaging.ImageAttributes ia = new System.Drawing.Imaging.ImageAttributes();
|
||||
System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(rgbtobgr);
|
||||
|
||||
ia.SetColorMatrix(cm);
|
||||
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(newBmp))
|
||||
{
|
||||
g.Clear(Color.Transparent);
|
||||
g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, bmp.Width, bmp.Height, System.Drawing.GraphicsUnit.Pixel, ia);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (newBmp != bmp)
|
||||
{
|
||||
bmp.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return newBmp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
|
2
FreeSO
2
FreeSO
|
@ -1 +1 @@
|
|||
Subproject commit b23f16c4de1792363bc25d94a4d34dc787d39899
|
||||
Subproject commit 2ea906d86f4fea5c71bb62f3ec42b2dba3b701ac
|
Loading…
Reference in a new issue