Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
Built with [Unity 2020.2](https://github.com/freezy/VisualPinball.Engine/pull/255).

### Added
- Plugin: Mission Pinball Framework ([Documentation](https://docs.visualpinball.org/plugins/mpf/index.html))
- Gamelogic Engine: Support for hardware rules ([#293](https://github.com/freezy/VisualPinball.Engine/pull/293)).
- Support for Extended ASCII strings ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)).
- Support for Elasticity Falloff in walls (added in VP 10.7) ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)).
- Support for table notes (added in VP 10.7) ([#291](https://github.com/freezy/VisualPinball.Engine/pull/291)).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

*A library that implements world's favorite pinball simulator.*

[![build](https://github.com/freezy/VisualPinball.Engine/workflows/Build/badge.svg)](https://github.com/freezy/VisualPinball.Engine/actions?query=workflow%3ABuild) [![codecov](https://codecov.io/gh/freezy/VisualPinball.Engine/branch/master/graph/badge.svg?token=gyLOj3al3T)](https://codecov.io/gh/freezy/VisualPinball.Engine)
[![build](https://github.com/freezy/VisualPinball.Engine/workflows/Build/badge.svg)](https://github.com/freezy/VisualPinball.Engine/actions?query=workflow%3ABuild) [![codecov](https://codecov.io/gh/freezy/VisualPinball.Engine/branch/master/graph/badge.svg?token=gyLOj3al3T)](https://codecov.io/gh/freezy/VisualPinball.Engine) [![UPM Package](https://img.shields.io/npm/v/org.visualpinball.engine.unity?label=org.visualpinball.engine.unity&registry_uri=https://registry.visualpinball.org&color=%2333cf57&logo=unity&style=flat)](https://registry.visualpinball.org/-/web/detail/org.visualpinball.engine.unity)

## Why?

Expand Down
6 changes: 6 additions & 0 deletions VisualPinball.Engine/Game/Engines/GamelogicEngineCoil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// ReSharper disable InconsistentNaming

using System;

namespace VisualPinball.Engine.Game.Engines
{
[Serializable]
public class GamelogicEngineCoil
{
public string Id;
Expand All @@ -26,6 +31,7 @@ public class GamelogicEngineCoil
public string DeviceHint;
public string DeviceItemHint;
public bool IsLamp;
public bool IsUnused;

public GamelogicEngineCoil(string id)
{
Expand Down
5 changes: 5 additions & 0 deletions VisualPinball.Engine/Game/Engines/GamelogicEngineLamp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// ReSharper disable InconsistentNaming

using System;

namespace VisualPinball.Engine.Game.Engines
{
[Serializable]
public class GamelogicEngineLamp
{
public string Id;
Expand Down
8 changes: 6 additions & 2 deletions VisualPinball.Engine/Game/Engines/GamelogicEngineSwitch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// ReSharper disable BuiltInTypeReferenceStyle
// ReSharper disable InconsistentNaming

using System;

namespace VisualPinball.Engine.Game.Engines
{
Expand All @@ -29,18 +32,19 @@ namespace VisualPinball.Engine.Game.Engines
/// This class isn't used during gameplay, but serves to declare the properties
/// that will then used in the mapping.
/// </remarks>
[Serializable]
public class GamelogicEngineSwitch
{
/// <summary>
/// A unique identifier. This is what VPE uses to identify a switch.
/// </summary>
public readonly string Id;
public string Id;

/// <summary>
/// A numerical identifier that can be used in gamelogic engines that
/// are tied to numerical identifiers.
/// </summary>
public readonly int InternalId;
public int InternalId;

/// <summary>
/// If true, inverts the signal, i.e. disabled switches return "closed" (true),
Expand Down
4 changes: 4 additions & 0 deletions VisualPinball.Engine/VPT/Mappings/Mappings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ public void PopulateCoils(GamelogicEngineCoil[] engineCoils, IEnumerable<ICoilab
var coilMapping = Data.Coils.FirstOrDefault(mappingsCoilData => mappingsCoilData.Id == engineCoil.Id);
if (coilMapping == null) {

if (engineCoil.IsUnused) {
continue;
}

// we'll handle those in a second loop when all the main coils are added
if (!string.IsNullOrEmpty(engineCoil.MainCoilIdOfHoldCoil)) {
holdCoils.Add(engineCoil);
Expand Down
18 changes: 18 additions & 0 deletions VisualPinball.Engine/VPT/Mappings/MappingsWireData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@ public class MappingsWireData : BiffData
[BiffInt("PLSE", Pos = 13)]
public int PulseDelay = 250;

public string DestinationId => Destination == WireDestination.Device ? DestinationDeviceItem : DestinationPlayfieldItem;

[ExcludeFromCodeCoverage]
public MappingsWireData(string description, MappingsSwitchData switchMapping, MappingsCoilData coilMapping) : this()
{
Description = description;
Source = switchMapping.Source;
SourceDevice = switchMapping.Device;
SourceDeviceItem = switchMapping.DeviceItem;
SourceInputAction = switchMapping.InputAction;
SourceInputActionMap = switchMapping.InputActionMap;
SourcePlayfieldItem = switchMapping.PlayfieldItem;
Destination = coilMapping.Destination == CoilDestination.Device ? WireDestination.Device : WireDestination.Playfield;
DestinationDevice = coilMapping.Device;
DestinationDeviceItem = coilMapping.DeviceItem;
DestinationPlayfieldItem = coilMapping.PlayfieldItem;
}

[ExcludeFromCodeCoverage]
public string Src { get {
switch (Source) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ When playing a pinball game, some part of the table is driving the gameplay, i.e

The gamelogic engine is purely gameplay driven. It gets input from switches, computes what will happen next, and updates the hardware components of the table. It does *not* handle game mechanics, which are about simulating the hardware *behavior* of the table - it just toggles it.

Classic examples of gamelogic engines are [MPF](https://missionpinball.org/) and [PinMAME](https://sourceforge.net/projects/pinmame/).
Classic examples of gamelogic engines are [MPF](../../plugins/mpf/index.html) and [PinMAME](https://github.com/vpinball/pinmame).

> [!note]
> Let's take a spinning wheel on the playfield as an example. The game*logic* engine's job is to know when to turn it on and off. The game *mechanics* component of the spinning wheel is about rotating the actual playfield element with the right speed, acceleration, and handle ball collisions with a given friction.
Expand Down

This file was deleted.

2 changes: 0 additions & 2 deletions VisualPinball.Unity/Documentation~/creators-guide/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
href: setup/installing-vpe.md
- name: Running VPE
href: setup/running-vpe.md
- name: Updating VPE
href: setup/updating-vpe.md

- name: Editor
items:
Expand Down
6 changes: 4 additions & 2 deletions VisualPinball.Unity/Documentation~/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
},
{
"files": [
"creators-guide/**.md",
"creators-guide/**/toc.yml",
"creators-guide/**.md",
"plugins/**/toc.yml",
"plugins/**.md",
"toc.yml",
"*.md"
]
Expand Down Expand Up @@ -80,7 +82,7 @@
"postProcessors": [ "ExtractSearchIndex" ],
"globalMetadata": {
"_appTitle": "VPE Documentation",
"_appFooter": "<span>Copyright © 2020 VPE Team</span>",
"_appFooter": "<span>Copyright © 2021 VPE Team</span>",
"_gitContribute": {
"branch": "master"
}
Expand Down
13 changes: 13 additions & 0 deletions VisualPinball.Unity/Documentation~/plugins/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: Plugins
description: Visual Pinball for Unity - Plugins
---

# Plugins

VPE has a plug-in system that allows other software to integrate with it. Plugins are typically required on a per-table basis. VPE ships with a number of default plugins which are documented here.


## [Mission Pinball Framework](mpf/index.html)

The [Mission Pinball Framework](https://missionpinball.org/) is software written in Python that is used to drive real pinball machines. It integrates with VPE as a gamelogic engine.
17 changes: 17 additions & 0 deletions VisualPinball.Unity/Documentation~/plugins/mpf/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: Mission Pinball Framework
description: Visual Pinball Engine integration with the Mission Pinball Framework.
---

<img alt="MPF Logo" width="256" src="https://missionpinball.org/images/mpf-logo-full.png" />

# Mission Pinball Framework

VPE connects to MPF using [gRPC](https://grpc.io/), which is a high-performance, low-latency RPC framework. It works by VPE launching MPF as a Python process. MPF will then spawn a gRPC server, to which VPE connects to.

There are two situations when this is done:

- In edit mode to retrieve available switches, coils and lamps
- During runtime to drive the game

VPE supports MPF's *hardware rules*, which are dynamic connections between coils and switches handled by the controller boards in order to reduce latency. The media controller is not yet supported.
36 changes: 36 additions & 0 deletions VisualPinball.Unity/Documentation~/plugins/mpf/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
title: MPF Setup
description: How to set up the Mission Pinball Framework with VPE.
---

# Setup

## Prerequisites

Future plans include shipping MPF entirely with Unity, but currently, you need to have MPF installed on your machine. You can install MPF by:

1. [Installing Python 3.7](https://www.python.org/downloads/)
2. `pip install --pre mpf mpf-mc`

You can *upgrade* MPF if you already have installed it by running:

```bash
pip install mpf mpf-mc --pre --upgrade
```

Note: On MacOS, you may have to substitue `pip` with `pip3`.

You will need at least MPF v0.55.0-dev.12.

## Unity Setup

Mission Pinball Framework integration comes as an UPM package. In Unity, add it by choosing *Window -> Package Manager -> Add package from git URL*:

<p><img alt="Package Manager" width="294" src="../../creators-guide/setup/unity-package-manager.png"/></p>

Then, input `org.visualpinball.engine.missionpinball` and click *Add* or press `Enter`. This will download and add MPF to the project.

> [!NOTE]
> You will need to have our scoped registry added in order for Unity to find the MPF package. How to do this is documented in the [general setup section](/creators-guide/setup/installing-vpe.html#vpe-package).

So let's [test it](usage.md).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions VisualPinball.Unity/Documentation~/plugins/mpf/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: MPF Usage
description: How to use the Mission Pinball Framework with VPE.
---

# Usage

MPF support is implemented as a [Gamelogic Engine](../../creators-guide/manual/gamelogic-engine.md). It's a [Unity Component](https://docs.unity3d.com/Manual/Components.html), so all you have to do is add it to the root node of your table.

You can do this by selecting the table in the hierarchy, then click *Add Component* in the inspector and select *Visual Pinball -> Game Logic Engine -> Mission Pinball Framework*.

<p><img alt="Package Manager" width="354" src="unity-add-component.png"/></p>


## Retrieve Machine Description

Since the gamelogic engine is the part of VPE that provides switch, coil, and lamp definitions so VPE can link them to the table during gameplay, you'll need to retrieve them from MPF.

You can do this by clicking *Get Machine Description* in the MPF component's inspector. This will save it to the component. You will only need to do this once unless you update the MPF machine config.

> [!NOTE]
> While VPE could read the MPF machine config itself, we let MPF handle it. That means we run MPF with the given machine config and then query its hardware.
>
> While this is a bit slower, it has the advantage of coherent behavior between edit time and runtime, and doesn't add an additional maintenance burden.

## Wire It Up

Now that VPE knows which switches, coils, and lamps your machine expects, you'll need to connect them using the [switch](../../editor/switch-manager.md), [coil](../../editor/coil-manager.md), and [lamp manager](../../editor/lamp-manager.md).

You can watch the entire process in a quick video here:

> [!Video https://www.youtube.com/embed/cdzvMUpdDgs]
10 changes: 10 additions & 0 deletions VisualPinball.Unity/Documentation~/plugins/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- name: Overview
href: index.md
- name: Mission Pinball Framework
items:
- name: Overview
href: mpf/index.md
- name: Setup
href: mpf/setup.md
- name: Usage
href: mpf/usage.md
2 changes: 2 additions & 0 deletions VisualPinball.Unity/Documentation~/toc.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
- name: Creator's Guide
href: creators-guide/
- name: Plugins
href: plugins/
- name: API Documentation
href: api/
homepage: api/index.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected float RowHeight {

public void Reload()
{
if (_tableAuthoring != null) {
if (_tableAuthoring) {
_data = CollectData();
_listView.SetData(_data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public TableAuthoring SelectedTable {
set => SetSelectedTable(value);
}

public void TableUpdated()
{
OnTableSelected?.Invoke(this, EventArgs.Empty);
}

/// <summary>
/// Returns true if there is an active table component.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions VisualPinball.Unity/VisualPinball.Unity/Game/DeviceSwitch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public DeviceSwitch(string name, bool isPulseSwitch, SwitchDefault switchDefault

IApiSwitchStatus IApiSwitch.AddSwitchDest(SwitchConfig switchConfig) =>
_switchHandler.AddSwitchDest(switchConfig.WithPulse(_isPulseSwitch).WithDefault(_switchDefault));
public void AddWireDest(WireDestConfig wireConfig) =>
_switchHandler.AddWireDest(wireConfig);
public void AddWireDest(WireDestConfig wireConfig) => _switchHandler.AddWireDest(wireConfig);
void IApiSwitch.RemoveWireDest(string destId) => _switchHandler.RemoveWireDest(destId);
public void DestroyBall(Entity ballEntity) { } // device switches can't destroy balls

/// <summary>
Expand Down
Loading