[WIP] Pre 1.0 Testing Commit

Moving onto a more common commit cycle here
- 2D CAS, family management, move in (even magic town with magicoins)
- WIP Lot Saves
- A ton of engine fixes (mostly in FreeSO project)
- A ton of UI things, icons for all build/buy categories
- Animation speed increase (consistent with TS1, 30 fps at 50 hz)
- Cool transitions to cas 🆒 😎
- A lot more
This commit is contained in:
riperiperi 2018-05-25 00:47:46 +01:00
parent a15ff3503b
commit 4ac38452dc
90 changed files with 2207 additions and 302 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 886 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 922 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 1,005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

View file

@ -23,7 +23,22 @@ namespace Simitone.Client
{ {
GameThread.NextUpdate((x) => GameThread.NextUpdate((x) =>
{ {
var screen = new TS1GameScreen(); var mode = NeighSelectionMode.Normal;
if (lotName.Length > 1 && lotName[0] == '!')
{
switch (lotName[1])
{
case 'n':
mode = NeighSelectionMode.MoveIn; break;
case 'm':
mode = NeighSelectionMode.MoveInMagic; break;
}
}
var screen = new TS1GameScreen(mode);
if (mode != NeighSelectionMode.Normal)
{
screen.StartMoveIn(int.Parse(lotName.Substring(2)));
}
var last = GameFacade.Screens.CurrentUIScreen; var last = GameFacade.Screens.CurrentUIScreen;
GameFacade.Screens.RemoveCurrent(); GameFacade.Screens.RemoveCurrent();
GameFacade.Screens.AddScreen(screen); GameFacade.Screens.AddScreen(screen);
@ -46,14 +61,14 @@ namespace Simitone.Client
public static void EnterCAS() public static void EnterCAS()
{ {
GameThread.NextUpdate((x) => //GameThread.NextUpdate((x) =>
{ //{
var screen = new TS1CASScreen(); var screen = new TS1CASScreen();
var last = GameFacade.Screens.CurrentUIScreen; var last = GameFacade.Screens.CurrentUIScreen;
if (last is TS1GameScreen) ((TS1GameScreen)last).CleanupLastWorld(); if (last is TS1GameScreen) ((TS1GameScreen)last).CleanupLastWorld();
GameFacade.Screens.RemoveCurrent(); GameFacade.Screens.RemoveCurrent();
GameFacade.Screens.AddScreen(screen); GameFacade.Screens.AddScreen(screen);
}); //});
} }
} }
} }

View file

@ -54,11 +54,14 @@
<Compile Include="UI\Controls\UIElasticButton.cs" /> <Compile Include="UI\Controls\UIElasticButton.cs" />
<Compile Include="UI\Controls\UISkillDisplay.cs" /> <Compile Include="UI\Controls\UISkillDisplay.cs" />
<Compile Include="UI\Controls\UIStencilButton.cs" /> <Compile Include="UI\Controls\UIStencilButton.cs" />
<Compile Include="UI\Controls\UITouchListbox.cs" />
<Compile Include="UI\Controls\UITouchScroll.cs" /> <Compile Include="UI\Controls\UITouchScroll.cs" />
<Compile Include="UI\Controls\UITwoStateButton.cs" /> <Compile Include="UI\Controls\UITwoStateButton.cs" />
<Compile Include="UI\Controls\UIValueBar.cs" /> <Compile Include="UI\Controls\UIValueBar.cs" />
<Compile Include="UI\Model\UIIconCache.cs" /> <Compile Include="UI\Model\UIIconCache.cs" />
<Compile Include="UI\Model\UIStyle.cs" /> <Compile Include="UI\Model\UIStyle.cs" />
<Compile Include="UI\Panels\CAS\UIFamiliesCASPanel.cs" />
<Compile Include="UI\Panels\CAS\UIFamilyCASItem.cs" />
<Compile Include="UI\Panels\CAS\UIFamilyCASPanel.cs" /> <Compile Include="UI\Panels\CAS\UIFamilyCASPanel.cs" />
<Compile Include="UI\Panels\CAS\UISimCASPanel.cs" /> <Compile Include="UI\Panels\CAS\UISimCASPanel.cs" />
<Compile Include="UI\Panels\LiveSubpanels\Catalog\UICatalogItem.cs" /> <Compile Include="UI\Panels\LiveSubpanels\Catalog\UICatalogItem.cs" />
@ -71,7 +74,7 @@
<Compile Include="UI\Panels\LiveSubpanels\UIMotiveSubpanel.cs" /> <Compile Include="UI\Panels\LiveSubpanels\UIMotiveSubpanel.cs" />
<Compile Include="UI\Panels\LiveSubpanels\UISubpanel.cs" /> <Compile Include="UI\Panels\LiveSubpanels\UISubpanel.cs" />
<Compile Include="UI\Panels\LotControls\UIArchTouchHelper.cs" /> <Compile Include="UI\Panels\LotControls\UIArchTouchHelper.cs" />
<Compile Include="UI\Panels\UI3DThumb.cs" /> <Compile Include="UI\Panels\LotControls\UICallNeighborAlert.cs" />
<Compile Include="UI\Panels\UIClockPanel.cs" /> <Compile Include="UI\Panels\UIClockPanel.cs" />
<Compile Include="UI\Panels\UICutawayPanel.cs" /> <Compile Include="UI\Panels\UICutawayPanel.cs" />
<Compile Include="UI\Panels\UIHouseSelectPanel.cs" /> <Compile Include="UI\Panels\UIHouseSelectPanel.cs" />
@ -92,11 +95,13 @@
<Compile Include="UI\Panels\UIRotationAnimation.cs" /> <Compile Include="UI\Panels\UIRotationAnimation.cs" />
<Compile Include="UI\Panels\UISimitoneFrontend.cs" /> <Compile Include="UI\Panels\UISimitoneFrontend.cs" />
<Compile Include="UI\Panels\UISwitchAvatarPanel.cs" /> <Compile Include="UI\Panels\UISwitchAvatarPanel.cs" />
<Compile Include="UI\Panels\UITransDialog.cs" />
<Compile Include="UI\Panels\WorldUI\UIHeadlineRenderer.cs" /> <Compile Include="UI\Panels\WorldUI\UIHeadlineRenderer.cs" />
<Compile Include="UI\Panels\WorldUI\UIMoneyHeadline.cs" /> <Compile Include="UI\Panels\WorldUI\UIMoneyHeadline.cs" />
<Compile Include="UI\Screens\LoadingGameScreen.cs" /> <Compile Include="UI\Screens\LoadingGameScreen.cs" />
<Compile Include="UI\Screens\TS1CASScreen.cs" /> <Compile Include="UI\Screens\TS1CASScreen.cs" />
<Compile Include="UI\Screens\TS1GameScreen.cs" /> <Compile Include="UI\Screens\TS1GameScreen.cs" />
<Compile Include="Utils\SimitoneNeighOBJExporter.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\FreeSO\Other\libs\FSOMonoGame\MonoGame.Framework\MonoGame.Framework.Net.WindowsGL.csproj"> <ProjectReference Include="..\..\..\FreeSO\Other\libs\FSOMonoGame\MonoGame.Framework\MonoGame.Framework.Net.WindowsGL.csproj">
@ -145,6 +150,21 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Content\3D\TEX_0.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\3D\TEX_1.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\cas\btn_createfam.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\cas\btn_deletefam.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\cas\btn_movein.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\cas\cas_adult.png"> <Content Include="Content\uigraphics\cas\cas_adult.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -196,6 +216,9 @@
<Content Include="Content\uigraphics\common\btn_back.png"> <Content Include="Content\uigraphics\common\btn_back.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\uigraphics\common\circle10px.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\dialog\ngbh_outline.png"> <Content Include="Content\uigraphics\dialog\ngbh_outline.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -247,6 +270,33 @@
<Content Include="Content\uigraphics\live\cat\cat_cancel.png"> <Content Include="Content\uigraphics\live\cat\cat_cancel.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\uigraphics\live\cat\cat_dt_food.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_dt_out.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_dt_shop.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_dt_street.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_st_spa.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_st_studio.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_vac_amen.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_vac_lodg.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat\cat_vac_recr.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\live\cat_btn_base.png"> <Content Include="Content\uigraphics\live\cat_btn_base.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -658,6 +708,12 @@
<Content Include="Content\uigraphics\ngbh\ngbh_vacat.png"> <Content Include="Content\uigraphics\ngbh\ngbh_vacat.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\uigraphics\trans\trans_cas.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\uigraphics\trans\trans_normal.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Content\TS1Patch\PetGym_performance.piff"> <Content Include="Content\TS1Patch\PetGym_performance.piff">
@ -682,6 +738,16 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="Content\3D\arrow.fsom">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Content\3D\star.fsom">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -20,6 +20,7 @@ using Microsoft.Xna.Framework.Audio;
using FSO.HIT.Model; using FSO.HIT.Model;
using FSO.Client; using FSO.Client;
using FSO.Files; using FSO.Files;
using FSO.SimAntics;
namespace Simitone.Client namespace Simitone.Client
{ {
@ -35,12 +36,12 @@ namespace Simitone.Client
public SimitoneGame() : base() public SimitoneGame() : base()
{ {
GameFacade.Game = this; GameFacade.Game = this;
ImageLoader.PremultiplyPNG = true;
if (GameFacade.DirectX) TimedReferenceController.SetMode(CacheType.PERMANENT); if (GameFacade.DirectX) TimedReferenceController.SetMode(CacheType.PERMANENT);
Content.RootDirectory = FSOEnvironment.GFXContentDir; Content.RootDirectory = FSOEnvironment.GFXContentDir;
TargetElapsedTime = new TimeSpan(10000000 / GlobalSettings.Default.TargetRefreshRate); TargetElapsedTime = new TimeSpan(10000000 / GlobalSettings.Default.TargetRefreshRate);
FSOEnvironment.RefreshRate = GlobalSettings.Default.TargetRefreshRate; FSOEnvironment.RefreshRate = GlobalSettings.Default.TargetRefreshRate;
FSOEnvironment.TexCompress = false;
if (!FSOEnvironment.SoftwareKeyboard) if (!FSOEnvironment.SoftwareKeyboard)
{ {
@ -91,8 +92,8 @@ namespace Simitone.Client
var settings = GlobalSettings.Default; var settings = GlobalSettings.Default;
if (FSOEnvironment.DPIScaleFactor != 1 || FSOEnvironment.SoftwareDepth) if (FSOEnvironment.DPIScaleFactor != 1 || FSOEnvironment.SoftwareDepth)
{ {
settings.GraphicsWidth = GraphicsDevice.Viewport.Width / FSOEnvironment.DPIScaleFactor; settings.GraphicsWidth = (int)(GraphicsDevice.Viewport.Width / FSOEnvironment.DPIScaleFactor);
settings.GraphicsHeight = GraphicsDevice.Viewport.Height / FSOEnvironment.DPIScaleFactor; settings.GraphicsHeight = (int)(GraphicsDevice.Viewport.Height / FSOEnvironment.DPIScaleFactor);
} }
FSO.LotView.WorldConfig.Current = new FSO.LotView.WorldConfig() FSO.LotView.WorldConfig.Current = new FSO.LotView.WorldConfig()

View file

@ -69,7 +69,7 @@ namespace Simitone.Client.UI.Controls
public override void Draw(UISpriteBatch SBatch) public override void Draw(UISpriteBatch SBatch)
{ {
if (!Visible) return; if (!Visible) return;
DrawLocalTexture(SBatch, Texture, new Vector2(Texture.Width, Texture.Height) / -2); DrawLocalTexture(SBatch, Texture, null, new Vector2(Texture.Width, Texture.Height) / -2, Vector2.One, Color.White * (Disabled?0.5f:1f));
} }
} }
} }

View file

@ -90,6 +90,15 @@ namespace Simitone.Client.UI.Controls
GameFacade.Screens.Tween.To(this, 0.5f, new Dictionary<string, float>() { { "InterpolatedAnimation", 1f} }, TweenQuad.EaseOut); GameFacade.Screens.Tween.To(this, 0.5f, new Dictionary<string, float>() { { "InterpolatedAnimation", 1f} }, TweenQuad.EaseOut);
} }
public override void GameResized()
{
base.GameResized();
TitleBg.SetSize(Width, 70);
Width = GameFacade.Screens.CurrentUIScreen.ScreenWidth;
ScrHeight = GameFacade.Screens.CurrentUIScreen.ScreenHeight;
InterpolatedAnimation = InterpolatedAnimation;
}
public void Close() public void Close()
{ {
if (!Closing) if (!Closing)

View file

@ -0,0 +1,131 @@
using FSO.Client.UI.Controls;
using FSO.Client.UI.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using FSO.Client;
using FSO.Content;
using Simitone.Client.UI.Model;
using Microsoft.Xna.Framework.Graphics;
using FSO.Common.Utils;
namespace Simitone.Client.UI.Controls
{
public class UITouchStringList : UIContainer
{
public UIImage Outline;
public UITouchScroll ScrollElem;
public event Action<int> OnSelectionChange;
private Vector2 _Size;
public override Vector2 Size
{
get
{
return _Size;
}
set
{
_Size = value;
Outline.Width = value.X;
Outline.Height = value.Y;
ScrollElem.Size = new Vector2(value.X - 12, value.Y - 12);
}
}
public List<string> BackingList = new List<string>();
public UITouchStringList()
{
var gd = GameFacade.GraphicsDevice;
var ui = Content.Get().CustomUI;
ScrollElem = new UITouchScroll(GetLength, GetElemAt);
ScrollElem.VerticalMode = true;
ScrollElem.Position = new Vector2(6);
ScrollElem.ItemWidth = 38;
ScrollElem.DrawBounds = false;
ScrollElem.Margin = 6;
ScrollElem.SetScroll(-6);
Add(ScrollElem);
Outline = new UIImage(ui.Get("cat_btn_base.png").Get(gd)).With9Slice(25, 25, 25, 25);
Add(Outline);
}
public void SelectionChanged(int id)
{
OnSelectionChange?.Invoke(id);
}
public void Refresh()
{
ScrollElem.Reset();
}
public int GetLength()
{
return BackingList.Count;
}
public UITSContainer GetElemAt(int i)
{
return new UITouchStringListItem(BackingList[i], new Point((int)Size.X-12, ScrollElem.ItemWidth), this);
}
}
public class UITouchStringListItem : UITSContainer
{
public string Value;
public Point ESize;
public bool Outlined;
public UITouchStringList TParent;
public UILabel Label;
private Texture2D Px;
public float SelectPct { get; set; }
public UITouchStringListItem(string value, Point esize, UITouchStringList parent)
{
TParent = parent;
Value = value;
ESize = esize;
Px = TextureGenerator.GetPxWhite(GameFacade.GraphicsDevice);
Label = new UILabel();
Label.CaptionStyle = Label.CaptionStyle.Clone();
Label.CaptionStyle.Size = 19;
Label.CaptionStyle.Color = UIStyle.Current.Text;
Label.Alignment = TextAlignment.Middle | TextAlignment.Left;
Label.Caption = Label.CaptionStyle.TruncateToWidth(value, esize.X-20);
Label.Size = esize.ToVector2();
Label.X += 10;
Add(Label);
SelectPct = SelectPct;
}
public override void Selected()
{
Outlined = true;
Label.CaptionStyle.Color = UIStyle.Current.Bg;
GameFacade.Screens.Tween.To(this, 0.3f, new Dictionary<string, float>() { { "SelectPct", 1f } }, TweenQuad.EaseOut);
TParent.SelectionChanged(ItemID);
}
public override void Deselected()
{
Label.CaptionStyle.Color = UIStyle.Current.Text;
GameFacade.Screens.Tween.To(this, 0.3f, new Dictionary<string, float>() { { "SelectPct", 0f } }, TweenQuad.EaseOut);
Outlined = false;
}
public override void Draw(UISpriteBatch batch)
{
DrawLocalTexture(batch, Px, null, Vector2.Zero, new Vector2(ESize.X*SelectPct, ESize.Y), UIStyle.Current.SecondaryText);
base.Draw(batch);
}
}
}

View file

@ -20,6 +20,7 @@ namespace Simitone.Client.UI.Controls
public Texture2D ScrollEdgeR; public Texture2D ScrollEdgeR;
public bool DrawBounds = true; public bool DrawBounds = true;
public int Margin; public int Margin;
public bool VerticalMode;
private UIMouseEventRef HitTest; private UIMouseEventRef HitTest;
@ -86,9 +87,19 @@ namespace Simitone.Client.UI.Controls
} }
} }
private int GetPAxis(Point p)
{
return (VerticalMode) ? p.Y : p.X;
}
private float GetPAxis(Vector2 p)
{
return (VerticalMode) ? p.Y : p.X;
}
public void Select(Point at) public void Select(Point at)
{ {
var item = (int)(at.X + Scroll) / ItemWidth; var item = (int)(GetPAxis(at) + Scroll) / ItemWidth;
if (item >= LengthProvider()) return; if (item >= LengthProvider()) return;
var rItem = GetOrPrepare(item); var rItem = GetOrPrepare(item);
if (rItem != null) if (rItem != null)
@ -107,6 +118,11 @@ namespace Simitone.Client.UI.Controls
item = ElemProvider(id); item = ElemProvider(id);
item.Visible = false; item.Visible = false;
item.ItemID = id; item.ItemID = id;
if (id == LastSelected?.ItemID)
{
item.Selected();
LastSelected = item;
}
Add(item); Add(item);
} }
return item; return item;
@ -133,11 +149,11 @@ namespace Simitone.Client.UI.Controls
var pos = lastMouse.MouseState.Position; var pos = lastMouse.MouseState.Position;
if (!InScroll) if (!InScroll)
{ {
if (Math.Abs((pos - MouseDownAt).X) > 25) InScroll = true; if (Math.Abs(GetPAxis(pos - MouseDownAt)) > 25) InScroll = true;
} }
if (InScroll) if (InScroll)
{ {
ScrollVelocity = -(pos - MouseDownAt).X; ScrollVelocity = -GetPAxis(pos - MouseDownAt);
MouseDownAt = pos; MouseDownAt = pos;
} }
} }
@ -148,7 +164,7 @@ namespace Simitone.Client.UI.Controls
Scroll += ScrollVelocity; Scroll += ScrollVelocity;
ScrollVelocity *= 0.9f; ScrollVelocity *= 0.9f;
Scroll = Math.Max(-Margin, Math.Min(length * ItemWidth - Size.X + Margin, Scroll)); Scroll = Math.Max(-Margin, Math.Min(length * ItemWidth - GetPAxis(Size) + Margin, Scroll));
//update children positions. //update children positions.
//delete ones that are not //delete ones that are not
@ -156,14 +172,15 @@ namespace Simitone.Client.UI.Controls
var untouched = new HashSet<UIElement>(Children); var untouched = new HashSet<UIElement>(Children);
var b = (int)(Scroll / ItemWidth); var b = (int)(Scroll / ItemWidth);
var e = b + (Size.X + (ItemWidth - 1)) / ItemWidth; var e = b + (GetPAxis(Size) + (ItemWidth - 1)) / ItemWidth;
for (int i=b; i<e; i++) for (int i=b; i<e; i++)
{ {
if (i < 0) continue; if (i < 0) continue;
if (i >= length) break; if (i >= length) break;
var item = GetOrPrepare(i); var item = GetOrPrepare(i);
untouched.Remove(item); untouched.Remove(item);
item.X = i * ItemWidth - Scroll; if (VerticalMode) item.Y = i * ItemWidth - Scroll;
else item.X = i * ItemWidth - Scroll;
item.Visible = true; item.Visible = true;
} }
@ -182,11 +199,20 @@ namespace Simitone.Client.UI.Controls
public override void Draw(UISpriteBatch batch) public override void Draw(UISpriteBatch batch)
{ {
if (!Visible) return;
base.Draw(batch); base.Draw(batch);
if (DrawBounds) if (DrawBounds)
{ {
DrawLocalTexture(batch, ScrollEdgeL, new Vector2(0, Size.Y / 2 - 64)); if (VerticalMode)
DrawLocalTexture(batch, ScrollEdgeR, new Vector2(Size.X - 15, Size.Y / 2 - 64)); {
DrawLocalTexture(batch, ScrollEdgeL, null, new Vector2(Size.X / 2 - 64, 0), Vector2.One, Color.White, (float)Math.PI/2f, new Vector2(0, ScrollEdgeL.Height));
DrawLocalTexture(batch, ScrollEdgeR, null, new Vector2(Size.X / 2 - 64, Size.Y - 15), Vector2.One, Color.White, (float)Math.PI / 2f, new Vector2(0, ScrollEdgeL.Height));
}
else
{
DrawLocalTexture(batch, ScrollEdgeL, new Vector2(0, Size.Y / 2 - 64));
DrawLocalTexture(batch, ScrollEdgeR, new Vector2(Size.X - 15, Size.Y / 2 - 64));
}
} }
} }

