diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..73d1437 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,59 @@ +name: Build Simitone + +on: + workflow_dispatch: + inputs: + configuration: + description: 'Build configuration' + required: false + default: 'Release' + type: choice + options: + - Release + - Debug + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Setup .NET 9 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '9.0.x' + + - name: Run Protobuild + shell: pwsh + run: | + cd FreeSO/Other/libs/FSOMonoGame/ + ./protobuild.exe --generate + continue-on-error: true + + - name: Restore Simitone dependencies + run: dotnet restore Client/Simitone/Simitone.sln + + - name: Restore FreeSO dependencies + run: dotnet restore FreeSO/TSOClient/FreeSO.sln + continue-on-error: true + + - name: Restore Roslyn dependencies + shell: pwsh + run: | + cd FreeSO/TSOClient/FSO.SimAntics.JIT.Roslyn/ + dotnet restore + continue-on-error: true + + - name: Build + run: dotnet build Client/Simitone/Simitone.sln -c ${{ inputs.configuration || 'Release' }} --no-restore + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: SimitoneWindows-${{ inputs.configuration || 'Release' }} + path: Client/Simitone/Simitone.Windows/bin/${{ inputs.configuration || 'Release' }}/net9.0-windows/ + if-no-files-found: error diff --git a/Client/Simitone/Simitone.Client/UI/Panels/UILotControl.cs b/Client/Simitone/Simitone.Client/UI/Panels/UILotControl.cs index 5e73ba1..c5d9580 100644 --- a/Client/Simitone/Simitone.Client/UI/Panels/UILotControl.cs +++ b/Client/Simitone/Simitone.Client/UI/Panels/UILotControl.cs @@ -88,6 +88,10 @@ public uint SelectedSimID private int RMBScrollX; private int RMBScrollY; + private bool MMBScroll; + private int MMBScrollX; + private int MMBScrollY; + //1 = near, 0.5 = med, 0.25 = far //"target" because we rescale the game target to fit this zoom level. public float TargetZoom = 1; @@ -865,10 +869,62 @@ public override void Update(UpdateState state) if (state.MouseState.RightButton != ButtonState.Pressed) { - if (RMBScroll) GameFacade.Cursor.SetCursor(CursorType.Normal); + if (RMBScroll) + { + GameFacade.Cursor.SetCursor(CursorType.Normal); + // Check if it was a click (not a drag) on a family member Sim + var deltaX = Math.Abs(state.MouseState.X - RMBScrollX); + var deltaY = Math.Abs(state.MouseState.Y - RMBScrollY); + if (deltaX < 5 && deltaY < 5 && LiveMode && ActiveEntity != null) + { + // It was a click - check if clicking on a household Sim + var clickedObjId = World.GetObjectIDAtScreenPos(RMBScrollX, RMBScrollY, GameFacade.GraphicsDevice); + if (clickedObjId > 0) + { + var clickedObj = vm.GetObjectById(clickedObjId); + if (clickedObj is VMAvatar && vm.TS1State.CurrentFamily?.RuntimeSubset.Contains(clickedObj.Object.OBJ.GUID) == true) + { + // Switch to this family member + vm.SendCommand(new VMNetChangeControlCmd() { TargetID = clickedObj.ObjectID }); + // Update local state immediately so interactions work right away + ActiveEntity = clickedObj; + Queue.QueueOwner = ActiveEntity; + HITVM.Get().PlaySoundEvent(UISounds.Click); + } + } + } + } RMBScroll = false; } + // Middle mouse button handling for camera rotation + if (state.MouseState.MiddleButton == ButtonState.Pressed) + { + if (!MMBScroll) + { + MMBScroll = true; + MMBScrollX = state.MouseState.X; + MMBScrollY = state.MouseState.Y; + } + } + else + { + if (MMBScroll) + { + // Check if it was a click (not a drag) + var deltaX = Math.Abs(state.MouseState.X - MMBScrollX); + var deltaY = Math.Abs(state.MouseState.Y - MMBScrollY); + if (deltaX < 5 && deltaY < 5) + { + // It was a click - rotate camera 90 degrees clockwise + World.State.Rotation = (WorldRotation)(((int)World.State.Rotation + 1) % 4); + HITVM.Get().PlaySoundEvent(UISounds.Click); + } + } + MMBScroll = false; + } + + if (!LiveMode && PieMenu != null) { PieMenu.RemoveSimScene();