View file

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FSO.Client.UI.Framework;
namespace Simitone.Client.UI.Controls namespace Simitone.Client.UI.Controls
{ {
@ -14,5 +15,14 @@ namespace Simitone.Client.UI.Controls
{ {
ImageStates = 2; ImageStates = 2;
} }
public override void Draw(UISpriteBatch SBatch)
{
var oldOpacity = Opacity;
if (Disabled) Opacity = 0.5f;
var col = BlendColor;
base.Draw(SBatch);
if (Disabled) Opacity = oldOpacity;
}
} }
} }

View file

@ -28,7 +28,9 @@ namespace Simitone.Client.UI.Model
if (obj is VMAvatar) if (obj is VMAvatar)
{ {
var ava = (VMAvatar)obj; var ava = (VMAvatar)obj;
var id = ava.HeadOutfit.Name +":"+ ava.HeadOutfit.OftData.TS1TextureID; var headname = ava.HeadOutfit.Name;
if (headname == "") headname = ava.BodyOutfit.OftData.TS1TextureID;
var id = headname +":"+ ava.HeadOutfit.OftData.TS1TextureID;
Texture2D result = null; Texture2D result = null;
if (!AvatarHeadCache.TryGetValue(id, out result)) if (!AvatarHeadCache.TryGetValue(id, out result))

View file

@ -42,5 +42,7 @@ namespace Simitone.Client.UI.Model
public Color SkillInactive = new Color(99, 109, 242, 255); public Color SkillInactive = new Color(99, 109, 242, 255);
public Color SkillActive = new Color(0, 255, 255, 255); public Color SkillActive = new Color(0, 255, 255, 255);
public Color SkillNeeded = new Color(255, 191, 0, 255); public Color SkillNeeded = new Color(255, 191, 0, 255);
public Color TransColor = new Color(0, 41, 69, 255);
} }
} }

View file

@ -0,0 +1,130 @@
using FSO.Client;
using FSO.Client.UI.Controls;
using FSO.Client.UI.Framework;
using FSO.Common.Utils;
using FSO.Content;
using FSO.Files.Formats.IFF.Chunks;
using FSO.SimAntics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Simitone.Client.UI.Controls;
using Simitone.Client.UI.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simitone.Client.UI.Panels.CAS
{
/// <summary>
/// Lists all of the families that can be moved in or deleted.
/// </summary>
public class UIFamiliesCASPanel : UIContainer
{
public UITouchScroll FamilyList;
public UILabel Title;
public UITwoStateButton DeleteButton;
public UITwoStateButton NewButton;
public event Action OnNewFamily;
public List<FAMI> Families = new List<FAMI>();
private VM vm;
private Texture2D WhitePx;
public int Selection;
public float TitleI { get; set; }
public UIFamiliesCASPanel()
{
var gd = GameFacade.GraphicsDevice;
var ui = Content.Get().CustomUI;
var sh = UIScreen.Current.ScreenHeight;
var sw = UIScreen.Current.ScreenWidth;
FamilyList = new UITouchScroll(FamilyLength, FamilyProvider);
FamilyList.VerticalMode = true;
FamilyList.Size = new Vector2(810, sh);
FamilyList.X = (sw - 810) / 2;
FamilyList.ItemWidth = 180;
FamilyList.Margin = 90;
FamilyList.DrawBounds = false;
Add(FamilyList);
WhitePx = TextureGenerator.GetPxWhite(GameFacade.GraphicsDevice);
Title = new UILabel();
Title.NewStyle(UIStyle.Current.Text, 37);
Title.Caption = "Select a Family";
Title.Size = new Vector2(sw, 60);
Title.Alignment = TextAlignment.Middle | TextAlignment.Center;
Title.Y = -85;
Add(Title);
DeleteButton = new UITwoStateButton(ui.Get("btn_deletefam.png").Get(gd));
DeleteButton.Position = new Vector2(sw - 140, sh - 260);
Add(DeleteButton);
NewButton = new UITwoStateButton(ui.Get("btn_createfam.png").Get(gd));
NewButton.Position = new Vector2(sw - 140, sh - 380);
Add(NewButton);
NewButton.OnButtonClick += (btn) => OnNewFamily?.Invoke();
TitleI = TitleI;
SetSelection(-1);
}
public void SetSelection(int i)
{
Selection = i;
DeleteButton.Disabled = Selection == -1;
NewButton.Disabled = false;
}
public override void GameResized()
{
var sh = UIScreen.Current.ScreenHeight;
var sw = UIScreen.Current.ScreenWidth;
FamilyList.Size = new Vector2(810, sh);
FamilyList.X = (sw - 810) / 2;
FamilyList.Reset();
Title.Size = new Vector2(sw, 60);
DeleteButton.Position = new Vector2(sw - 140, sh - 260);
NewButton.Position = new Vector2(sw - 140, sh - 380);
base.GameResized();
}
public int FamilyLength()
{
return Families.Count;
}
public UITSContainer FamilyProvider(int id)
{
var item = new UIFamilyCASItem(this, Families[id], vm);
return item;
}
public void UpdateFamilies(List<FAMI> families, VM vm)
{
this.vm = vm;
Families = families;
FamilyList.Reset();
}
public override void Draw(UISpriteBatch batch)
{
var y = TitleI * 100 - 85;
Title.Y = y;
NewButton.X = UIScreen.Current.ScreenWidth - 140 * TitleI;
DeleteButton.X = NewButton.X;
FamilyList.Opacity = TitleI;
FamilyList.Visible = FamilyList.Opacity > 0;
Title.Visible = false;
base.Draw(batch);
DrawLocalTexture(batch, WhitePx, null, new Vector2(0, y), new Vector2(UIScreen.Current.ScreenWidth, 60), UIStyle.Current.Bg);
Title.Visible = true;
Title.Draw(batch);
}
}
}

View file

@ -0,0 +1,125 @@
using FSO.Client;
using FSO.Client.UI.Controls;
using FSO.Client.UI.Framework;
using FSO.Common.Utils;
using FSO.Content;
using FSO.Files.Formats.IFF.Chunks;
using FSO.LotView.Model;
using FSO.SimAntics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Simitone.Client.UI.Controls;
using Simitone.Client.UI.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simitone.Client.UI.Panels.CAS
{
public class UIFamilyCASItem : UITSContainer
{
public Texture2D PxWhite;
public Texture2D Grad;
public UIImage Background;
public UIImage SelectedGrad;
public UILabel FamilyTitle;
public UIFamiliesCASPanel FParent;
public List<UIAvatarSelectButton> Btns = new List<UIAvatarSelectButton>();
public int MaxWidth = 810;
public int Width;
public int TitleWidth;
public float SelectPct { get; set; }
public UIFamilyCASItem(UIFamiliesCASPanel parent, FAMI family, VM vm)
{
FParent = parent;
var ui = Content.Get().CustomUI;
var gd = GameFacade.GraphicsDevice;
PxWhite = TextureGenerator.GetPxWhite(gd);
Grad = ui.Get("dialog_title_grad.png").Get(gd);
Background = new UIImage(ui.Get("circle10px.png").Get(gd)).With9Slice(19, 19, 19, 19);
//set the width based on number of family members
//30 margin on family thumbs
Width = 100 * family.FamilyGUIDs.Length + 10;
Background.SetSize(Width, 120);
Background.Position = new Vector2((MaxWidth - Width) / 2, 40);
Add(Background);
//max width is 100*8+10, 810
var fams = family.ChunkParent.Get<FAMs>(family.ChunkID);
FamilyTitle = new UILabel();
FamilyTitle.CaptionStyle = FamilyTitle.CaptionStyle.Clone();
FamilyTitle.CaptionStyle.Color = UIStyle.Current.Text;
FamilyTitle.CaptionStyle.Size = 19;
FamilyTitle.Size = new Vector2(MaxWidth, 40);
FamilyTitle.Alignment = TextAlignment.Center | TextAlignment.Middle;
FamilyTitle.Caption = fams?.GetString(0) ?? "";
Add(FamilyTitle);
TitleWidth = (int)FamilyTitle.CaptionStyle.MeasureString(FamilyTitle.Caption).X + 30;
//display heads of all family members
InitAvatarList(family.FamilyGUIDs, vm);
SelectPct = SelectPct;
}
public override void Draw(UISpriteBatch batch)
{
DrawLocalTexture(batch, PxWhite, null, new Vector2((MaxWidth - TitleWidth) / 2, 0), new Vector2(TitleWidth, 40), UIStyle.Current.Bg);
Background.Visible = true;
Background.Draw(batch);
DrawLocalTexture(batch, Grad, null, new Vector2((MaxWidth - Width) / 2, 54), new Vector2((Width / (float)Grad.Width)*SelectPct, 66), Color.White);
Background.Visible = false;
base.Draw(batch);
}
public void InitAvatarList(uint[] guids, VM vm)
{
int i = 0;
foreach (var btn in Btns)
{
Remove(btn);
}
Btns.Clear();
i = 0;
var baseX = MaxWidth / 2 - (guids.Length-1) * 50;
foreach (var sim in guids)
{
var fam = vm.Context.CreateObjectInstance(sim, LotTilePos.OUT_OF_WORLD, Direction.NORTH).BaseObject;
fam.Tick();
var btn = new UIAvatarSelectButton(UIIconCache.GetObject(fam));
btn.Opacity = 1f;
var id = i;
btn.Name = fam.Name;
btn.X = baseX + (i++) * 100;
btn.Y = 88;
btn.DeregisterHandler();
Btns.Add(btn);
Add(btn);
fam.Delete(true, vm.Context);
}
}
public override void Selected()
{
base.Selected();
FamilyTitle.CaptionStyle.Color = UIStyle.Current.SecondaryText;
GameFacade.Screens.Tween.To(this, 0.33f, new Dictionary<string, float>() { { "SelectPct", 1f } }, TweenQuad.EaseOut);
FParent.SetSelection(ItemID);
}
public override void Deselected()
{
base.Deselected();
FamilyTitle.CaptionStyle.Color = UIStyle.Current.Text;
GameFacade.Screens.Tween.To(this, 0.33f, new Dictionary<string, float>() { { "SelectPct", 0f } }, TweenQuad.EaseOut);
}
}
}

View file

@ -369,7 +369,7 @@ namespace Simitone.Client.UI.Panels.CAS
if (MouseOn) if (MouseOn)
{ {
//how much allowance do we have on this specifically //how much allowance do we have on this specifically
var allowance = CAS.AllowedPoints - (CAS.TotalPoints - Points); var allowance = Math.Min(10, CAS.AllowedPoints - (CAS.TotalPoints - Points));
var newPTs = Math.Max(0, Math.Min(allowance, (int)Math.Ceiling(GlobalPoint(state.MouseState.Position.ToVector2()).X / 24))); var newPTs = Math.Max(0, Math.Min(allowance, (int)Math.Ceiling(GlobalPoint(state.MouseState.Position.ToVector2()).X / 24)));
if (newPTs != Points) if (newPTs != Points)
{ {

View file

@ -158,6 +158,122 @@ namespace Simitone.Client.UI.Panels.LiveSubpanels
}, },
}; };
public static Dictionary<UICatalogMode, List<UICatalogSubcat>> DTCategories = new Dictionary<UICatalogMode, List<UICatalogSubcat>>()
{
{
UICatalogMode.Downtown,
new List<UICatalogSubcat>()
{
new UICatalogSubcat() { MaskBit = 0, StrTable = 150, StrInd = 16}, //food
new UICatalogSubcat() { MaskBit = 1, StrTable = 150, StrInd = 17}, //shops
new UICatalogSubcat() { MaskBit = 2, StrTable = 150, StrInd = 18}, //outside
new UICatalogSubcat() { MaskBit = 3, StrTable = 150, StrInd = 19}, //street
}
},
{
UICatalogMode.Community,
new List<UICatalogSubcat>()
{
new UICatalogSubcat() { MaskBit = 0, StrTable = 150, StrInd = 32}, //food
new UICatalogSubcat() { MaskBit = 1, StrTable = 150, StrInd = 33}, //shops
new UICatalogSubcat() { MaskBit = 2, StrTable = 150, StrInd = 34}, //outside
new UICatalogSubcat() { MaskBit = 3, StrTable = 150, StrInd = 35}, //street
}
},
{
UICatalogMode.Vacation,
new List<UICatalogSubcat>()
{
new UICatalogSubcat() { MaskBit = 0, StrTable = 150, StrInd = 24}, //lodging
new UICatalogSubcat() { MaskBit = 1, StrTable = 150, StrInd = 25}, //shops
new UICatalogSubcat() { MaskBit = 2, StrTable = 150, StrInd = 26}, //recreation
new UICatalogSubcat() { MaskBit = 3, StrTable = 150, StrInd = 27}, //ameneties
}
},
{
UICatalogMode.Studiotown,
new List<UICatalogSubcat>()
{
new UICatalogSubcat() { MaskBit = 0, StrTable = 150, StrInd = 40}, //food
new UICatalogSubcat() { MaskBit = 1, StrTable = 150, StrInd = 41}, //shops
new UICatalogSubcat() { MaskBit = 2, StrTable = 150, StrInd = 42}, //studio
new UICatalogSubcat() { MaskBit = 3, StrTable = 150, StrInd = 43}, //spa
}
},
{
UICatalogMode.Magictown,
new List<UICatalogSubcat>()
{
new UICatalogSubcat() { MaskBit = 0, StrTable = 150, StrInd = 16}, //food
new UICatalogSubcat() { MaskBit = 1, StrTable = 150, StrInd = 17}, //shops
new UICatalogSubcat() { MaskBit = 2, StrTable = 150, StrInd = 44}, //magico
new UICatalogSubcat() { MaskBit = 3, StrTable = 150, StrInd = 18}, //outside
}
},
};
public static Dictionary<UICatalogMode, List<string>> DTIcons = new Dictionary<UICatalogMode, List<string>>()
{
{
UICatalogMode.Downtown,
new List<string>()
{
"dt_food", //food
"dt_shop", //shops
"dt_out", //outside
"dt_street", //street
}
},
{
UICatalogMode.Community,
new List<string>()
{
"dt_food", //food
"dt_shop", //shops
"dt_out", //outside
"dt_street", //street
}
},
{
UICatalogMode.Vacation,
new List<string>()
{
"vac_lodg", //food
"dt_shop", //shops
"vac_recr", //recreation
"vac_amen", //amenities
}
},
{
UICatalogMode.Studiotown,
new List<string>()
{
"dt_food", //food
"dt_shop", //shops
"st_studio", //studio
"st_spa", //spa
}
},
{
UICatalogMode.Magictown,
new List<string>()
{
"dt_food", //food
"dt_shop", //shops
"misc_magi", //magic
"dt_out", //outside
}
},
};
static UIBuyBrowsePanel() static UIBuyBrowsePanel()
{ {
Categories = new List<List<UICatalogSubcat>>(); Categories = new List<List<UICatalogSubcat>>();
@ -397,7 +513,32 @@ namespace Simitone.Client.UI.Panels.LiveSubpanels
ChoosingSub = true; ChoosingSub = true;
var cats = (Mode == UICatalogMode.Build)?BuildCategories[category]:Categories[category]; List<UICatalogSubcat> cats;
if (Mode == UICatalogMode.Build) cats = BuildCategories[category];
else if (Mode != UICatalogMode.Normal)
{
cats = DTCategories[Mode];
if (cats.Count == 4) //haven't added other or all subcats yet
{
cats.Add(new UICatalogSubcat()
{
StrTable = 210,
MaskBit = 7,
StrInd = 1, //other
});
cats.Add(new UICatalogSubcat()
{
StrTable = 210,
MaskBit = 8,
StrInd = 2, //all
});
}
}
else
{
cats = Categories[category];
}
var boff = CatContainer.Size.X/(cats.Count + 0.5f) / 2f; var boff = CatContainer.Size.X/(cats.Count + 0.5f) / 2f;
@ -422,6 +563,11 @@ namespace Simitone.Client.UI.Panels.LiveSubpanels
if (Mode == UICatalogMode.Build) { if (Mode == UICatalogMode.Build) {
name = BuildIcons[category][i]; name = BuildIcons[category][i];
} }
else if (Mode != UICatalogMode.Normal) {
if (cat.MaskBit == 7) name = "other";
else if (cat.MaskBit == 8) name = "all";
else name = DTIcons[Mode][cat.MaskBit];
}
else else
{ {
if (cat.MaskBit == 7) name = "other"; if (cat.MaskBit == 7) name = "other";
@ -434,6 +580,7 @@ namespace Simitone.Client.UI.Panels.LiveSubpanels
var subbutton = new UICatButton(Content.Get().CustomUI.Get("cat_"+name+".png").Get(GameFacade.GraphicsDevice)); var subbutton = new UICatButton(Content.Get().CustomUI.Get("cat_"+name+".png").Get(GameFacade.GraphicsDevice));
subbutton.OnButtonClick += (btn) => { InitSubcategory(cat); }; subbutton.OnButtonClick += (btn) => { InitSubcategory(cat); };
subbutton.Position = new Vector2(boff * (1.5f + i * 2) - (65 / 2), 16); subbutton.Position = new Vector2(boff * (1.5f + i * 2) - (65 / 2), 16);
subbutton.Disabled = SubcatIsEmpty(cat);
SelButtons.Add(subbutton); SelButtons.Add(subbutton);
Add(subbutton); Add(subbutton);
} }
@ -674,6 +821,24 @@ namespace Simitone.Client.UI.Panels.LiveSubpanels
} }
} }
private bool SubcatIsEmpty(UICatalogSubcat cat)
{
var index = cat.MaskBit;
if (Mode == UICatalogMode.Build)
{
return FullCategory.FirstOrDefault() == null;
}
else if (index == 8)
{
return !FullCategory.Any(x => (GetSubsort(x.Item)) > 0);
}
else
{
var mask = 1 << index;
return !FullCategory.Any(x => (GetSubsort(x.Item) & mask) > 0);
}
}
public void InitSubcategory(UICatalogSubcat cat) public void InitSubcategory(UICatalogSubcat cat)
{ {
var index = cat.MaskBit; var index = cat.MaskBit;

View file

@ -87,7 +87,7 @@ namespace Simitone.Client.UI.Panels.LiveSubpanels
if (sel == null) return; if (sel == null) return;
var neighbourhood = Content.Get().Neighborhood; var neighbourhood = Content.Get().Neighborhood;
var neighbour = sel.GetPersonData(VMPersonDataVariable.NeighborId); var neighbour = sel.GetPersonData(VMPersonDataVariable.NeighborId);
var inventory = neighbourhood.GetInventoryByNID(neighbour).Where(x => (CatSort == -1 && !HiddenCats.Contains(x.Type)) || CatSort == x.Type).ToList(); var inventory = neighbourhood.GetInventoryByNID(neighbour)?.Where(x => (CatSort == -1 && !HiddenCats.Contains(x.Type)) || CatSort == x.Type)?.ToList() ?? new List<InventoryItem>();
bool difference = false; bool difference = false;
if (inventory.Count == Items.Count) if (inventory.Count == Items.Count)

View file

@ -0,0 +1,154 @@
using FSO.Client.UI.Framework;
using FSO.Content;
using FSO.LotView.Model;
using FSO.SimAntics;
using FSO.SimAntics.Model;
using Simitone.Client.UI.Controls;
using Simitone.Client.UI.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simitone.Client.UI.Panels.LotControls
{
public class UICallNeighborAlert : UIMobileDialog
{
public UICallNeighborPanel NPanel;
public short SelectedNeighbour
{
get
{
return NPanel.SelectedNeighbour;
}
}
public event Action<int> OnResult;
public UICallNeighborAlert(short callerNID, VM vm)
{
Caption = "Call Neighbour";
SetHeight(490);
NPanel = new UICallNeighborPanel(callerNID, vm);
NPanel.Position = new Microsoft.Xna.Framework.Vector2((Width - 1030) / 2, 110);
NPanel.OnResult += (res) => { OnResult?.Invoke(res); Close(); };
Add(NPanel);
}
}
public class UICallNeighborPanel : UIContainer
{
public Dictionary<short, List<short>> NeighborsByFamilyID = new Dictionary<short, List<short>>();
public UITouchStringList FamilyList;
public UITouchStringList NeighbourList;
public UIAvatarSelectButton Icon;
public UIBigButton CallButton;
public int SelectedFamily = -1;
public short SelectedNeighbour = -1;
public VM VM;
public event Action<int> OnResult;
public UICallNeighborPanel(short callerNID, VM vm)
{
VM = vm;
var nb = Content.Get().Neighborhood;
var neigh = nb.GetNeighborByID(callerNID);
var rels = neigh.Relationships.Keys;
//var rels = nb.Neighbors.NeighbourByID.Keys;
foreach (var to in rels)
{
var tn = nb.GetNeighborByID((short)to);
var family = tn.PersonData?.ElementAt((int)VMPersonDataVariable.TS1FamilyNumber) ?? 0;
var gender = tn.PersonData?.ElementAt((int)VMPersonDataVariable.Gender) ?? 0; //can't call pets
if (family != 0 && gender < 2)
{
List<short> famList = null;
if (!NeighborsByFamilyID.TryGetValue(family, out famList))
{
famList = new List<short>();
NeighborsByFamilyID[family] = famList;
}
famList.Add((short)to);
}
}
FamilyList = new UITouchStringList();
FamilyList.Size = new Microsoft.Xna.Framework.Vector2(320, 350);
FamilyList.BackingList = NeighborsByFamilyID.Select(x => nb.GetFamilyString((ushort)x.Key).GetString(0)).ToList();
FamilyList.Refresh();
FamilyList.OnSelectionChange += FamilyList_OnSelectionChange;
Add(FamilyList);
NeighbourList = new UITouchStringList();
NeighbourList.Size = new Microsoft.Xna.Framework.Vector2(320, 350);
NeighbourList.Position = new Microsoft.Xna.Framework.Vector2(370, 0);
NeighbourList.OnSelectionChange += NeighbourList_OnSelectionChange;
Add(NeighbourList);
var cancelButton = new UIBigButton(false);
cancelButton.Caption = "Cancel";
cancelButton.Position = new Microsoft.Xna.Framework.Vector2(370 + 385, 135);
cancelButton.OnButtonClick += (btn) => { OnResult?.Invoke(-1); };
cancelButton.Width = 275;
Add(cancelButton);
CallButton = new UIBigButton(true);
CallButton.Caption = "Call";
CallButton.Position = new Microsoft.Xna.Framework.Vector2(370 + 385, 255);
CallButton.OnButtonClick += (btn) => { OnResult?.Invoke(SelectedNeighbour); };
CallButton.Width = 275;
Add(CallButton);
NeighbourList_OnSelectionChange((NeighborsByFamilyID.Count==0)?-2:-1);
OnResult += (res) => { CallButton.Disabled = true; cancelButton.Disabled = true; };
}
private void NeighbourList_OnSelectionChange(int obj)
{
if (Icon != null) { Remove(Icon); Icon = null; }
if (obj == -1)
{
SelectedNeighbour = -1;
CallButton.Disabled = true;
} else
{
SelectedNeighbour = NeighborsByFamilyID.ElementAt(SelectedFamily).Value[obj];
CallButton.Disabled = false;
var guid = Content.Get().Neighborhood.GetNeighborByID(SelectedNeighbour).GUID;
var temp = VM.Context.CreateObjectInstance(guid, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true);
Icon = new UIAvatarSelectButton(UIIconCache.GetObject(temp.BaseObject));
Icon.Position = new Microsoft.Xna.Framework.Vector2(892, 60);
Add(Icon);
temp.Delete(VM.Context);
}
}
private void FamilyList_OnSelectionChange(int obj)
{
var nb = Content.Get().Neighborhood;
//populate the rightmost list with the selected family
NeighbourList.BackingList.Clear();
if (obj != -1)
{
var people = NeighborsByFamilyID.ElementAt(obj).Value;
NeighbourList.BackingList =
people.Select(x => {
var guid = nb.GetNeighborByID(x).GUID;
var gobj = Content.Get().WorldObjects.Get(guid);
if (gobj == null) return "Unknown";
return gobj.Resource.Get<FSO.Files.Formats.IFF.Chunks.CTSS>(gobj.OBJ.CatalogStringsID)?.GetString(0) ?? "Unknown";
}
).ToList();
}
NeighbourList.Refresh();
NeighbourList_OnSelectionChange(-1);
SelectedFamily = obj;
}
}
}

View file

@ -1,123 +0,0 @@
using FSO.Client;
using FSO.Common.Rendering.Framework;
using FSO.Common.Rendering.Framework.Camera;
using FSO.Content;
using FSO.LotView.Components;
using FSO.LotView.Debug;
using FSO.SimAntics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simitone.Client.UI.Panels
{
public class UI3DThumb
{
public _3DTargetScene Scene;
public BasicCamera Camera;
public Texture2D Tex
{
get { return Scene.Target; }
}
public float RotationSpeed = 0.20f;
public float RotationX = -(float)Math.PI;
public Vector3 Ctr;
public float Size;
public List<Debug3DDGRPComponent> Comp3D;
public UI3DThumb(VMEntity ent)
{
Camera = new BasicCamera(GameFacade.GraphicsDevice, new Vector3(3, 1, 0), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
Camera.NearPlane = 0.001f;
Scene = new _3DTargetScene(GameFacade.GraphicsDevice, Camera, new Point(150, 150), 0);
Scene.Initialize(GameFacade.Scenes);
if (Comp3D != null)
{
foreach (var e in Comp3D)
{
e.Dispose();
Scene.Remove(e);
}
}
Comp3D = new List<Debug3DDGRPComponent>();
BoundingBox? total = null;
var pos = ent.MultitileGroup.GetBasePositions();
var i = 0;
foreach (var obj in ent.MultitileGroup.Objects)
{
var c = new Debug3DDGRPComponent();
var dgrp = ((ObjectComponent)obj.WorldUI).DGRP;
c.Mesh = (dgrp == null) ? null : Content.Get().RCMeshes.Get(dgrp, obj.Object.OBJ); //new DGRP3DMesh(((ObjectComponent)obj.WorldUI).DGRP, obj.Object.OBJ, GameFacade.GraphicsDevice, null);
Scene.Add(c);
if (c.Mesh == null) continue;
var vp = pos[i++];
c.Position = new Vector3((vp.X - 0.5f), vp.Z, (vp.Y - 0.5f));
if (total == null) total = OffsetBox(c.Mesh.Bounds ?? new BoundingBox(), c.Position);
else total = BoundingBox.CreateMerged(total.Value, OffsetBox(c.Mesh.Bounds ?? new BoundingBox(), c.Position));
c.Initialize();
Comp3D.Add(c);
}
if (total != null)
{
Ctr = new Vector3((total.Value.Max.X + total.Value.Min.X) / 2, (total.Value.Max.Y + total.Value.Min.Y) / 2, (total.Value.Max.Z + total.Value.Min.Z) / 2);
var diag = total.Value.Max - total.Value.Min;
Size = diag.Length();
}
}
public BoundingBox OffsetBox(BoundingBox box, Vector3 off)
{
return new BoundingBox(box.Min + off, box.Max + off);
}
public void RecalcBounds()
{
BoundingBox? total = null;
foreach (var c in Comp3D)
{
if (total == null) total = OffsetBox(c.Mesh.Bounds ?? new BoundingBox(), c.Position);
else total = BoundingBox.CreateMerged(total.Value, OffsetBox(c.Mesh.Bounds ?? new BoundingBox(), c.Position));
}
if (total != null)
{
Ctr = new Vector3((total.Value.Max.X + total.Value.Min.X) / 2, (total.Value.Max.Y + total.Value.Min.Y) / 2, (total.Value.Max.Z + total.Value.Min.Z) / 2);
var diag = total.Value.Max - total.Value.Min;
Size = diag.Length();
}
}
public void Draw()
{
RecalcBounds();
RotationX += RotationSpeed;
RotationSpeed += (0.01f - RotationSpeed) / 20;
var mat = Microsoft.Xna.Framework.Matrix.CreateRotationY(RotationX);
Camera.Position = Ctr + Vector3.Transform(new Vector3(4, 3, 0)*(0.1f + Size*0.2f), mat);
Camera.Target = Ctr + new Vector3(0, 0, 0);
var old = GameFacade.GraphicsDevice.BlendState;
GameFacade.GraphicsDevice.BlendState = BlendState.NonPremultiplied;
Scene.Draw(GameFacade.GraphicsDevice);
GameFacade.GraphicsDevice.BlendState = old;
}
public void Dispose()
{
Scene.Dispose();
if (Comp3D != null)
{
foreach (var e in Comp3D) e.Dispose();
}
}
}
}

View file

@ -4,9 +4,15 @@ using FSO.Client.UI.Framework;
using FSO.Common.Utils; using FSO.Common.Utils;
using FSO.Content; using FSO.Content;
using FSO.Files.Formats.IFF.Chunks; using FSO.Files.Formats.IFF.Chunks;
using FSO.LotView.Model;
using FSO.SimAntics;
using FSO.SimAntics.Engine.TSOTransaction;
using FSO.SimAntics.Model;
using FSO.SimAntics.NetPlay.Drivers;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Simitone.Client.UI.Controls; using Simitone.Client.UI.Controls;
using Simitone.Client.UI.Model; using Simitone.Client.UI.Model;
using Simitone.Client.UI.Screens;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -23,6 +29,8 @@ namespace Simitone.Client.UI.Panels
public UILabel StreetTitle; public UILabel StreetTitle;
public UILabel LotTitle; public UILabel LotTitle;
public UILabel LotDescription; public UILabel LotDescription;
public UILabel SecondaryText;
public UIHouseFamilyList FamilyDisplay;
public UIBigButton EnterLot; public UIBigButton EnterLot;
public UIBigButton More; public UIBigButton More;
@ -30,10 +38,54 @@ namespace Simitone.Client.UI.Panels
public event Action<int> OnSelected; public event Action<int> OnSelected;
public int HouseID; public int HouseID;
public List<UIBigButton> OptionButtons = new List<UIBigButton>();
private float _MoreTween;
public float MoreTween
{
get
{
return _MoreTween;
}
set
{
var nonOptionButtons = new UIElement[]
{
LotDescription,
SecondaryText,
EnterLot,
More,
};
foreach (var btn in nonOptionButtons)
{
btn.Opacity = 1 - value;
btn.Visible = btn.Opacity > 0;
}
foreach (var btn in OptionButtons)
{
btn.Opacity = value;
btn.Visible = btn.Opacity > 0;
}
var screen = UIScreen.Current;
var scale = Math.Max(2 / 3f, Math.Min(1, screen.ScreenWidth / 1704f));
var space = (96 * scale) - 56;
if (FamilyDisplay != null)
FamilyDisplay.X = (48 + space / 2) - value * screen.ScreenWidth / 2;
_MoreTween = value;
}
}
public UIHouseSelectPanel(int houseID) public UIHouseSelectPanel(int houseID)
{ {
HouseID = houseID;
var screen = GameFacade.Screens.CurrentUIScreen; var screen = GameFacade.Screens.CurrentUIScreen;
var extra = Math.Max(0, (screen.ScreenHeight - 640) / 128) * 64;
HouseID = houseID;
Diag = new UIDiagonalStripe(new Point(screen.ScreenWidth / 2, screen.ScreenHeight + 16), UIDiagonalStripeSide.RIGHT, UIStyle.Current.Bg); Diag = new UIDiagonalStripe(new Point(screen.ScreenWidth / 2, screen.ScreenHeight + 16), UIDiagonalStripeSide.RIGHT, UIStyle.Current.Bg);
Diag.Y = -16; Diag.Y = -16;
Diag.ListenForMouse(Diag.GetBounds(), (e, s) => { }); Diag.ListenForMouse(Diag.GetBounds(), (e, s) => { });
@ -41,58 +93,304 @@ namespace Simitone.Client.UI.Panels
TitleStripe = new UIDiagonalStripe(new Point(screen.ScreenWidth / 2, 92 + 8 + 32), UIDiagonalStripeSide.RIGHT, UIStyle.Current.Bg); TitleStripe = new UIDiagonalStripe(new Point(screen.ScreenWidth / 2, 92 + 8 + 32), UIDiagonalStripeSide.RIGHT, UIStyle.Current.Bg);
TitleStripe.StartOff = 8 + 32; TitleStripe.StartOff = 8 + 32;
TitleStripe.Y = 82 - 34; TitleStripe.Y = -16 + extra;
Add(TitleStripe); Add(TitleStripe);
var house = Content.Get().Neighborhood.GetHouse(houseID);
var street = Content.Get().Neighborhood.StreetNames; var neigh = Content.Get().Neighborhood;
var assignment = street.Get<STR>(2001).GetString(houseID-1);
var house = neigh.GetHouse(houseID);
var street = neigh.StreetNames;
var assignment = street.Get<STR>(2001).GetString(houseID - 1);
int streetName; int streetName;
if (int.TryParse(assignment, out streetName)) if (int.TryParse(assignment, out streetName))
{ {
StreetTitle = new UILabel(); StreetTitle = new UILabel();
StreetTitle.Position = new Vector2(30, 94); StreetTitle.Position = new Vector2(30, 94 + extra - 64);
InitLabel(StreetTitle); InitLabel(StreetTitle);
StreetTitle.CaptionStyle.Color = UIStyle.Current.BtnActive; StreetTitle.CaptionStyle.Color = UIStyle.Current.BtnActive;
StreetTitle.Caption = street.Get<STR>(2000).GetString(streetName-1).Replace("%s", houseID.ToString()); StreetTitle.Caption = street.Get<STR>(2000).GetString(streetName - 1).Replace("%s", houseID.ToString());
} }
var nameDesc = Content.Get().Neighborhood.GetHouseNameDesc(houseID); var nameDesc = neigh.GetHouseNameDesc(houseID);
var name = nameDesc.Item1; var name = nameDesc.Item1;
if (name == "") name = "Unnamed House"; if (name == "") name = StreetTitle.Caption;
LotTitle = new UILabel(); LotTitle = new UILabel();
LotTitle.Position = new Vector2(30, 122); LotTitle.Position = new Vector2(30, 122 + extra - 64);
InitLabel(LotTitle); InitLabel(LotTitle);
LotTitle.CaptionStyle.Size = 37; LotTitle.CaptionStyle.Size = 37;
LotTitle.Caption = name; LotTitle.Caption = name;
var family = neigh.GetFamilyForHouse((short)houseID);
LotDescription = new UILabel(); LotDescription = new UILabel();
LotDescription.Position = new Vector2(30, 206); LotDescription.Position = new Vector2(30, 206 + extra);
InitLabel(LotDescription); InitLabel(LotDescription);
//LotDescription.CaptionStyle.Size = 15; //LotDescription.CaptionStyle.Size = 15;
LotDescription.Size = new Vector2(502, screen.ScreenHeight-415); LotDescription.Size = new Vector2(screen.ScreenWidth/2 - 60, screen.ScreenHeight - 415);
LotDescription.Wrapped = true; LotDescription.Wrapped = true;
LotDescription.Alignment = TextAlignment.Top | TextAlignment.Left; LotDescription.Alignment = TextAlignment.Top | TextAlignment.Left;
LotDescription.Caption = nameDesc.Item2;
SecondaryText = new UILabel();
SecondaryText.Position = new Vector2(30, screen.ScreenHeight - (165 + extra));
InitLabel(SecondaryText);
SecondaryText.Size = new Vector2(screen.ScreenWidth / 2 - 60, 29);
SecondaryText.Wrapped = true;
SecondaryText.Alignment = TextAlignment.Bottom | TextAlignment.Right;
SecondaryText.CaptionStyle.Color = UIStyle.Current.SecondaryText;
var moveInID = (UIScreen.Current as Screens.TS1GameScreen).MoveInFamily;
var moveIn = (moveInID == null) ? null : Content.Get().Neighborhood.GetFamily((ushort)moveInID.Value);
var buttonValid = true;
if (family != null)
{
var famUI = new UIHouseFamilyList(family);
var scale = Math.Max(2 / 3f, Math.Min(1, screen.ScreenWidth / 1704f));
famUI.ScaleX = famUI.ScaleY = scale;
var space = (96 * scale) - 56;
LotDescription.Y += space;
famUI.Position = new Vector2(48 + space / 2, 152 + extra + space / 2);
Add(famUI);
FamilyDisplay = famUI;
LotDescription.Caption = GameFacade.Strings.GetString("134", "0", new string[] {
Content.Get().Neighborhood.MainResource.Get<FAMs>(family.ChunkID)?.GetString(0) ?? "?",
"§" + (family.ValueInArch + family.Budget).ToString("##,#0"), //should include lot value eventually
family.FamilyFriends.ToString()
});
LotDescription.CaptionStyle.Color = UIStyle.Current.SecondaryText;
if (moveIn != null)
{
SecondaryText.Caption = GameFacade.Strings.GetString("132", "15"); //house occupied
buttonValid = false;
}
} else
{
LotDescription.Y -= 64;
LotDescription.Size = new Vector2(LotDescription.Size.X, LotDescription.Size.Y + 65);
//LotDescription.Caption = new string(Enumerable.Range(1, 255).Select(x => 'a').ToArray());
LotDescription.Caption = nameDesc.Item2;
//set up the secondary text
var zones = neigh.ZoningDictionary;
short result = 1;
if (!zones.TryGetValue((short)houseID, out result))
result = (short)((houseID >= 81 && houseID <= 89) ? 2 : 1);
if (result > 0)
{
//zone
string str;
if (moveIn != null)
{
str = GameFacade.Strings.GetString("134", "18").Substring(8); //is community, can't move in
buttonValid = false;
}
else
{
str = GameFacade.Strings.GetString("134", "17").Substring(8); //is community
}
SecondaryText.Caption = str;
} else
{
//show price
var price = house.Get<SIMI>(1)?.PurchaseValue ?? 0;
string str;
if (houseID >= 90 && houseID <= 92)
{
//also requires magicoins
var magicoins = neigh.GetMagicoinsForFamily(family);
var requiredMC = int.Parse(GameFacade.Strings.GetString("134", (32 + Math.Abs(91 - houseID)).ToString()));
if (moveIn != null)
{
if (magicoins >= requiredMC)
{
if (moveIn.Budget >= price)
{
str = GameFacade.Strings.GetString("134", "31", new string[] { "", "",
"§" + price.ToString("##,#0"),
requiredMC.ToString()
});
}
else
{
//missing simoleons
str = GameFacade.Strings.GetString("134", "38", new string[] { "", "",
"§" + price.ToString("##,#0"),
requiredMC.ToString(),
moveIn.ChunkParent.Get<FAMs>(moveIn.ChunkID)?.GetString(0) ?? "",
"§" +moveIn.Budget.ToString("##,#0")
}).Substring(4);
buttonValid = false;
}
}
else
{
if (moveIn.Budget >= price)
{
//missing magicoins
str = GameFacade.Strings.GetString("134", "36", new string[] { "", "",
"§" + price.ToString("##,#0"),
requiredMC.ToString(),
moveIn.ChunkParent.Get<FAMs>(moveIn.ChunkID)?.GetString(0) ?? "",
magicoins.ToString()
}).Substring(4);
}
else
{
//missing both
str = GameFacade.Strings.GetString("134", "37", new string[] { "", "",
"§" + price.ToString("##,#0"),
requiredMC.ToString(),
moveIn.ChunkParent.Get<FAMs>(moveIn.ChunkID)?.GetString(0) ?? "",
magicoins.ToString()
}).Substring(4);
buttonValid = false;
}
buttonValid = false;
}
}
else
{
//suggest move in
str = GameFacade.Strings.GetString("134", "29", new string[] { "", "",
"§" + price.ToString("##,#0"),
requiredMC.ToString()
}).Substring(4);
}
}
else
{
if (moveIn != null)
{
if (moveIn.Budget >= price)
{
str = GameFacade.Strings.GetString("134", "5", new string[] { "", "",
"§" + price.ToString("##,#0"),
"§" +(moveIn.Budget - price).ToString("##,#0")
}).Substring(4);
}
else
{
str = GameFacade.Strings.GetString("134", "4", new string[] { "", "",
"§" + price.ToString("##,#0"),
moveIn.ChunkParent.Get<FAMs>(moveIn.ChunkID)?.GetString(0) ?? "",
"§" +moveIn.Budget.ToString("##,#0")
}).Substring(4);
buttonValid = false;
}
}
else
{
//suggest move in
str = GameFacade.Strings.GetString("134", "1", new string[] { "", "", "§" + price.ToString("##,#0") }).Substring(4);
}
}
SecondaryText.Caption = str;
SecondaryText.CaptionStyle.Size = 15;
}
}
EnterLot = new UIBigButton(false); EnterLot = new UIBigButton(false);
EnterLot.Caption = "Enter Lot"; EnterLot.Caption = (moveIn == null)?"Enter Lot":"Move In";
EnterLot.Width = 275; EnterLot.Width = (moveIn == null)? (screen.ScreenWidth / 2 - 293) : (screen.ScreenWidth/2-60);
EnterLot.Position = new Vector2(30, screen.ScreenHeight - 160); EnterLot.Disabled = !buttonValid;
EnterLot.Position = new Vector2(30, screen.ScreenHeight - (extra + 125));
EnterLot.OnButtonClick += (b) => { OnSelected?.Invoke(houseID); Kill(); }; EnterLot.OnButtonClick += (b) => { OnSelected?.Invoke(houseID); Kill(); };
Add(EnterLot); Add(EnterLot);
More = new UIBigButton(true); More = new UIBigButton(true);
More.Caption = "More"; More.Caption = "More";
More.Width = 192; More.Width = 208;
More.Position = new Vector2(330, screen.ScreenHeight - 160); More.Position = new Vector2(screen.ScreenWidth / 2 - 238, screen.ScreenHeight - (extra + 125));
Add(More); More.OnButtonClick += (btn) => { ShowMore(true); };
if (moveIn == null) Add(More);
var optionFunctions = new ButtonClickDelegate[]
{
(family==null)?null:(ButtonClickDelegate)((btn) => Evict(family)),
null,
null,
(btn) => ShowMore(false)
};
var optionNames = new string[]
{
(family==null)?"Bulldoze":"Evict",
"Rezone",
"Export",
"Back"
};
var bY = extra+140;
for (int i=0; i<optionFunctions.Length; i++)
{
var btn = new UIBigButton(i == optionFunctions.Length-1);
btn.Caption = optionNames[i];
btn.Position = new Vector2(screen.ScreenWidth / 4 - btn.Width / 2, bY);
btn.Disabled = optionFunctions[i] == null;
btn.OnButtonClick += optionFunctions[i];
Add(btn);
bY += 120;
OptionButtons.Add(btn);
}
X = screen.ScreenWidth / -2; X = screen.ScreenWidth / -2;
GameFacade.Screens.Tween.To(this, 0.5f, new Dictionary<string, float>() { { "X", 0f } }, TweenQuad.EaseOut); GameFacade.Screens.Tween.To(this, 0.5f, new Dictionary<string, float>() { { "X", 0f } }, TweenQuad.EaseOut);
MoreTween = MoreTween;
}
public void Evict(FAMI family)
{
if (family == null) return;
var familyName = family.ChunkParent.Get<FAMs>(family.ChunkID)?.GetString(0) ?? "selected";
UIMobileAlert evictDialog = null;
evictDialog = new UIMobileAlert(new UIAlertOptions()
{
Title = GameFacade.Strings.GetString("131", "2"),
Message = GameFacade.Strings.GetString("131", "3", new string[] {
familyName.ToString(),
"§" + (family.ValueInArch + family.Budget).ToString("##,#0") }
),
Buttons = UIAlertButton.YesNo(
(b) => { evictDialog.Close(); ((TS1GameScreen)UIScreen.Current).EvictLot(family, (short)HouseID); },
(b) => { evictDialog.Close(); }
)
});
UIScreen.GlobalShowDialog(evictDialog, true);
}
public void ShowMore(bool more)
{
GameFacade.Screens.Tween.To(this, 0.5f, new Dictionary<string, float>() { { "MoreTween", (more)?1f:0f } }, TweenQuad.EaseOut);
/*
var nonOptionButtons = new UIElement[]
{
LotDescription,
SecondaryText,
EnterLot,
More
};
foreach (var btn in nonOptionButtons)
{
var b = btn as UIButton;
if (b != null) b.Disabled = more;
}
foreach (var btn in OptionButtons)
{
btn.Disabled = !more;
}
*/
} }
public void Kill() public void Kill()
@ -112,4 +410,46 @@ namespace Simitone.Client.UI.Panels
Add(label); Add(label);
} }
} }
public class UIHouseFamilyList : UIContainer
{
public List<UIAvatarSelectButton> Btns = new List<UIAvatarSelectButton>();
public UIHouseFamilyList(FAMI family)
{
PopulateList(family);
}
public void PopulateList(FAMI family)
{
var world = new FSO.LotView.World(GameFacade.GraphicsDevice);
world.Initialize(GameFacade.Scenes);
var context = new VMContext(world);
var vm = new VM(context, new VMServerDriver(new VMTS1GlobalLinkStub()), new VMNullHeadlineProvider());
vm.Init();
var blueprint = new Blueprint(1, 1);
//world.InitBlueprint(blueprint);
context.Blueprint = blueprint;
context.Architecture = new VMArchitecture(1, 1, blueprint, vm.Context);
int i = 0;
var baseX = 0;
foreach (var sim in family.FamilyGUIDs)
{
var fam = vm.Context.CreateObjectInstance(sim, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true).BaseObject;
var btn = new UIAvatarSelectButton(UIIconCache.GetObject(fam));
btn.Opacity = 1f;
var id = i;
btn.Name = fam.Name;
btn.X = baseX + (i++) * 100;
btn.Y = 0;
btn.DeregisterHandler();
Btns.Add(btn);
Add(btn);
fam.Delete(true, vm.Context);
}
world.Dispose();
}
}
} }

View file

@ -35,6 +35,7 @@ using FSO.LotView.RC;
using Simitone.Client.UI.Panels.LotControls; using Simitone.Client.UI.Panels.LotControls;
using FSO.Client.UI.Panels.LotControls; using FSO.Client.UI.Panels.LotControls;
using FSO.UI.Panels.LotControls; using FSO.UI.Panels.LotControls;
using Simitone.Client.UI.Controls;
namespace Simitone.Client.UI.Panels namespace Simitone.Client.UI.Panels
{ {
@ -55,6 +56,11 @@ namespace Simitone.Client.UI.Panels
public FSO.SimAntics.VM vm; public FSO.SimAntics.VM vm;
public FSO.LotView.World World { get; set; } public FSO.LotView.World World { get; set; }
public VMEntity ActiveEntity { get; set; } public VMEntity ActiveEntity { get; set; }
public int Budget { get
{
return vm.TS1State.CurrentFamily?.Budget ?? int.MaxValue;
}
}
public uint SelectedSimID public uint SelectedSimID
{ {
get get
@ -88,7 +94,7 @@ namespace Simitone.Client.UI.Panels
// NOTE: Blocking dialog system assumes that nothing goes wrong with data transmission (which it shouldn't, because we're using TCP) // NOTE: Blocking dialog system assumes that nothing goes wrong with data transmission (which it shouldn't, because we're using TCP)
// and that the code actually blocks further dialogs from appearing while waiting for a response. // and that the code actually blocks further dialogs from appearing while waiting for a response.
// If we are to implement controlling multiple sims, this must be changed. // If we are to implement controlling multiple sims, this must be changed.
private UIMobileAlert BlockingDialog; private UIMobileDialog BlockingDialog;
private UINeighborhoodSelectionPanel TS1NeighSelector; private UINeighborhoodSelectionPanel TS1NeighSelector;
private ulong LastDialogID; private ulong LastDialogID;
@ -174,11 +180,6 @@ namespace Simitone.Client.UI.Panels
if (IDEHook.IDE != null) IDEHook.IDE.IDEBreakpointHit(vm, entity); if (IDEHook.IDE != null) IDEHook.IDE.IDEBreakpointHit(vm, entity);
} }
public string GetLotTitle()
{
return vm.LotName + " - " + vm.Entities.Count(x => x is VMAvatar && x.PersistID != 0);
}
void vm_OnDialog(FSO.SimAntics.Model.VMDialogInfo info) void vm_OnDialog(FSO.SimAntics.Model.VMDialogInfo info)
{ {
if (info != null && ((info.DialogID == LastDialogID && info.DialogID != 0 && info.Block))) return; if (info != null && ((info.DialogID == LastDialogID && info.DialogID != 0 && info.Block))) return;
@ -245,7 +246,21 @@ namespace Simitone.Client.UI.Panels
((TS1GameScreen)Parent).LotControl.Visible = false; ((TS1GameScreen)Parent).LotControl.Visible = false;
TS1NeighSelector.OnHouseSelect += HouseSelected; TS1NeighSelector.OnHouseSelect += HouseSelected;
return; return;
case VMDialogType.TS1PhoneBook:
var phone = new UICallNeighborAlert(((VMAvatar)info.Caller).GetPersonData(FSO.SimAntics.Model.VMPersonDataVariable.NeighborId), vm);
BlockingDialog = phone;
UIScreen.GlobalShowDialog(phone, true);
phone.OnResult += (result) =>
{
vm.SendCommand(new VMNetDialogResponseCmd
{
ActorUID = info.Caller.PersistID,
ResponseCode = (byte)((result > 0) ? 1 : 0),
ResponseText = result.ToString()
});
BlockingDialog = null;
};
return;
} }
var alert = new UIMobileAlert(options); var alert = new UIMobileAlert(options);
@ -291,14 +306,15 @@ namespace Simitone.Client.UI.Panels
private void DialogResponse(byte code) private void DialogResponse(byte code)
{ {
if (BlockingDialog == null || ActiveEntity == null) return; if (BlockingDialog == null || !(BlockingDialog is UIMobileAlert) || ActiveEntity == null) return;
BlockingDialog.Close(); BlockingDialog.Close();
var ma = (UIMobileAlert)BlockingDialog;
LastDialogID = 0; LastDialogID = 0;
vm.SendCommand(new VMNetDialogResponseCmd vm.SendCommand(new VMNetDialogResponseCmd
{ {
ActorUID = ActiveEntity.PersistID, ActorUID = ActiveEntity.PersistID,
ResponseCode = code, ResponseCode = code,
ResponseText = (BlockingDialog.ResponseText == null) ? "" : BlockingDialog.ResponseText ResponseText = (ma.ResponseText == null) ? "" : ma.ResponseText
}); });
BlockingDialog = null; BlockingDialog = null;
} }
@ -507,8 +523,8 @@ namespace Simitone.Client.UI.Panels
{ {
OldMX = state.MouseState.X; OldMX = state.MouseState.X;
OldMY = state.MouseState.Y; OldMY = state.MouseState.Y;
var newHover = World.GetObjectIDAtScreenPos(state.MouseState.X / FSOEnvironment.DPIScaleFactor, var newHover = World.GetObjectIDAtScreenPos(state.MouseState.X,
state.MouseState.Y / FSOEnvironment.DPIScaleFactor, state.MouseState.Y,
GameFacade.GraphicsDevice); GameFacade.GraphicsDevice);
if (ObjectHover != newHover) if (ObjectHover != newHover)
@ -671,9 +687,7 @@ namespace Simitone.Client.UI.Panels
if (World.State.Zoom != targetZoom) World.State.Zoom = targetZoom; if (World.State.Zoom != targetZoom) World.State.Zoom = targetZoom;
WorldConfig.Current.SmoothZoom = false; WorldConfig.Current.SmoothZoom = false;
} }
//Cheats.Update(state);
//AvatarDS.Update();
if (ActiveEntity == null || ActiveEntity.Dead || ActiveEntity.PersistID != SelectedSimID) if (ActiveEntity == null || ActiveEntity.Dead || ActiveEntity.PersistID != SelectedSimID)
{ {
ActiveEntity = vm.Entities.FirstOrDefault(x => x is VMAvatar && x.PersistID == SelectedSimID); //try and hook onto a sim if we have none selected. ActiveEntity = vm.Entities.FirstOrDefault(x => x is VMAvatar && x.PersistID == SelectedSimID); //try and hook onto a sim if we have none selected.
@ -690,6 +704,28 @@ namespace Simitone.Client.UI.Panels
if (GotoObject == null) GotoObject = vm.Context.CreateObjectInstance(GOTO_GUID, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true).Objects[0]; if (GotoObject == null) GotoObject = vm.Context.CreateObjectInstance(GOTO_GUID, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true).Objects[0];
//update plumbbob
var plumb = Content.Get().RCMeshes.Get("arrow.fsom");
foreach (VMAvatar avatar in vm.Context.ObjectQueries.Avatars)
{
if (avatar.Avatar == null) continue;
var isActive = (avatar == ActiveEntity);
if ((avatar.Avatar.HeadObject == plumb) != isActive)
{
avatar.Avatar.HeadObject = (avatar == ActiveEntity) ? plumb : null;
avatar.Avatar.HeadObjectSpeedyVel = 0.2f;
}
avatar.Avatar.HeadObjectRotation += 3f / FSOEnvironment.RefreshRate;
if (isActive)
{
avatar.Avatar.HeadObjectRotation += avatar.Avatar.HeadObjectSpeedyVel;
avatar.Avatar.HeadObjectSpeedyVel *= 0.98f;
} else if (avatar.GetValue(FSO.SimAntics.Model.VMStackObjectVariable.Category) == 87)
{
avatar.Avatar.HeadObject = Content.Get().RCMeshes.Get("star.fsom");
}
}
/* /*
if (ActiveEntity != null && BlockingDialog != null) if (ActiveEntity != null && BlockingDialog != null)
{ {
@ -775,6 +811,21 @@ namespace Simitone.Client.UI.Panels
PieMenu = null; PieMenu = null;
} }
if (state.NewKeys.Contains(Keys.F8))
{
UIMobileAlert alert = null;
alert = new UIMobileAlert(new UIAlertOptions()
{
Title = "Debug Lot Thumbnail",
Message = "Arch Value: "+VMArchitectureStats.GetArchValue(vm.Context.Architecture),
Buttons = UIAlertButton.Ok((btn) => UIScreen.RemoveDialog(alert))
});
Texture2D roofless = null;
var thumb = World.GetLotThumb(GameFacade.GraphicsDevice, (tex) => roofless = FSO.Common.Utils.TextureUtils.Decimate(tex, GameFacade.GraphicsDevice, 2, false));
thumb = FSO.Common.Utils.TextureUtils.Decimate(thumb, GameFacade.GraphicsDevice, 2, false);
alert.SetIcon(thumb, thumb.Width, thumb.Height);
UIScreen.GlobalShowDialog(alert, true);
}
if (LiveMode) LiveModeUpdate(state, scrolled); if (LiveMode) LiveModeUpdate(state, scrolled);
else if (CustomControl != null) else if (CustomControl != null)
{ {

View file

@ -99,6 +99,12 @@ namespace Simitone.Client.UI.Panels
RefreshSize(); RefreshSize();
} }
public override void GameResized()
{
base.GameResized();
RefreshSize();
}
public void RefreshSize() public void RefreshSize()
{ {
var w = Width; var w = Width;
@ -123,14 +129,7 @@ namespace Simitone.Client.UI.Panels
h += 45; h += 45;
} }
var btnX = (w - ((Buttons.Count-1) * 350)) / 2; h = ResetButtons(h, true);
var btnY = h - 125;
foreach (UIButton button in Buttons)
{
button.Y = btnY;
button.X = btnX - button.Width/2;
btnX += 350;
}
if (Height != h) if (Height != h)
{ {
@ -139,6 +138,47 @@ namespace Simitone.Client.UI.Panels
//update bg with height //update bg with height
} }
private int ResetButtons(int h, bool setY)
{
var btnX = Width/2;
var btnY = h - 125;
var totalBtnWidth = Buttons.Sum(x => x.Width);
int runningWidth = 0;
int start = 0;
int i = 0;
for (i=0; i<Buttons.Count; i++)
{
var btn = Buttons[i];
if (runningWidth == 0 || (Width-50) - runningWidth > btn.Width)
{
btn.X = btnX + runningWidth;
} else
{
btnY += 120;
h += 120;
//center buttons
runningWidth -= 25;
for (int j=start; j<i; j++)
{
Buttons[j].X -= runningWidth / 2;
}
runningWidth = 0;
start = i;
btn.X = btnX + runningWidth;
}
runningWidth += (int)btn.Width + 25;
if (setY) btn.Y = btnY;
}
runningWidth -= 25;
for (int j = start; j < i; j++)
{
Buttons[j].X -= runningWidth / 2;
}
return h;
}
private float TargetIX; private float TargetIX;
public void SetIcon(Texture2D img, int width, int height) public void SetIcon(Texture2D img, int width, int height)
@ -226,12 +266,11 @@ namespace Simitone.Client.UI.Panels
{ {
Icon.Visible = true; Icon.Visible = true;
Icon.X = newIX; Icon.X = newIX;
var btnX = (Width - ((Buttons.Count - 1) * 350)) / 2; ResetButtons(Height, false);
foreach (UIButton button in Buttons) foreach (var btn in Buttons)
{ {
button.X = off + btnX - button.Width / 2; btn.X += off;
button.Visible = true; btn.Visible = true;
btnX += 350;
} }
} }
} }

View file

@ -62,6 +62,7 @@ namespace Simitone.Client.UI.Panels
BuildButton, BuildButton,
OptionButton OptionButton
}; };
UpdateBuildBuy();
} }
public override void Update(UpdateState state) public override void Update(UpdateState state)
@ -73,6 +74,13 @@ namespace Simitone.Client.UI.Panels
} }
} }
public void UpdateBuildBuy()
{
var bbEnable = Game.vm.Context.Architecture.BuildBuyEnabled;
BuyButton.Disabled = !bbEnable;
BuildButton.Disabled = !bbEnable;
}
public void EndSwitch(UIMainPanelMode mode) public void EndSwitch(UIMainPanelMode mode)
{ {
UIButton frontButton; UIButton frontButton;

View file

@ -17,6 +17,10 @@ using FSO.Client;
using FSO.Content; using FSO.Content;
using FSO.Common.Utils; using FSO.Common.Utils;
using Simitone.Client.UI.Controls; using Simitone.Client.UI.Controls;
using Simitone.Client.Utils;
using FSO.Common;
using System.IO;
using FSO.Files.RC;
namespace Simitone.Client.UI.Panels namespace Simitone.Client.UI.Panels
{ {
@ -127,7 +131,6 @@ namespace Simitone.Client.UI.Panels
GameResized(); GameResized();
} }
public void UpdatePosition() public void UpdatePosition()
{ {
base.GameResized(); base.GameResized();
@ -203,6 +206,7 @@ namespace Simitone.Client.UI.Panels
Zoom = Zoom; Zoom = Zoom;
CenterPositionX = CenterPositionX; CenterPositionX = CenterPositionX;
CenterPositionY = CenterPositionY; CenterPositionY = CenterPositionY;
//SimitoneNeighOBJExporter.SaveOBJ(Path.Combine(FSOEnvironment.UserDir, "NeighModel" + mode + "/"), locations);
} }
public void ResetZoom() public void ResetZoom()
@ -337,17 +341,26 @@ namespace Simitone.Client.UI.Panels
public UINeighborhoodHouseButton(int houseNumber, Action<int> selectionCallback, float scale) public UINeighborhoodHouseButton(int houseNumber, Action<int> selectionCallback, float scale)
{ {
if (houseNumber == 71) { }
AlphaTime = 0; AlphaTime = 0;
var house = Content.Get().Neighborhood.GetHouse(houseNumber); var house = Content.Get().Neighborhood.GetHouse(houseNumber);
HouseTex = house.Get<BMP>(513).GetTexture(GameFacade.GraphicsDevice); HouseTex = house.Get<BMP>(513)?.GetTexture(GameFacade.GraphicsDevice);
HouseOpenTex = house.Get<BMP>(512).GetTexture(GameFacade.GraphicsDevice); if (HouseTex != null) {
HouseOpenTex = house.Get<BMP>(512).GetTexture(GameFacade.GraphicsDevice);
Offsets = house.Get<THMB>(512); //get offsets before scaling
} else
{
HouseTex = house.Get<PNG>(513).GetTexture(GameFacade.GraphicsDevice);
HouseOpenTex = house.Get<PNG>(512).GetTexture(GameFacade.GraphicsDevice);
Offsets = new THMB() { Width = HouseTex.Width / 2, Height = HouseTex.Height / 2 };
}
HouseScale = scale; HouseScale = scale;
Offsets = house.Get<THMB>(512); //get offsets before scaling
var w = (int)(HouseTex.Width / HouseScale); var w = (int)(HouseTex.Width / HouseScale);
var h = (int)(HouseTex.Height / HouseScale); var h = (int)(HouseTex.Height / HouseScale);
var clickHandler = var clickHandler =
ListenForMouse(new Rectangle(w / -2, h / -2, w, h), (evt, state) => ListenForMouse(new Rectangle(w / -2, w / -4, w, h/2), (evt, state) =>
{ {
switch (evt) switch (evt)
{ {
@ -367,13 +380,13 @@ namespace Simitone.Client.UI.Panels
public override void Draw(UISpriteBatch batch) public override void Draw(UISpriteBatch batch)
{ {
var yOff = new Vector2(Offsets.XOff, Offsets.BaseYOff) / (HouseScale * 2f); var yOff = new Vector2(Offsets.XOff, -Offsets.BaseYOff) / HouseScale;
var yOff2 = yOff; var yOff2 = yOff;
yOff2.Y -= Offsets.AddYOff / (HouseScale); yOff2.Y -= Offsets.AddYOff / (HouseScale);
DrawLocalTexture(batch, HouseTex, null, new Vector2(-HouseTex.Width, -HouseTex.Height) / (HouseScale * 2) + yOff, new Vector2(1f / HouseScale, 1f / HouseScale)); DrawLocalTexture(batch, HouseTex, null, new Vector2(-Offsets.Width, -Offsets.Height)/ HouseScale + yOff, new Vector2(1f / HouseScale, 1f / HouseScale));
if (AlphaTime > 0) if (AlphaTime > 0)
{ {
DrawLocalTexture(batch, HouseOpenTex, null, new Vector2(-HouseTex.Width, -HouseTex.Height) / (HouseScale * 2) + yOff2, new Vector2(1f / HouseScale, 1f / HouseScale), Color.White * AlphaTime); DrawLocalTexture(batch, HouseOpenTex, null, new Vector2(-Offsets.Width, -Offsets.Height)/ HouseScale + yOff2, new Vector2(1f / HouseScale, 1f / HouseScale), Color.White * AlphaTime);
} }
} }

View file

@ -17,25 +17,33 @@ namespace Simitone.Client.UI.Panels
public List<UIElasticButton> RightBtns = new List<UIElasticButton>(); public List<UIElasticButton> RightBtns = new List<UIElasticButton>();
private UINeighborhoodSelectionPanel Panel; private UINeighborhoodSelectionPanel Panel;
private ushort Mode; private ushort Mode;
public bool MoveInMode;
public UINeighbourhoodSwitcher(UINeighborhoodSelectionPanel panel, ushort mode) public UINeighbourhoodSwitcher(UINeighborhoodSelectionPanel panel, ushort mode, bool moveIn)
{ {
Panel = panel; Panel = panel;
SetMode(mode); SetMode(mode, moveIn);
} }
public void SetMode(ushort mode) public void SetMode(ushort mode, bool moveIn)
{ {
MoveInMode = moveIn;
foreach (var btn in LeftBtns) Remove(btn); foreach (var btn in LeftBtns) Remove(btn);
foreach (var btn in RightBtns) Remove(btn); foreach (var btn in RightBtns) Remove(btn);
LeftBtns.Clear(); RightBtns.Clear(); LeftBtns.Clear(); RightBtns.Clear();
AddBtn(LeftBtns, "ngbh_cas.png", (btn) => GameController.EnterCAS()); AddBtn(LeftBtns, "ngbh_cas.png", (btn) =>
{
var transition = new UITransDialog("cas", () =>
{
GameController.EnterCAS();
});
});
if (mode != 4) AddBtn(LeftBtns, "ngbh_back.png", (btn) => PopMode(4)); if (mode != 4) AddBtn(LeftBtns, "ngbh_back.png", (btn) => PopMode(4));
if (mode != 2) AddBtn(RightBtns, "ngbh_downt.png", (btn) => PopMode(2)); if (mode != 2 && !moveIn) AddBtn(RightBtns, "ngbh_downt.png", (btn) => PopMode(2));
if (mode != 3) AddBtn(RightBtns, "ngbh_vacat.png", (btn) => PopMode(3)); if (mode != 3 && !moveIn) AddBtn(RightBtns, "ngbh_vacat.png", (btn) => PopMode(3));
if (mode != 5) AddBtn(RightBtns, "ngbh_studio.png", (btn) => PopMode(5)); if (mode != 5 && !moveIn) AddBtn(RightBtns, "ngbh_studio.png", (btn) => PopMode(5));
if (mode != 7) AddBtn(RightBtns, "ngbh_magic.png", (btn) => PopMode(7)); if (mode != 7) AddBtn(RightBtns, "ngbh_magic.png", (btn) => PopMode(7));
Mode = mode; Mode = mode;
@ -45,7 +53,7 @@ namespace Simitone.Client.UI.Panels
public void PopMode(ushort mode) public void PopMode(ushort mode)
{ {
Panel.PopulateScreen(mode); Panel.PopulateScreen(mode);
SetMode(mode); SetMode(mode, MoveInMode);
} }
private void LayBtns() private void LayBtns()

View file

@ -117,7 +117,7 @@ namespace Simitone.Client.UI.Panels
//rotate through to try all configurations //rotate through to try all configurations
var dir = Holding.Dir; var dir = Holding.Dir;
VMPlacementError status = VMPlacementError.Success; VMPlacementError status = VMPlacementError.Success;
if (!Holding.IsBought && !vm.TSOState.CanPlaceNewUserObject(vm)) status = VMPlacementError.TooManyObjectsOnTheLot; if (!Holding.IsBought && !vm.PlatformState.CanPlaceNewUserObject(vm)) status = VMPlacementError.TooManyObjectsOnTheLot;
else else
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -164,7 +164,7 @@ namespace Simitone.Client.UI.Panels
if (UseNet || !Holding.IsBought) if (UseNet || !Holding.IsBought)
{ {
Holding.Group.Delete(vm.Context); RecursiveDelete(vm.Context, Holding.Group.BaseObject);
} else } else
{ {
if (Holding.RealEnt == null) Holding.RealEnt = Holding.Group.BaseObject; if (Holding.RealEnt == null) Holding.RealEnt = Holding.Group.BaseObject;
@ -182,6 +182,27 @@ namespace Simitone.Client.UI.Panels
vm.Tick(); vm.Tick();
} }
private void RecursiveDelete(VMContext context, VMEntity real)
{
var rgrp = real.MultitileGroup;
for (int i = 0; i < rgrp.Objects.Count; i++)
{
var slots = rgrp.Objects[i].TotalSlots();
var objs = new List<VMEntity>();
for (int j = 0; j < slots; j++)
{
var slot = rgrp.Objects[i].GetSlot(j);
if (slot != null)
{
objs.Add(slot);
}
}
foreach (var obj in objs) RecursiveDelete(context, obj);
}
rgrp.Delete(context);
}
public void MouseDown(UpdateState state) public void MouseDown(UpdateState state)
{ {
MouseIsDown = true; MouseIsDown = true;
@ -357,7 +378,7 @@ namespace Simitone.Client.UI.Panels
{ {
MoveSelected(Holding.TilePos, Holding.Level); MoveSelected(Holding.TilePos, Holding.Level);
if (!Holding.IsBought && Holding.CanPlace == VMPlacementError.Success && if (!Holding.IsBought && Holding.CanPlace == VMPlacementError.Success &&
ParentControl.ActiveEntity != null && ParentControl.ActiveEntity.TSOState.Budget.Value < Holding.Price) ParentControl.ActiveEntity != null && ParentControl.Budget < Holding.Price)
Holding.CanPlace = VMPlacementError.InsufficientFunds; Holding.CanPlace = VMPlacementError.InsufficientFunds;
if (Holding.CanPlace != VMPlacementError.Success) if (Holding.CanPlace != VMPlacementError.Success)
{ {
@ -390,7 +411,7 @@ namespace Simitone.Client.UI.Panels
else if (MouseClicked) else if (MouseClicked)
{ {
//not holding an object, but one can be selected //not holding an object, but one can be selected
var newHover = World.GetObjectIDAtScreenPos(state.MouseState.X / FSOEnvironment.DPIScaleFactor, state.MouseState.Y / FSOEnvironment.DPIScaleFactor, GameFacade.GraphicsDevice); var newHover = World.GetObjectIDAtScreenPos(state.MouseState.X, state.MouseState.Y, GameFacade.GraphicsDevice);
if (MouseClicked && (newHover != 0) && (vm.GetObjectById(newHover) is VMGameObject)) if (MouseClicked && (newHover != 0) && (vm.GetObjectById(newHover) is VMGameObject))
{ {
var objGroup = vm.GetObjectById(newHover).MultitileGroup; var objGroup = vm.GetObjectById(newHover).MultitileGroup;

View file

@ -17,6 +17,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FSO.Common.Rendering.Framework.Model; using FSO.Common.Rendering.Framework.Model;
using FSO.Common.Rendering.Framework.IO; using FSO.Common.Rendering.Framework.IO;
using FSO.UI.Panels;
namespace Simitone.Client.UI.Panels namespace Simitone.Client.UI.Panels
{ {

View file

@ -18,6 +18,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FSO.Common.Rendering.Framework.Model; using FSO.Common.Rendering.Framework.Model;
using FSO.Common; using FSO.Common;
using FSO.UI.Panels;
namespace Simitone.Client.UI.Panels namespace Simitone.Client.UI.Panels
{ {
@ -130,6 +131,8 @@ namespace Simitone.Client.UI.Panels
Title.Alignment = TextAlignment.Left | TextAlignment.Top; Title.Alignment = TextAlignment.Left | TextAlignment.Top;
Body.Alignment = TextAlignment.Left | TextAlignment.Top; Body.Alignment = TextAlignment.Left | TextAlignment.Top;
InternalBefore = true;
} }
public override void Update(UpdateState state) public override void Update(UpdateState state)

View file

@ -12,6 +12,10 @@ using FSO.Client;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Simitone.Client.UI.Panels.LiveSubpanels; using Simitone.Client.UI.Panels.LiveSubpanels;
using FSO.Client.UI.Model; using FSO.Client.UI.Model;
using Microsoft.Xna.Framework.Input;
using FSO.SimAntics;
using FSO.SimAntics.NetPlay.Model.Commands;
using FSO.HIT;
namespace Simitone.Client.UI.Panels namespace Simitone.Client.UI.Panels
{ {
@ -198,6 +202,22 @@ namespace Simitone.Client.UI.Panels
public float ClockTween; public float ClockTween;
public override void Update(UpdateState state) public override void Update(UpdateState state)
{ {
if (state.NewKeys.Contains(Keys.Space))
{
var selected = Game.LotControl.ActiveEntity;
var familyMembers = Game.vm.Context.ObjectQueries.Avatars.Where(x =>
((VMAvatar)x).GetPersonData(
FSO.SimAntics.Model.VMPersonDataVariable.TS1FamilyNumber) == (Game.vm.TS1State.CurrentFamily?.ChunkID)
).ToList();
var index = familyMembers.IndexOf(selected);
if (familyMembers.Count > 0)
{
index = (index + 1) % (familyMembers.Count);
HITVM.Get().PlaySoundEvent(UISounds.QueueAdd);
Game.vm.SendCommand(new VMNetChangeControlCmd() { TargetID = familyMembers[index].ObjectID });
}
}
base.Update(state); base.Update(state);
if (LastCut != Game.LotControl.WallsMode) if (LastCut != Game.LotControl.WallsMode)
{ {

View file

@ -27,7 +27,7 @@ namespace Simitone.Client.UI.Panels
Game = screen; Game = screen;
Bg = Content.Get().CustomUI.Get("pswitch_bg.png").Get(GameFacade.GraphicsDevice); Bg = Content.Get().CustomUI.Get("pswitch_bg.png").Get(GameFacade.GraphicsDevice);
var familyMembers = Game.vm.Context.ObjectQueries.Avatars.Where(x => ((VMAvatar)x).GetPersonData(FSO.SimAntics.Model.VMPersonDataVariable.TS1FamilyNumber) == (Game.vm.CurrentFamily?.ChunkID)); var familyMembers = Game.vm.Context.ObjectQueries.Avatars.Where(x => ((VMAvatar)x).GetPersonData(FSO.SimAntics.Model.VMPersonDataVariable.TS1FamilyNumber) == (Game.vm.TS1State.CurrentFamily?.ChunkID));
int i = 0; int i = 0;
foreach (var fam in familyMembers) foreach (var fam in familyMembers)
{ {

View file

@ -0,0 +1,99 @@
using FSO.Client;
using FSO.Client.UI.Framework;
using FSO.Common.Utils;
using FSO.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Simitone.Client.UI.Controls;
using Simitone.Client.UI.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simitone.Client.UI.Panels
{
public class UITransDialog : UIContainer
{
private float _TransPct;
public float TransPct {
get
{
return _TransPct;
}
set
{
Diag.X = Math.Max(0, (value - 1) * UIScreen.Current.ScreenWidth);
Diag.BodySize = new Vector2(Math.Min(1, value) * UIScreen.Current.ScreenWidth, UIScreen.Current.ScreenHeight).ToPoint();
Diag.DiagSide = (value <= 1) ? UIDiagonalStripeSide.RIGHT : UIDiagonalStripeSide.LEFT;
if (value == 1 && !FiredTransition)
{
FiredTransition = true;
GameThread.NextUpdate((u) =>
{
UIScreen.RemoveDialog(this);
TransAction();
UIScreen.GlobalShowDialog(this, true);
GameThread.NextUpdate((u2) =>
{
if (!UIScreen.Current.GetChildren().Contains(this))
{
DrawsSince = 0;
Parent = null;
UIScreen.GlobalShowDialog(this, true);
}
});
});
}
if (value == 2 && FiredTransition)
{
UIScreen.RemoveDialog(this);
}
_TransPct = value;
}
}
public bool FiredTransition = false;
private UIDiagonalStripe Diag;
private Texture2D TransImage;
private Action TransAction;
public UITransDialog(string transType, Action transAction)
{
var ui = Content.Get().CustomUI;
TransImage = ui.Get($"trans_{transType}.png").Get(GameFacade.GraphicsDevice);
TransAction = transAction;
Diag = new UIDiagonalStripe(new Point(0,0), UIDiagonalStripeSide.RIGHT, UIStyle.Current.TransColor);
Add(Diag);
UIScreen.GlobalShowDialog(this, true);
GameFacade.Screens.Tween.To(this, 0.2f, new Dictionary<string, float>() { { "TransPct", 1f } });
TransPct = TransPct;
}
public override void Removed()
{
base.Removed();
}
public int DrawsSince = 0;
public override void Draw(UISpriteBatch batch)
{
base.Draw(batch);
DrawLocalTexture(batch, TransImage, null,
new Vector2(UIScreen.Current.ScreenWidth - TransImage.Width, UIScreen.Current.ScreenHeight - TransImage.Height) / 2,
Vector2.One, Color.White * (1-Math.Abs(1-TransPct)));
if (FiredTransition && TransPct == 1)
{
if (DrawsSince++ == 2)
{
GameFacade.Screens.Tween.To(this, 0.2f, new Dictionary<string, float>() { { "TransPct", 2f } });
}
}
if (TransPct > 1) { }
}
}
}

View file

@ -23,10 +23,19 @@ namespace Simitone.Client.UI.Panels.WorldUI
{ {
Style = TextStyle.DefaultLabel.Clone(); Style = TextStyle.DefaultLabel.Clone();
Style.Size = 12; Style.Size = 12;
var value = (int)(headline.Operand.Flags2 | (ushort)(headline.Operand.Duration << 16)); var value = (int)(headline.Operand.Flags2 | (headline.Operand.Duration << 16));
Text = (value > 0)?("§" + value):("-§"+ value); if (value < -10000)
{
Text = (-10000-value).ToString();
Style.Color = Model.UIStyle.Current.SecondaryText;
}
else
{
Text = (value > 0) ? ("§" + value) : ("-§" + value);
Style.Color = Model.UIStyle.Current.Text;
}
var measure = Style.MeasureString(Text); var measure = Style.MeasureString(Text);
Style.Color = Model.UIStyle.Current.Text;
var GD = GameFacade.GraphicsDevice; var GD = GameFacade.GraphicsDevice;
MoneyTarget = new RenderTarget2D(GD, (int)measure.X+10, (int)measure.Y+30); MoneyTarget = new RenderTarget2D(GD, (int)measure.X+10, (int)measure.Y+30);

View file

@ -14,6 +14,7 @@ using Simitone.Client.UI.Controls;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Graphics;
using FSO.Common.Utils; using FSO.Common.Utils;
using FSO.SimAntics;
namespace Simitone.Client.UI.Screens namespace Simitone.Client.UI.Screens
{ {
@ -94,6 +95,7 @@ namespace Simitone.Client.UI.Screens
(new Thread(() => { (new Thread(() => {
FSO.Content.Content.Init(GlobalSettings.Default.StartupPath, GameFacade.GraphicsDevice); FSO.Content.Content.Init(GlobalSettings.Default.StartupPath, GameFacade.GraphicsDevice);
VMContext.InitVMConfig();
lock (this) lock (this)
{ {
LoadingComplete = true; LoadingComplete = true;

View file

@ -26,6 +26,11 @@ using FSO.Content.TS1;
using Simitone.Client.UI.Panels.CAS; using Simitone.Client.UI.Panels.CAS;
using Simitone.Client.UI.Controls; using Simitone.Client.UI.Controls;
using FSO.SimAntics.Model; using FSO.SimAntics.Model;
using FSO.Files.Formats.IFF.Chunks;
using Simitone.Client.UI.Panels;
using FSO.Client.UI.Controls;
using Simitone.Client.Utils;
using FSO.SimAntics.Utils;
namespace Simitone.Client.UI.Screens namespace Simitone.Client.UI.Screens
{ {
@ -35,6 +40,7 @@ namespace Simitone.Client.UI.Screens
public FSO.SimAntics.VM vm { get; set; } public FSO.SimAntics.VM vm { get; set; }
public VMNetDriver Driver; public VMNetDriver Driver;
public BasicCamera Cam; public BasicCamera Cam;
public bool Initialized;
public VMAvatar[] HeadAvatars; public VMAvatar[] HeadAvatars;
public VMAvatar[] BodyAvatars; public VMAvatar[] BodyAvatars;
public List<string> ActiveHeads; public List<string> ActiveHeads;
@ -42,16 +48,19 @@ namespace Simitone.Client.UI.Screens
public List<string> ActiveHeadTex; public List<string> ActiveHeadTex;
public List<string> ActiveHandgroupTex; public List<string> ActiveHandgroupTex;
public List<string> ActiveBodyTex; public List<string> ActiveBodyTex;
public static int NeighTypeFrom = 4;
private bool Dead; private bool Dead;
private float _FamilySimInterp; private float _FamilySimInterp = -2;
public float FamilySimInterp public float FamilySimInterp
{ {
set set
{ {
CameraInterp(value); CameraInterp(value);
CASPanel.Position = new Vector2((ScreenWidth - 500) / 2, 10 - (282 * (1-value))); CASPanel.Position = new Vector2((Cam == null)?10:((ScreenWidth - 500) / 2), 10 - (282 * (1-value)));
FamilyPanel.ShowI = 1-Math.Abs(value); FamilyPanel.ShowI = 1-Math.Abs(value);
FamiliesPanel.TitleI = 1 - Math.Abs(value+1);
_FamilySimInterp = value; _FamilySimInterp = value;
} }
@ -75,6 +84,8 @@ namespace Simitone.Client.UI.Screens
public string CurrentSkin = "lgt"; public string CurrentSkin = "lgt";
private bool CurrentChild; private bool CurrentChild;
private int? MoveInFamily;
private UICASMode Mode = UICASMode.FamilyEdit; private UICASMode Mode = UICASMode.FamilyEdit;
public List<CASFamilyMember> WIPFamily = new List<CASFamilyMember>(); public List<CASFamilyMember> WIPFamily = new List<CASFamilyMember>();
@ -82,11 +93,13 @@ namespace Simitone.Client.UI.Screens
public UISimCASPanel CASPanel; public UISimCASPanel CASPanel;
public UIFamilyCASPanel FamilyPanel; public UIFamilyCASPanel FamilyPanel;
public UIFamiliesCASPanel FamiliesPanel;
public UITwoStateButton BackButton; public UITwoStateButton BackButton;
public UITwoStateButton AcceptButton; public UITwoStateButton AcceptButton;
public Vector3[] ModePositions = new Vector3[] public Vector3[] ModePositions = new Vector3[]
{ {
new Vector3(177.3843f, 150.92333f, 3.25105f),
new Vector3(157.3843f, 28.92333f, 23.25105f), new Vector3(157.3843f, 28.92333f, 23.25105f),
new Vector3(119.5611f, 6.122346f, 104.0364f), new Vector3(119.5611f, 6.122346f, 104.0364f),
new Vector3(114.0793f, 10f, 64.67827f) new Vector3(114.0793f, 10f, 64.67827f)
@ -94,13 +107,23 @@ namespace Simitone.Client.UI.Screens
public Vector3[] ModeTargets = new Vector3[] public Vector3[] ModeTargets = new Vector3[]
{ {
new Vector3(177.3843f-7f, 130.92333f, 3.25105f+5f),
new Vector3(150.3057f, 26.01005f, 29.6858f), new Vector3(150.3057f, 26.01005f, 29.6858f),
new Vector3(111.7678f, 3.936443f, 98.164f), new Vector3(111.7678f, 3.936443f, 98.164f),
new Vector3(104.5736f, 6.896059f, 64.59684f) new Vector3(104.5736f, 6.896059f, 64.59684f)
}; };
public Vector3[] Mode2D = new Vector3[]
{
new Vector3(104, 0, 57),
new Vector3(104, 0, 57),
new Vector3(103.5611f, 0, 92.0364f),
new Vector3(84.0793f+6, 0, 64f-6)
};
public Vector3[] SinTransitions = new Vector3[] public Vector3[] SinTransitions = new Vector3[]
{ {
new Vector3(0, 0, 0),
new Vector3(12f, 0, 0), new Vector3(12f, 0, 0),
new Vector3(-6f, 0, 0), new Vector3(-6f, 0, 0),
new Vector3() new Vector3()
@ -108,24 +131,44 @@ namespace Simitone.Client.UI.Screens
public void CameraInterp(float value) public void CameraInterp(float value)
{ {
if (value < -1) return; if (value < -2) value = -2;
var prev = (int)(value + 1); var prev = (int)(value + 2);
var next = (int)(Math.Ceiling(value) + 1); var next = (int)(Math.Ceiling(value) + 2);
if (next > 2) next = 2; if (next > 3) next = 3;
var pos1 = ModePositions[prev]; if (Cam == null)
var pos2 = ModePositions[next]; {
var targ1 = ModeTargets[prev] - pos1; //2d
var targ2 = ModeTargets[next] - pos2; var pos1 = Mode2D[prev];
var pos2 = Mode2D[next];
value = (float)DirectionUtils.PosMod(value, 1.0); if (World != null) World.State.PreciseZoom = 1 + Math.Min(0, value*0.5f);
var camvec = Vector3.Lerp(targ1, targ2, value); value = (float)DirectionUtils.PosMod(value, 1.0);
var campos = Vector3.Lerp(pos1, pos2, value); var campos = Vector3.Lerp(pos1, pos2, value);
campos += (float)Math.Sin(value * Math.PI) * SinTransitions[prev];
campos += (float)Math.Sin(value * Math.PI) * SinTransitions[prev];
Cam.Position = campos;
Cam.Target = campos + camvec; if (World != null)
World.State.CenterTile = new Vector2(campos.X, campos.Z) / 3f;
}
else
{
var pos1 = ModePositions[prev];
var pos2 = ModePositions[next];
var targ1 = ModeTargets[prev] - pos1;
var targ2 = ModeTargets[next] - pos2;
value = (float)DirectionUtils.PosMod(value, 1.0);
var camvec = Vector3.Lerp(targ1, targ2, value);
var campos = Vector3.Lerp(pos1, pos2, value);
campos += (float)Math.Sin(value * Math.PI) * SinTransitions[prev];
Cam.Position = campos;
Cam.Target = campos + camvec;
}
} }
private void PopulateSimType(string simtype) private void PopulateSimType(string simtype)
@ -135,8 +178,6 @@ namespace Simitone.Client.UI.Screens
if (simtype[1] == 'c') simtype += "chd"; if (simtype[1] == 'c') simtype += "chd";
var bodies = Content.Get().BCFGlobal.CollectionsByName["b"].ClothesByAvatarType[simtype]; var bodies = Content.Get().BCFGlobal.CollectionsByName["b"].ClothesByAvatarType[simtype];
//todo: search for textures
var tex = (TS1AvatarTextureProvider)Content.Get().AvatarTextures; var tex = (TS1AvatarTextureProvider)Content.Get().AvatarTextures;
var texnames = tex.GetAllNames(); var texnames = tex.GetAllNames();
ActiveHeads = heads; ActiveHeads = heads;
@ -207,7 +248,7 @@ namespace Simitone.Client.UI.Screens
var moving = 0; var moving = 0;
if (state.MouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed) if (state.MouseStates.Count > 0)
{ {
if (XLast == -1) if (XLast == -1)
{ {
@ -396,6 +437,10 @@ namespace Simitone.Client.UI.Screens
FamilyPanel.ModifySim = ModifySim; FamilyPanel.ModifySim = ModifySim;
Add(FamilyPanel); Add(FamilyPanel);
FamiliesPanel = new UIFamiliesCASPanel();
FamiliesPanel.OnNewFamily += () => { SetMode(UICASMode.FamilyEdit); };
Add(FamiliesPanel);
BackButton = new UITwoStateButton(ui.Get("btn_back.png").Get(gd)); BackButton = new UITwoStateButton(ui.Get("btn_back.png").Get(gd));
BackButton.Position = new Vector2(25, ScreenHeight - 140); BackButton.Position = new Vector2(25, ScreenHeight - 140);
Add(BackButton); Add(BackButton);
@ -462,7 +507,7 @@ namespace Simitone.Client.UI.Screens
} }
for (int j = 0; j < 5; j++) for (int j = 0; j < 5; j++)
{ {
CASPanel.Personalities[j].Points = sim.Personality[j]; CASPanel.Personalities[j].Points = sim.Personality[j] / 100;
} }
CurrentSkin = sim.SkinColor; CurrentSkin = sim.SkinColor;
@ -492,6 +537,8 @@ namespace Simitone.Client.UI.Screens
CASPanel.UpdateType(); CASPanel.UpdateType();
} }
public UIMobileAlert ConfirmDialog;
private void Accept(UIElement button) private void Accept(UIElement button)
{ {
switch (Mode) switch (Mode)
@ -503,9 +550,27 @@ namespace Simitone.Client.UI.Screens
case UICASMode.FamilyEdit: case UICASMode.FamilyEdit:
//add or replace the family in the neighbourhood //add or replace the family in the neighbourhood
//need to generate an actual FAMI and save it for this //need to generate an actual FAMI and save it for this
if (ConfirmDialog == null)
{
ConfirmDialog = new UIMobileAlert(new UIAlertOptions()
{
Title = GameFacade.Strings.GetString("129", "13"),
Message = GameFacade.Strings.GetString("129", "14"),
Buttons = UIAlertButton.YesNo(
(ybtn) => { ConfirmDialog.Close(); Accept(ybtn); ConfirmDialog = null; },
(nbtn) => { ConfirmDialog.Close(); ConfirmDialog = null; }
)
});
UIScreen.GlobalShowDialog(ConfirmDialog, true);
return;
} else
{
SaveFamily();
}
break; break;
case UICASMode.FamilySelect: case UICASMode.FamilySelect:
//accept button here is move in. notify the neighbourhood screen that we're moving in now. //accept button here is move in. notify the neighbourhood screen that we're moving in now.
MoveInFamily = FamiliesPanel.Families[FamiliesPanel.Selection].ChunkID;
break; break;
} }
SetMode((UICASMode)(((int)Mode) - 1)); SetMode((UICASMode)(((int)Mode) - 1));
@ -513,6 +578,27 @@ namespace Simitone.Client.UI.Screens
private void GoBack(UIElement button) private void GoBack(UIElement button)
{ {
if (Mode == UICASMode.FamilyEdit)
{
if (ConfirmDialog == null)
{
ConfirmDialog = new UIMobileAlert(new UIAlertOptions()
{
Title = GameFacade.Strings.GetString("129", "7"),
Message = GameFacade.Strings.GetString("129", "8"),
Buttons = UIAlertButton.YesNo(
(ybtn) => { ConfirmDialog.Close(); GoBack(ybtn); ConfirmDialog = null; },
(nbtn) => { ConfirmDialog.Close(); ConfirmDialog = null; }
)
});
UIScreen.GlobalShowDialog(ConfirmDialog, true);
return;
}
else
{
ClearFamily();
}
}
SetMode((UICASMode)(((int)Mode) - 1)); SetMode((UICASMode)(((int)Mode) - 1));
} }
@ -521,13 +607,25 @@ namespace Simitone.Client.UI.Screens
if (mode == UICASMode.ToNeighborhood) if (mode == UICASMode.ToNeighborhood)
{ {
//todo: animate into this //todo: animate into this
CleanupLastWorld();
Dead = true; Dead = true;
GameController.EnterGameMode("", false); var dialog = new UITransDialog("normal", () => {
CleanupLastWorld();
if (MoveInFamily == null)
GameController.EnterGameMode("", false);
else
GameController.EnterGameMode("!"+((NeighTypeFrom == 7)?'m':'n')+MoveInFamily.Value.ToString(), false);
});
return;
} else if (mode == UICASMode.FamilyEdit) } else if (mode == UICASMode.FamilyEdit)
{ {
FamilyPanel.Reset(); FamilyPanel.Reset();
} }
FamiliesPanel.SetSelection(-1);
if (mode == UICASMode.FamilySelect) AcceptButton.Texture = Content.Get().CustomUI.Get("btn_movein.png").Get(GameFacade.GraphicsDevice);
else AcceptButton.Texture = Content.Get().CustomUI.Get("btn_accept.png").Get(GameFacade.GraphicsDevice);
GameFacade.Screens.Tween.To(this, 1f, new Dictionary<string, float> { { "FamilySimInterp", (int)mode-1 } }, TweenQuad.EaseInOut); GameFacade.Screens.Tween.To(this, 1f, new Dictionary<string, float> { { "FamilySimInterp", (int)mode-1 } }, TweenQuad.EaseInOut);
Mode = mode; Mode = mode;
} }
@ -553,25 +651,48 @@ namespace Simitone.Client.UI.Screens
public override void Update(UpdateState state) public override void Update(UpdateState state)
{ {
base.Update(state); base.Update(state);
ModePositions[2].Y = 11; ModePositions[3].Y = 11;
ModeTargets[2].Y = 7.896059f; ModeTargets[3].Y = 7.896059f;
if (Dead) return; if (Dead) return;
if (vm == null) InitializeLot(); if (vm == null) InitializeLot();
vm.Update(); vm.Update();
if (World != null && Cam == null) if (World != null && !Initialized)
{ {
var rcs = (WorldStateRC)(World.State); var rcs = (World.State as WorldStateRC);
Cam = (WorldCamera3D)rcs.Camera; if (rcs != null)
rcs.FixedCam = true; {
rcs.CameraMode = true; Cam = (WorldCamera3D)rcs.Camera;
SetMode(UICASMode.FamilyEdit); rcs.FixedCam = true;
rcs.CameraMode = true;
}
SetMode(UICASMode.FamilySelect);
SetFamilies();
Initialized = true;
//FamilySimInterp = FamilySimInterp; //FamilySimInterp = FamilySimInterp;
} }
if (World.State.Level != 2) if (World.State.PreciseZoom != 1) World.State.PreciseZoom = World.State.PreciseZoom;
switch (Mode)
{ {
World.State.Level = 2; case UICASMode.FamilySelect:
World.State.DrawRoofs = true; if (World.State.Level != 2)
{
World.State.Level = 2;
World.State.DrawRoofs = true;
vm.Context.Blueprint.Cutaway = new bool[vm.Context.Blueprint.Cutaway.Length];
vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED));
}
break;
default:
if (World.State.Level != 1 && Cam == null)
{
World.State.Level = 1;
World.State.DrawRoofs = false;
vm.Context.Blueprint.Cutaway = VMArchitectureTools.GenerateRoomCut(vm.Context.Architecture, World.State.Level, World.State.CutRotation,
new HashSet<uint>(vm.Context.RoomInfo.Where(x => x.Room.IsOutside == false).Select(x => (uint)x.Room.RoomID)));
vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED));
}
break;
} }
vm.Context.Clock.Minutes = 0; vm.Context.Clock.Minutes = 0;
@ -588,11 +709,17 @@ namespace Simitone.Client.UI.Screens
case UICASMode.SimEdit: case UICASMode.SimEdit:
if (CASPanel.FirstNameTextBox.CurrentText.Length == 0) disableAccept = true; if (CASPanel.FirstNameTextBox.CurrentText.Length == 0) disableAccept = true;
break; break;
case UICASMode.FamilySelect:
if (FamiliesPanel.Selection == -1) disableAccept = true;
break;
case UICASMode.FamilyEdit:
if (WIPFamily.Count == 0) disableAccept = true;
break;
} }
AcceptButton.Disabled = disableAccept; AcceptButton.Disabled = disableAccept;
AcceptButton.ForceState = disableAccept ? 0 : -1; //AcceptButton.ForceState = disableAccept ? 0 : -1;
AcceptButton.Opacity = disableAccept ? 0.5f : 1; //AcceptButton.Opacity = disableAccept ? 0.5f : 1;
if (Mode == UICASMode.SimEdit) if (Mode == UICASMode.SimEdit)
UpdateCarousel(state); UpdateCarousel(state);
@ -631,6 +758,15 @@ namespace Simitone.Client.UI.Screens
} }
} }
public void SetFamilies()
{
//get all families that don't have a house from neighbourhood, and populate the list
//i think house number -1 is townies, so only select 0
var all = Content.Get().Neighborhood.MainResource.List<FAMI>();
var families = all.Where(x => (x.Unknown & 16) > 0 && x.HouseNumber == 0);
FamiliesPanel.UpdateFamilies(families.ToList(), vm);
}
public void SetFamilyMember(int index) public void SetFamilyMember(int index)
{ {
if (RepresentFamily.Count <= index) if (RepresentFamily.Count <= index)
@ -684,6 +820,46 @@ namespace Simitone.Client.UI.Screens
fam.HeadOutfit = new FSO.SimAntics.Model.VMOutfitReference(new Outfit() { TS1AppearanceID = data.Head+".apr", TS1TextureID = data.HeadTex }); fam.HeadOutfit = new FSO.SimAntics.Model.VMOutfitReference(new Outfit() { TS1AppearanceID = data.Head+".apr", TS1TextureID = data.HeadTex });
} }
private SimTemplateCreateInfo CASToNeighGen(CASFamilyMember x)
{
var code = ((x.Gender & 1) == 0) ? "m" : "f";
code += (x.Gender > 1) ? "c" : "a";
var ind = x.Body.IndexOf("_");
var bodyType = x.Body.Substring(ind - 3, 3);
code += bodyType;
var info = new SimTemplateCreateInfo(code, x.SkinColor);
info.Name = x.Name;
info.Bio = x.Bio;
info.PersonalityPoints = x.Personality;
info.BodyStringReplace[1] = x.Body + ",BODY=" + x.BodyTex;
info.BodyStringReplace[2] = x.Head + ",HEAD-HEAD=" + x.HeadTex;
var hand = (x.Gender > 1) ? "u" : ((x.Gender == 0) ? "m" : "f");
info.BodyStringReplace[17] = "H" + hand + "LO,HAND=" + "huao" + x.HandgroupTex;
info.BodyStringReplace[18] = "H" + hand + "RO,HAND=" + "huao" + x.HandgroupTex;
info.BodyStringReplace[19] = "H" + hand + "LP,HAND=" + "huao" + x.HandgroupTex;
info.BodyStringReplace[20] = "H" + hand + "RP,HAND=" + "huao" + x.HandgroupTex;
info.BodyStringReplace[21] = "H" + hand + "LO,HAND=" + "huao" + x.HandgroupTex;
info.BodyStringReplace[22] = "H" + hand + "RC,HAND=" + "huao" + x.HandgroupTex;
return info;
}
public void ClearFamily()
{
var count = WIPFamily.Count;
FamilyPanel.SecondName.CurrentText = "";
for (int i = count-1; i >= 0; i--)
ModifySim(true, i);
}
public void SaveFamily()
{
SimitoneNeighbourGenerator.CreateFamily(FamilyPanel.SecondName.CurrentText, WIPFamily.Count, WIPFamily.Select(CASToNeighGen).ToArray());
SetFamilies();
ClearFamily();
}
public void AcceptMember() public void AcceptMember()
{ {
var mem = BuildMember(); var mem = BuildMember();
@ -713,7 +889,7 @@ namespace Simitone.Client.UI.Screens
Head = ActiveHeads[j], Head = ActiveHeads[j],
HeadTex = ActiveHeadTex[j], HeadTex = ActiveHeadTex[j],
Gender = (short)(((CurrentCode[0] == 'm') ? 0 : 1) | ((CurrentCode[1] == 'c') ? 2 : 0)), Gender = (short)(((CurrentCode[0] == 'm') ? 0 : 1) | ((CurrentCode[1] == 'c') ? 2 : 0)),
Personality = CASPanel.Personalities.Select(x => (short)x.Points).ToArray(), Personality = CASPanel.Personalities.Select(x => (short)(x.Points * 100)).ToArray(),
SkinColor = CurrentSkin SkinColor = CurrentSkin
}; };
return sim; return sim;
@ -746,7 +922,6 @@ namespace Simitone.Client.UI.Screens
//clear our cache too, if the setting lets us do that //clear our cache too, if the setting lets us do that
TimedReferenceController.Clear(); TimedReferenceController.Clear();
TimedReferenceController.Clear(); TimedReferenceController.Clear();
VM.ClearAssembled();
vm.Context.Ambience.Kill(); vm.Context.Ambience.Kill();
foreach (var ent in vm.Entities) foreach (var ent in vm.Entities)
@ -802,13 +977,11 @@ namespace Simitone.Client.UI.Screens
vm.Tick(); vm.Tick();
vm.Context.Clock.Hours = 12; vm.Context.Clock.Hours = 12;
vm.TSOState.Size = (10) | (3 << 8); vm.MyUID = uint.MaxValue;
vm.Context.UpdateTSOBuildableArea();
vm.MyUID = 1;
var settings = GlobalSettings.Default; var settings = GlobalSettings.Default;
var myClient = new VMNetClient var myClient = new VMNetClient
{ {
PersistID = 1, PersistID = uint.MaxValue,
RemoteIP = "local", RemoteIP = "local",
AvatarState = new VMNetAvatarPersistState() AvatarState = new VMNetAvatarPersistState()
{ {
@ -816,7 +989,7 @@ namespace Simitone.Client.UI.Screens
DefaultSuits = new VMAvatarDefaultSuits(settings.DebugGender), DefaultSuits = new VMAvatarDefaultSuits(settings.DebugGender),
BodyOutfit = settings.DebugBody, BodyOutfit = settings.DebugBody,
HeadOutfit = settings.DebugHead, HeadOutfit = settings.DebugHead,
PersistID = 1, PersistID = uint.MaxValue,
SkinTone = (byte)settings.DebugSkin, SkinTone = (byte)settings.DebugSkin,
Gender = (short)(settings.DebugGender ? 1 : 0), Gender = (short)(settings.DebugGender ? 1 : 0),
Permissions = FSO.SimAntics.Model.TSOPlatform.VMTSOAvatarPermissions.Admin, Permissions = FSO.SimAntics.Model.TSOPlatform.VMTSOAvatarPermissions.Admin,

View file

@ -8,19 +8,24 @@ using FSO.Common;
using FSO.Common.Rendering.Framework; using FSO.Common.Rendering.Framework;
using FSO.Common.Utils; using FSO.Common.Utils;
using FSO.Content; using FSO.Content;
using FSO.Files.Formats.IFF;
using FSO.Files.Formats.IFF.Chunks; using FSO.Files.Formats.IFF.Chunks;
using FSO.Files.RC;
using FSO.HIT; using FSO.HIT;
using FSO.LotView; using FSO.LotView;
using FSO.SimAntics; using FSO.SimAntics;
using FSO.SimAntics.Engine.TSOTransaction; using FSO.SimAntics.Engine.TSOTransaction;
using FSO.SimAntics.Marshals; using FSO.SimAntics.Marshals;
using FSO.SimAntics.Model;
using FSO.SimAntics.NetPlay; using FSO.SimAntics.NetPlay;
using FSO.SimAntics.NetPlay.Drivers; using FSO.SimAntics.NetPlay.Drivers;
using FSO.SimAntics.NetPlay.Model; using FSO.SimAntics.NetPlay.Model;
using FSO.SimAntics.NetPlay.Model.Commands; using FSO.SimAntics.NetPlay.Model.Commands;
using FSO.SimAntics.Utils; using FSO.SimAntics.Utils;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
using Simitone.Client.UI.Controls;
using Simitone.Client.UI.Panels; using Simitone.Client.UI.Panels;
using Simitone.Client.UI.Panels.WorldUI; using Simitone.Client.UI.Panels.WorldUI;
using System; using System;
@ -37,7 +42,7 @@ namespace Simitone.Client.UI.Screens
public UIContainer WindowContainer; public UIContainer WindowContainer;
public bool Downtown; public bool Downtown;
public UILotControl LotControl { get; set; } public UILotControl LotControl { get; set; }
public UISimitoneFrontend Frontend { get; set; } public UISimitoneFrontend Frontend { get; set; }
private FSO.LotView.World World; private FSO.LotView.World World;
public FSO.SimAntics.VM vm { get; set; } public FSO.SimAntics.VM vm { get; set; }
@ -163,7 +168,7 @@ namespace Simitone.Client.UI.Screens
} }
} }
public TS1GameScreen() : base() public TS1GameScreen(NeighSelectionMode mode) : base()
{ {
Bg = new UISimitoneBg(); Bg = new UISimitoneBg();
Bg.Position = (new Vector2(ScreenWidth, ScreenHeight)) / 2; Bg.Position = (new Vector2(ScreenWidth, ScreenHeight)) / 2;
@ -174,25 +179,74 @@ namespace Simitone.Client.UI.Screens
if (Content.Get().TS1) if (Content.Get().TS1)
{ {
NeighSelection(); NeighSelection(mode);
} }
} }
public int? MoveInFamily;
public void NeighSelection() public void StartMoveIn(int familyID)
{ {
TS1NeighPanel = new UINeighborhoodSelectionPanel(4); MoveInFamily = familyID;
var switcher = new UINeighbourhoodSwitcher(TS1NeighPanel, 4); }
public void NeighSelection(NeighSelectionMode mode)
{
var nbd = (ushort)((mode == NeighSelectionMode.MoveInMagic) ? 7 : 4);
TS1NeighPanel = new UINeighborhoodSelectionPanel(nbd);
var switcher = new UINeighbourhoodSwitcher(TS1NeighPanel, nbd, mode != NeighSelectionMode.Normal);
TS1NeighPanel.OnHouseSelect += (house) => TS1NeighPanel.OnHouseSelect += (house) =>
{ {
ActiveFamily = Content.Get().Neighborhood.GetFamilyForHouse((short)house); if (MoveInFamily != null)
InitializeLot(Path.Combine(FSOEnvironment.UserDir, "UserData/Houses/House" + house.ToString().PadLeft(2, '0') + ".iff"), false);// "UserData/Houses/House21.iff" {
Remove(TS1NeighPanel); //move them in first
Remove(switcher); //confirm it
UIMobileAlert confirmDialog = null;
confirmDialog = new UIMobileAlert(new UIAlertOptions()
{
Title = GameFacade.Strings.GetString("132", "0"),
Message = GameFacade.Strings.GetString("132", "1"),
Buttons = UIAlertButton.YesNo((b) =>
{
confirmDialog.Close();
MoveInAndPlay((short)house, MoveInFamily.Value, switcher);
},
(b) => confirmDialog.Close())
});
UIScreen.GlobalShowDialog(confirmDialog, true);
}
else
{
PlayHouse((short)house, switcher);
}
}; };
Add(TS1NeighPanel); Add(TS1NeighPanel);
Add(switcher); Add(switcher);
} }
public void PlayHouse(short house, UIElement switcher)
{
ActiveFamily = Content.Get().Neighborhood.GetFamilyForHouse((short)house);
InitializeLot(Content.Get().Neighborhood.GetHousePath(house), false);// "UserData/Houses/House21.iff"
Remove(TS1NeighPanel);
if (switcher != null) Remove(switcher);
}
public void MoveInAndPlay(short house, int family, UIElement switcher)
{
var neigh = Content.Get().Neighborhood;
var fami = neigh.GetFamily((ushort)family);
neigh.SetFamilyForHouse(house, fami, true);
PlayHouse(house, switcher);
}
public void EvictLot(FAMI family, short houseID)
{
family.Budget += family.ValueInArch;
family.ValueInArch = 0;
Content.Get().Neighborhood.MoveOut(houseID);
TS1NeighPanel.SelectHouse(houseID);
}
public override void GameResized() public override void GameResized()
{ {
base.GameResized(); base.GameResized();
@ -284,9 +338,9 @@ namespace Simitone.Client.UI.Screens
GameFacade.Game.IsMouseVisible = Visible; GameFacade.Game.IsMouseVisible = Visible;
base.Update(state); base.Update(state);
if (state.NewKeys.Contains(Keys.NumPad1)) ChangeSpeedTo(1); if (state.NewKeys.Contains(Keys.D1)) ChangeSpeedTo(1);
if (state.NewKeys.Contains(Keys.NumPad2)) ChangeSpeedTo(2); if (state.NewKeys.Contains(Keys.D2)) ChangeSpeedTo(2);
if (state.NewKeys.Contains(Keys.NumPad3)) ChangeSpeedTo(3); if (state.NewKeys.Contains(Keys.D3)) ChangeSpeedTo(3);
if (state.NewKeys.Contains(Keys.P)) ChangeSpeedTo(0); if (state.NewKeys.Contains(Keys.P)) ChangeSpeedTo(0);
if (World != null) if (World != null)
@ -306,7 +360,7 @@ namespace Simitone.Client.UI.Screens
else else
{ {
Downtown = true; Downtown = true;
InitializeLot(Path.Combine(Content.Get().TS1BasePath, "UserData/Houses/House" + SwitchLot.ToString().PadLeft(2, '0') + ".iff"), false); InitializeLot(Content.Get().Neighborhood.GetHousePath(SwitchLot), false);
} }
SwitchLot = -1; SwitchLot = -1;
} }
@ -329,7 +383,6 @@ namespace Simitone.Client.UI.Screens
//clear our cache too, if the setting lets us do that //clear our cache too, if the setting lets us do that
TimedReferenceController.Clear(); TimedReferenceController.Clear();
TimedReferenceController.Clear(); TimedReferenceController.Clear();
VM.ClearAssembled();
if (ZoomLevel < 4) ZoomLevel = 5; if (ZoomLevel < 4) ZoomLevel = 5;
vm.Context.Ambience.Kill(); vm.Context.Ambience.Kill();
@ -401,15 +454,15 @@ namespace Simitone.Client.UI.Screens
public void InitializeLot(VMMarshal marshal) public void InitializeLot(VMMarshal marshal)
{ {
InitializeLot(); InitializeLot();
vm.MyUID = 1; vm.MyUID = uint.MaxValue;
vm.Load(marshal); vm.Load(marshal);
vm.ActivateFamily(ActiveFamily); vm.TS1State.ActivateFamily(vm, ActiveFamily);
var settings = GlobalSettings.Default; var settings = GlobalSettings.Default;
var myClient = new VMNetClient var myClient = new VMNetClient
{ {
PersistID = 1, PersistID = uint.MaxValue,
RemoteIP = "local", RemoteIP = "local",
AvatarState = new VMNetAvatarPersistState() AvatarState = new VMNetAvatarPersistState()
{ {
@ -417,7 +470,7 @@ namespace Simitone.Client.UI.Screens
DefaultSuits = new VMAvatarDefaultSuits(settings.DebugGender), DefaultSuits = new VMAvatarDefaultSuits(settings.DebugGender),
BodyOutfit = settings.DebugBody, BodyOutfit = settings.DebugBody,
HeadOutfit = settings.DebugHead, HeadOutfit = settings.DebugHead,
PersistID = 1, PersistID = uint.MaxValue,
SkinTone = (byte)settings.DebugSkin, SkinTone = (byte)settings.DebugSkin,
Gender = (short)(settings.DebugGender ? 1 : 0), Gender = (short)(settings.DebugGender ? 1 : 0),
Permissions = FSO.SimAntics.Model.TSOPlatform.VMTSOAvatarPermissions.Admin, Permissions = FSO.SimAntics.Model.TSOPlatform.VMTSOAvatarPermissions.Admin,
@ -438,7 +491,7 @@ namespace Simitone.Client.UI.Screens
public void InitializeLot(string lotName, bool external) public void InitializeLot(string lotName, bool external)
{ {
if (lotName == "") return; if (lotName == "" || lotName[0] == '!') return;
InitializeLot(); InitializeLot();
if (!external) if (!external)
@ -446,17 +499,15 @@ namespace Simitone.Client.UI.Screens
if (!Downtown && ActiveFamily != null) if (!Downtown && ActiveFamily != null)
{ {
ActiveFamily.SelectWholeFamily(); ActiveFamily.SelectWholeFamily();
vm.ActivateFamily(ActiveFamily); vm.TS1State.ActivateFamily(vm, ActiveFamily);
} }
BlueprintReset(lotName); BlueprintReset(lotName, null);
vm.TSOState.Size = (10) | (3 << 8); vm.MyUID = uint.MaxValue;
vm.Context.UpdateTSOBuildableArea();
vm.MyUID = 1;
var settings = GlobalSettings.Default; var settings = GlobalSettings.Default;
var myClient = new VMNetClient var myClient = new VMNetClient
{ {
PersistID = 1, PersistID = uint.MaxValue,
RemoteIP = "local", RemoteIP = "local",
AvatarState = new VMNetAvatarPersistState() AvatarState = new VMNetAvatarPersistState()
{ {
@ -464,17 +515,36 @@ namespace Simitone.Client.UI.Screens
DefaultSuits = new VMAvatarDefaultSuits(settings.DebugGender), DefaultSuits = new VMAvatarDefaultSuits(settings.DebugGender),
BodyOutfit = settings.DebugBody, BodyOutfit = settings.DebugBody,
HeadOutfit = settings.DebugHead, HeadOutfit = settings.DebugHead,
PersistID = 1, PersistID = uint.MaxValue,
SkinTone = (byte)settings.DebugSkin, SkinTone = (byte)settings.DebugSkin,
Gender = (short)(settings.DebugGender ? 1 : 0), Gender = (short)(settings.DebugGender ? 1 : 0),
Permissions = FSO.SimAntics.Model.TSOPlatform.VMTSOAvatarPermissions.Admin, Permissions = FSO.SimAntics.Model.TSOPlatform.VMTSOAvatarPermissions.Admin,
Budget = 1000000 Budget = 1000000
} }
}; };
if (Downtown)
{
var ngbh = Content.Get().Neighborhood;
var crossData = ngbh.GameState;
var neigh = ngbh.GetNeighborIDForGUID(crossData.DowntownSimGUID);
if (neigh != null) {
var inv = ngbh.GetInventoryByNID(neigh.Value);
if (inv != null) {
var hr = inv.FirstOrDefault(x => x.Type == 2 && x.GUID == 7)?.Count ?? 0;
var min = inv.FirstOrDefault(x => x.Type == 2 && x.GUID == 8)?.Count ?? 0;
Driver.SendCommand(new VMNetSetTimeCmd()
{
Hours = hr,
Minutes = min,
});
}
}
}
var server = (VMServerDriver)Driver; var server = (VMServerDriver)Driver;
server.ConnectClient(myClient); server.ConnectClient(myClient);
LoadSurrounding(short.Parse(lotName.Substring(lotName.Length - 6, 2)));
GameFacade.Cursor.SetCursor(CursorType.Normal); GameFacade.Cursor.SetCursor(CursorType.Normal);
ZoomLevel = 1; ZoomLevel = 1;
@ -484,9 +554,48 @@ namespace Simitone.Client.UI.Screens
this.Add(Frontend); this.Add(Frontend);
} }
public void BlueprintReset(string path) public void LoadSurrounding(short houseID)
{
return;
var surrounding = new NBHm(new OBJ(File.OpenRead(@"C:\Users\Rhys\Desktop\nb2.obj")));
NBHmHouse myH = null;
var myHeight = vm.Context.Blueprint.InterpAltitude(new Vector3(0, 0, 0));
if (!surrounding.Houses.TryGetValue(houseID, out myH)) return;
foreach (var house in surrounding.Houses)
{
if (house.Key == houseID) continue;
var h = house.Value;
//let's make their lot as a surrounding lot
var gd = World.State.Device;
var subworld = World.MakeSubWorld(gd);
subworld.Initialize(gd);
var tempVM = new VM(new VMContext(subworld), new VMServerDriver(new VMTSOGlobalLinkStub()), new VMNullHeadlineProvider());
tempVM.Init();
BlueprintReset(Content.Get().Neighborhood.GetHousePath(house.Key), tempVM);
subworld.State.Level = 5;
var subHeight = tempVM.Context.Blueprint.InterpAltitude(new Vector3(0, 0, 0));
tempVM.Context.Blueprint.BaseAlt = (int)Math.Round(((subHeight - myHeight) + myH.Position.Y - h.Position.Y) / tempVM.Context.Blueprint.TerrainFactor);
subworld.GlobalPosition = new Vector2((myH.Position.X - h.Position.X), (myH.Position.Z - h.Position.Z));
foreach (var obj in tempVM.Entities)
{
obj.Position = obj.Position;
}
vm.Context.Blueprint.SubWorlds.Add(subworld);
}
vm.Context.World.InitSubWorlds();
}
public void BlueprintReset(string path, VM vm)
{ {
string filename = Path.GetFileName(path); string filename = Path.GetFileName(path);
bool isSurrounding = true;
if (vm == null)
{
isSurrounding = false;
vm = this.vm;
}
try try
{ {
using (var file = new BinaryReader(File.OpenRead(Path.Combine(FSOEnvironment.UserDir, "LocalHouse/") + filename.Substring(0, filename.Length - 4) + ".fsov"))) using (var file = new BinaryReader(File.OpenRead(Path.Combine(FSOEnvironment.UserDir, "LocalHouse/") + filename.Substring(0, filename.Length - 4) + ".fsov")))
@ -527,9 +636,11 @@ namespace Simitone.Client.UI.Screens
}); });
} }
vm.SpeedMultiplier = -1;
vm.Tick(); vm.Tick();
vm.SpeedMultiplier = 1;
if (ActiveFamily == null) if (ActiveFamily == null && !isSurrounding)
{ {
vm.SetGlobalValue(32, 1); vm.SetGlobalValue(32, 1);
vm.SpeedMultiplier = -1; vm.SpeedMultiplier = -1;
@ -539,7 +650,12 @@ namespace Simitone.Client.UI.Screens
private void Vm_OnGenericVMEvent(VMEventType type, object data) private void Vm_OnGenericVMEvent(VMEventType type, object data)
{ {
//hmm... switch (type)
{
case VMEventType.TS1BuildBuyChange:
Frontend.ModeSwitcher.UpdateBuildBuy();
break;
}
} }
private void VMLotSwitch(uint lotId) private void VMLotSwitch(uint lotId)
@ -626,13 +742,74 @@ namespace Simitone.Client.UI.Screens
public void Save() public void Save()
{ {
//save the house first
var iff = new IffFile();
vm.TS1State.UpdateSIMI(vm);
var marshal = vm.Save();
var fsov = new FSOV();
fsov.ChunkLabel = "Simitone Lot Data";
fsov.ChunkID = 1;
fsov.ChunkProcessed = true;
fsov.ChunkType = "FSOV";
fsov.AddedByPatch = true;
using (var stream = new MemoryStream())
{
marshal.SerializeInto(new BinaryWriter(stream));
fsov.Data = stream.ToArray();
}
iff.AddChunk(fsov);
var simi = vm.TS1State.SimulationInfo;
simi.ChunkProcessed = true;
simi.AddedByPatch = true;
iff.AddChunk(simi);
Texture2D roofless = null;
var thumb = World.GetLotThumb(GameFacade.GraphicsDevice, (tex) => roofless = FSO.Common.Utils.TextureUtils.Decimate(tex, GameFacade.GraphicsDevice, 2, false));
thumb = FSO.Common.Utils.TextureUtils.Decimate(thumb, GameFacade.GraphicsDevice, 2, false);
var tPNG = GeneratePNG(thumb);
tPNG.ChunkID = 513;
iff.AddChunk(tPNG);
var rPNG = GeneratePNG(roofless);
rPNG.ChunkID = 512;
iff.AddChunk(rPNG);
Content.Get().Neighborhood.SaveHouse(vm.GetGlobalValue(10), iff);
Content.Get().Neighborhood.SaveNeighbourhood(true);
}
public PNG GeneratePNG(Texture2D data)
{
var png = new PNG();
using (var stream = new MemoryStream())
{
data.SaveAsPng(stream, data.Width, data.Height);
png.data = stream.ToArray();
}
png.ChunkLabel = "Lot Thumbnail";
png.ChunkProcessed = true;
png.ChunkType = "PNG_";
png.AddedByPatch = true;
return png;
} }
public void ExitLot() public void ExitLot()
{ {
CleanupLastWorld(); CleanupLastWorld();
NeighSelection(); NeighSelection(NeighSelectionMode.Normal);
} }
} }
public enum NeighSelectionMode
{
Normal,
MoveIn,
MoveInMagic
}
} }

View file

@ -0,0 +1,218 @@
using FSO.Client;
using FSO.Common;
using FSO.Content;
using FSO.Files.Formats.IFF.Chunks;
using FSO.LotView;
using FSO.LotView.Facade;
using FSO.LotView.RC;
using FSO.SimAntics;
using FSO.SimAntics.Engine.TSOTransaction;
using FSO.SimAntics.NetPlay.Drivers;
using FSO.SimAntics.Utils;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Simitone.Client.UI.Panels.WorldUI;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Simitone.Client.Utils
{
/// <summary>
/// Exports the entire neighbourhood in *.obj format
/// </summary>
public static class SimitoneNeighOBJExporter
{
public static void SaveOBJ(string destPath, STR locations)
{
var exportedFlr = new HashSet<ushort>();
var gd = GameFacade.GraphicsDevice;
var mtlBuilder = new StringBuilder();
Directory.CreateDirectory(destPath);
//var mtlMem = new MemoryStream();
//var mtlIO = new StreamWriter(mtlMem);
var mtlIO = new StreamWriter(new FileStream(Path.Combine(destPath, "neighbourhood.mtl"), FileMode.Create, FileAccess.Write, FileShare.None));
var path = Path.Combine(destPath, "neighbourhood.obj");
var filename = Path.GetFileNameWithoutExtension(path);
using (var io = new StreamWriter(new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)))
{
io.WriteLine("# Generated by the Simitone Neighbourhood Exporter.");
io.WriteLine("# The purpose is to allow users to mesh neighbourhood surroundings using");
io.WriteLine("# the projected physical positions and terrain profiles of lots as a starting point.");
io.WriteLine("mtllib neighbourhood.mtl");
io.WriteLine("s 1");
int indCount = 1;
for (int i = 0; i < locations.Length; i++)
{
var loc = locations.GetString(i).Split(',');
var num = int.Parse(loc[0].TrimStart());
var pos2d = new Vector2(int.Parse(loc[1].TrimStart()), int.Parse(loc[2].TrimStart()));
var house = Content.Get().Neighborhood.GetHouse(num);
World world;
if (FSOEnvironment.Enable3D)
{
world = new FSO.LotView.RC.WorldRC(GameFacade.GraphicsDevice);
}
else
{
world = new FSO.LotView.World(GameFacade.GraphicsDevice);
}
world.Opacity = 1;
GameFacade.Scenes.Add(world);
var globalLink = new VMTS1GlobalLinkStub();
var driver = new VMServerDriver(globalLink);
var vm = new VM(new VMContext(world), driver, new UIHeadlineRendererProvider());
vm.ListenBHAVChanges();
vm.Init();
vm.SetGlobalValue(11, (short)num);
var activator = new VMTS1Activator(vm, vm.Context.World, (short)num);
var blueprint = activator.LoadFromIff(house);
var floorVerts = blueprint.Terrain.GetVertices(gd);
blueprint.FloorGeom.FullReset(gd, false);
var groundfloor = blueprint.FloorGeom.Floors[0];
//we need to calculate the
var minHeight = int.MaxValue;
var heights = vm.Context.Architecture.Terrain.Heights;
for (int j=0; j<heights.Length; j++)
{
if ((j % blueprint.Width) == 0 || (j % blueprint.Width) == blueprint.Width - 1 || j < blueprint.Width || j >= (blueprint.Height - 1) * blueprint.Width)
continue;
var h = heights[j];
if (h != 0 && h < minHeight) minHeight = h;
}
if (minHeight == int.MaxValue) minHeight = 0;
var scale = (locations.Length > 30 ? 1f : 2f) * 1.4142135623730950488016887242097f;
var baseV = new Vector3(pos2d.X + pos2d.Y * 2, 0, pos2d.Y * 2 - pos2d.X) / scale;
baseV.Y -= (minHeight * 3 / 160f) * 3;
var ctr = blueprint.GetFineBounds().Location.ToVector2() + blueprint.GetFineBounds().Size.ToVector2() / 2;
var voff = baseV + new Vector3(ctr.X, 0, ctr.Y) * 3f / -1;
voff.X = (int)(voff.X / 3) * 3;
voff.Z = (int)(voff.Z / 3) * 3;
SetOutsideTime(GameFacade.GraphicsDevice, vm, world, 0.5f, false);
world.State.PrepareLighting();
var facade = new LotFacadeGenerator();
facade.FLOOR_TILES = blueprint.Width;
facade.GROUND_SUBDIV = blueprint.Width;
facade.FLOOR_RES_PER_TILE = 4;
facade.LotName = "p"+num.ToString();
facade.Generate(GameFacade.GraphicsDevice, (WorldRC)world, blueprint);
facade.AppendOBJ(io, filename, indCount, voff / 3);
facade.AppendMTL(mtlIO, Path.GetDirectoryName(path));
indCount = facade.LastIndex;
/*
foreach (var group in groundfloor.GroupForTileType)
{
if (!exportedFlr.Contains(group.Key) && group.Key != 0 && group.Key < 65000)
{
//get and export this floor's texture. add it as a material as well.
var floor = Content.Get().WorldFloors.Get(group.Key).Near.Frames[0].GetTexture(gd);
using (var flrStream = new FileStream(Path.Combine(destPath, "flr_" + group.Key + ".png"), FileMode.Create, FileAccess.Write, FileShare.None))
floor.SaveAsPng(flrStream, floor.Width, floor.Height);
//add as material
GenerateMTL("flr_" + group.Key, mtlBuilder);
}
//write out verts and indices.
var indices = group.Value.BuildIndexData();
var done = new Dictionary<int, int>(); //index remap
if (group.Key == 0)
{
//grass... export as grass colour
io.WriteLine("usemtl " + "grass");
io.WriteLine("o " + "lot_" + num + "_grass");
}
else
{
//export with floor textured material
io.WriteLine("usemtl " + "flr_" + group.Key);
io.WriteLine("o " + "lot_" + num + "_" + group.Key);
}
var indexStr = new StringBuilder();
indexStr.Append("f ");
for (int j = 0; j < indices.Length; j++)
{
var index = indices[j];
int remapped = index;
if (!done.TryGetValue(index, out remapped))
{
remapped = indCount;
done.Add(index, indCount++);
//append a vertex
var vert = floorVerts[index];
vert.Position += voff;
io.Write("v " + vert.Position.X.ToString(CultureInfo.InvariantCulture) + " " + vert.Position.Y.ToString(CultureInfo.InvariantCulture) + " " + vert.Position.Z.ToString(CultureInfo.InvariantCulture));
io.WriteLine((group.Key == 0) ? " " + vert.Color.X.ToString(CultureInfo.InvariantCulture) + " " + vert.Color.Y.ToString(CultureInfo.InvariantCulture) + " " + vert.Color.Z.ToString(CultureInfo.InvariantCulture) : "");
io.WriteLine("vt " + vert.GrassInfo.Y.ToString(CultureInfo.InvariantCulture) + " " + (1 - vert.GrassInfo.Z).ToString(CultureInfo.InvariantCulture));
}
indexStr.Append(remapped + "/" + remapped);
if (j % 3 == 2)
{
indexStr.AppendLine();
if (j != indices.Length - 1) indexStr.Append("f ");
}
else indexStr.Append(" ");
}
io.WriteLine(indexStr);
}
*/
GameFacade.Scenes.Remove(world);
world.Dispose();
}
}
mtlIO.Close();
}
private static void SetOutsideTime(GraphicsDevice gd, VM vm, World world, float time, bool lightsOn)
{
vm.Context.Architecture.SetTimeOfDay(time);
world.Force2DPredraw(gd);
vm.Context.Architecture.SetTimeOfDay();
}
private static void GenerateMTL(string oname, StringBuilder str)
{
str.AppendLine("newmtl " + oname);
str.AppendLine("Ka 1.000 1.000 1.000");
str.AppendLine("Kd 1.000 1.000 1.000");
str.AppendLine("Ks 0.000 0.000 0.000");
str.AppendLine("Ns 10.0000");
str.AppendLine("illum 2");
str.AppendLine("map_Kd " + oname + ".png");
str.AppendLine("map_d " + oname + ".png");
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -24,7 +24,7 @@ namespace Simitone.Windows
{ {
var gameLocator = new WindowsLocator(); var gameLocator = new WindowsLocator();
var useDX = false; var useDX = true;
var path = gameLocator.FindTheSimsOnline(); var path = gameLocator.FindTheSimsOnline();
if (useDX) GlobalSettings.Default.AntiAlias = false; if (useDX) GlobalSettings.Default.AntiAlias = false;

View file

@ -51,6 +51,9 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Icon.bmp">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
<Content Include="Icon.ico" /> <Content Include="Icon.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -58,9 +61,9 @@
<Project>{6d6009f4-0afb-4806-89d7-7945f20270f5}</Project> <Project>{6d6009f4-0afb-4806-89d7-7945f20270f5}</Project>
<Name>MonoGame.Framework.Net.WindowsGL</Name> <Name>MonoGame.Framework.Net.WindowsGL</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\..\FreeSO\Other\libs\FSOMonoGame\MonoGame.Framework\MonoGame.Framework.WindowsGL.csproj"> <ProjectReference Include="..\..\..\FreeSO\Other\libs\FSOMonoGame\MonoGame.Framework\MonoGame.Framework.Windows.csproj">
<Project>{6d75e618-19ca-4c51-9546-f10965fbc0b8}</Project> <Project>{7de47032-a904-4c29-bd22-2d235e8d91ba}</Project>
<Name>MonoGame.Framework.WindowsGL</Name> <Name>MonoGame.Framework.Windows</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\..\FreeSO\Other\libs\mp3sharp\mp3sharp\Mp3Sharp.csproj"> <ProjectReference Include="..\..\..\FreeSO\Other\libs\mp3sharp\mp3sharp\Mp3Sharp.csproj">
<Project>{834cab58-648d-47cc-ac6f-d01c08c809a4}</Project> <Project>{834cab58-648d-47cc-ac6f-d01c08c809a4}</Project>
@ -99,6 +102,9 @@
<Name>Simitone.Client</Name> <Name>Simitone.Client</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" /> <Import Project="$(MSBuildExtensionsPath)\MonoGame\v3.0\MonoGame.Content.Builder.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MonoGame.Framework.WindowsDX" version="3.6.0.1625" targetFramework="net45" />
</packages>

View file

@ -445,8 +445,8 @@ Global
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.AppStore|x86.ActiveCfg = Release|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.AppStore|x86.ActiveCfg = Release|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.AppStore|x86.Build.0 = Release|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.AppStore|x86.Build.0 = Release|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|Any CPU.Build.0 = Debug|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|Any CPU.Build.0 = Release|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|iPhone.ActiveCfg = Debug|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|iPhone.Build.0 = Debug|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|iPhone.Build.0 = Debug|Any CPU
{7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {7DE47032-A904-4C29-BD22-2D235E8D91BA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
@ -477,8 +477,8 @@ Global
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.AppStore|x86.ActiveCfg = Release|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.AppStore|x86.ActiveCfg = Release|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.AppStore|x86.Build.0 = Release|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.AppStore|x86.Build.0 = Release|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|Any CPU.Build.0 = Debug|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|Any CPU.Build.0 = Release|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|iPhone.ActiveCfg = Debug|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|iPhone.Build.0 = Debug|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|iPhone.Build.0 = Debug|Any CPU
{6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {6D6009F4-0AFB-4806-89D7-7945F20270F5}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
@ -629,8 +629,8 @@ Global
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.AppStore|x86.ActiveCfg = Release|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.AppStore|x86.ActiveCfg = Release|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.AppStore|x86.Build.0 = Release|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.AppStore|x86.Build.0 = Release|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|Any CPU.Build.0 = Debug|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|Any CPU.Build.0 = Release|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|iPhone.ActiveCfg = Debug|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|iPhone.Build.0 = Debug|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|iPhone.Build.0 = Debug|Any CPU
{6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {6D75E618-19CA-4C51-9546-F10965FBC0B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
@ -661,8 +661,8 @@ Global
{AE483C29-042E-4226-BA52-D247CE7676DA}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.AppStore|x86.ActiveCfg = Release|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.AppStore|x86.ActiveCfg = Release|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.AppStore|x86.Build.0 = Release|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.AppStore|x86.Build.0 = Release|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.Build.0 = Debug|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|Any CPU.Build.0 = Release|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|iPhone.ActiveCfg = Debug|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|iPhone.Build.0 = Debug|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|iPhone.Build.0 = Debug|Any CPU
{AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU {AE483C29-042E-4226-BA52-D247CE7676DA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU

2
FreeSO

@ -1 +1 @@
Subproject commit 6385ba5cf5025b27b952b5e8a585bacf0af7af00 Subproject commit b23f16c4de1792363bc25d94a4d34dc787d39899