[Feat] Interactive Board (#258)

* interactive board

* change2

* fixes
This commit is contained in:
CaypenNow
2024-04-02 19:17:43 +05:00
committed by GitHub
parent 600d236ac2
commit b635d4efaf
21 changed files with 752 additions and 1 deletions

View File

@@ -0,0 +1,9 @@
using Content.Shared._White.InteractiveBoard;
using Robust.Shared.GameStates;
namespace Content.Client._White.InteractiveBoard;
[NetworkedComponent, RegisterComponent]
public sealed partial class InteractiveBoardComponent : SharedInteractiveBoardComponent
{
}

View File

@@ -0,0 +1,24 @@
using Content.Client._White.InteractiveBoard.UI;
using Robust.Client.GameObjects;
using static Content.Shared._White.InteractiveBoard.SharedInteractiveBoardComponent;
namespace Content.Client._White.InteractiveBoard;
public sealed class InteractiveBoardSystem : VisualizerSystem<InteractiveBoardVisualsComponent>
{
protected override void OnAppearanceChange(EntityUid uid, InteractiveBoardVisualsComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
if (AppearanceSystem.TryGetData<InteractiveBoardStatus>(uid, InteractiveBoardVisuals.Status , out var writingStatus, args.Component))
args.Sprite.LayerSetVisible(InteractiveBoardVisualLayers.Writing, writingStatus == InteractiveBoardStatus.Written);
}
}
public enum InteractiveBoardVisualLayers
{
Writing
}

View File

@@ -0,0 +1,66 @@
using JetBrains.Annotations;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
using Robust.Shared.Utility;
using static Content.Shared._White.InteractiveBoard.SharedInteractiveBoardComponent;
namespace Content.Client._White.InteractiveBoard.UI;
[UsedImplicitly]
public sealed class InteractiveBoardBoundUserInterface : BoundUserInterface
{
[ViewVariables]
private InteractiveBoardWindow? _window;
public InteractiveBoardBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
{
}
protected override void Open()
{
base.Open();
_window = new InteractiveBoardWindow();
_window.OnClose += Close;
_window.Input.OnKeyBindDown += args =>
{
if (args.Function == EngineKeyFunctions.TextSubmit)
{
var text = Rope.Collapse(_window.Input.TextRope);
Input_OnTextEntered(text);
args.Handle();
}
};
if (EntMan.TryGetComponent<InteractiveBoardVisualsComponent>(Owner, out var visuals))
{
_window.InitVisuals(Owner, visuals);
}
_window.OpenCentered();
}
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
_window?.Populate((InteractiveBoardBoundUserInterfaceState) state);
}
private void Input_OnTextEntered(string text)
{
SendMessage(new InteractiveBoardInputTextMessage(text));
if (_window != null)
{
_window.Input.TextRope = Rope.Leaf.Empty;
_window.Input.CursorPosition = new TextEdit.CursorPos(0, TextEdit.LineBreakBias.Top);
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (!disposing) return;
_window?.Dispose();
}
}

View File

@@ -0,0 +1,35 @@
using System.Numerics;
namespace Content.Client._White.InteractiveBoard.UI;
[RegisterComponent]
public sealed partial class InteractiveBoardVisualsComponent : Component
{
public string ImagePath = "/Textures/White/Interface/InteractiveBoard/interactiveboardbackground.png";
public Box2 BackgroundPatchMargin = default;
public Color BackgroundModulate = Color.White;
public bool BackgroundImageTile = false;
public Vector2 BackgroundScale = Vector2.One;
public string? HeaderImagePath;
public Color HeaderImageModulate = Color.White;
public Box2 HeaderMargin = default;
public string? ContentImagePath;
public Color ContentImageModulate = Color.White;
public Box2 ContentMargin = default;
public int ContentImageNumLines = 1;
public Color FontAccentColor = new(223, 223, 213);
public Vector2? MaxWritableArea = null;
}

View File

@@ -0,0 +1,28 @@
<controls:InteractiveBoardWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client._White.InteractiveBoard.UI"
MouseFilter="Stop" MinSize="500 500"
SetSize="600 650">
<BoxContainer Name="ContentsRoot" Orientation="Vertical">
<PanelContainer StyleClasses="AngleRect" VerticalAlignment="Top">
<TextureButton Name="CloseButton" StyleClasses="windowCloseButton" HorizontalAlignment="Right"/>
<Button Name="CopyButton" Text="Копировать текст" StyleClasses="windowCopyButton" HorizontalAlignment="Left"/>
</PanelContainer>
<PanelContainer Name="Background" StyleClasses="DefaultBorder" VerticalExpand="True" HorizontalExpand="True">
<ScrollContainer Name="ScrollingContents" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="False">
<PanelContainer Name="Content" VerticalExpand="True" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" VerticalAlignment="Stretch">
<TextureButton Name="HeaderImage" HorizontalAlignment="Center" VerticalAlignment="Top" MouseFilter="Ignore"/>
<Control Name="TextAlignmentPadding" VerticalAlignment="Top"/>
<RichTextLabel Name="BlankIndicator" StyleClasses="LabelSecondaryColor" VerticalAlignment="Top" HorizontalAlignment="Center"/>
<RichTextLabel StyleClasses="WrittenText" Name="WrittenTextLabel" VerticalAlignment="Stretch" Margin="4" HorizontalExpand="True"/>
<PanelContainer Name="InputContainer" StyleClasses="TransparentBorderedWindowPanel" MinHeight="100"
VerticalAlignment="Stretch" VerticalExpand="True" HorizontalExpand="True">
<TextEdit Name="Input" StyleClasses="LineEdit" Access="Public" />
</PanelContainer>
</BoxContainer>
</PanelContainer>
</ScrollContainer>
</PanelContainer>
</BoxContainer>
</controls:InteractiveBoardWindow>

View File

@@ -0,0 +1,207 @@
using System.Numerics;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.RichText;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Utility;
using static Content.Shared._White.InteractiveBoard.SharedInteractiveBoardComponent;
namespace Content.Client._White.InteractiveBoard.UI
{
[GenerateTypedNameReferences]
public sealed partial class InteractiveBoardWindow : BaseWindow
{
private static readonly Color DefaultTextColor = new(255, 255, 255);
private const int MarginSize = 12;
private StyleBoxTexture _contentTex = new();
private float _contentLineScale = 1.0f;
private DragMode _allowedResizeModes = ~DragMode.None;
private readonly Type[] _allowedTags = new Type[]
{
typeof(BoldItalicTag),
typeof(BoldTag),
typeof(BulletTag),
typeof(ColorTag),
typeof(HeadingTag),
typeof(ItalicTag)
};
public InteractiveBoardWindow()
{
RobustXamlLoader.Load(this);
CloseButton.OnPressed += _ => Close();
CopyButton.OnPressed += _ => CopyToClipboard();
}
public void InitVisuals(EntityUid entity, InteractiveBoardVisualsComponent visuals)
{
var resCache = IoCManager.Resolve<IResourceCache>();
Background.ModulateSelfOverride = visuals.BackgroundModulate;
var backgroundImage = resCache.GetResource<TextureResource>(visuals.ImagePath);
{
var backgroundImageMode = visuals.BackgroundImageTile ? StyleBoxTexture.StretchMode.Tile : StyleBoxTexture.StretchMode.Stretch;
var backgroundPatchMargin = visuals.BackgroundPatchMargin;
Background.PanelOverride = new StyleBoxTexture
{
Texture = backgroundImage,
TextureScale = visuals.BackgroundScale,
Mode = backgroundImageMode,
PatchMarginLeft = backgroundPatchMargin.Left,
PatchMarginBottom = backgroundPatchMargin.Bottom,
PatchMarginRight = backgroundPatchMargin.Right,
PatchMarginTop = backgroundPatchMargin.Top
};
}
if (visuals.HeaderImagePath != null)
{
HeaderImage.TexturePath = visuals.HeaderImagePath;
HeaderImage.MinSize = HeaderImage.TextureNormal?.Size ?? Vector2.Zero;
}
HeaderImage.ModulateSelfOverride = visuals.HeaderImageModulate;
HeaderImage.Margin = new Thickness(visuals.HeaderMargin.Left, visuals.HeaderMargin.Top,
visuals.HeaderMargin.Right, visuals.HeaderMargin.Bottom);
Content.ModulateSelfOverride = visuals.ContentImageModulate;
WrittenTextLabel.ModulateSelfOverride = visuals.FontAccentColor;
var contentImage = visuals.ContentImagePath != null ? resCache.GetResource<TextureResource>(visuals.ContentImagePath) : null;
if (contentImage != null)
{
_contentTex = new StyleBoxTexture
{
Texture = contentImage,
Mode = StyleBoxTexture.StretchMode.Tile,
};
Content.PanelOverride = _contentTex;
_contentLineScale = visuals.ContentImageNumLines;
}
Content.Margin = new Thickness(
visuals.ContentMargin.Left, visuals.ContentMargin.Top,
visuals.ContentMargin.Right, visuals.ContentMargin.Bottom);
if (visuals.MaxWritableArea != null)
{
var a = (Vector2)visuals.MaxWritableArea;
ScrollingContents.MinSize = Vector2.Zero;
ScrollingContents.MinSize = a;
if (a.X > 0.0f)
{
ScrollingContents.MaxWidth = a.X;
_allowedResizeModes &= ~(DragMode.Left | DragMode.Right);
SetWidth = float.NaN;
}
if (a.Y > 0.0f)
{
ScrollingContents.MaxHeight = a.Y;
_allowedResizeModes &= ~(DragMode.Top | DragMode.Bottom);
SetHeight = float.NaN;
}
}
}
protected override void Draw(DrawingHandleScreen handle)
{
if (WrittenTextLabel.TryGetStyleProperty<Font>("font", out var font))
{
float fontLineHeight = font.GetLineHeight(1.0f);
_contentTex.ExpandMarginTop = font.GetDescent(UIScale);
var scaleY = _contentLineScale * fontLineHeight / _contentTex.Texture?.Height ?? fontLineHeight;
_contentTex.TextureScale = new Vector2(1, scaleY);
{
var headerHeight = HeaderImage.Size.Y + HeaderImage.Margin.Top + HeaderImage.Margin.Bottom;
var headerInLines = headerHeight / (fontLineHeight * _contentLineScale);
var paddingRequiredInLines = (float)Math.Ceiling(headerInLines) - headerInLines;
var verticalMargin = fontLineHeight * paddingRequiredInLines * _contentLineScale;
TextAlignmentPadding.Margin = new Thickness(0.0f, verticalMargin, 0.0f, 0.0f);
}
}
base.Draw(handle);
}
public void Populate(InteractiveBoardBoundUserInterfaceState state)
{
var isEditing = state.Mode == InteractiveBoardAction.Write;
var wasEditing = InputContainer.Visible;
InputContainer.Visible = isEditing;
var msg = new FormattedMessage();
msg.AddMarkupPermissive(state.Text);
var shouldCopyText = 0 == Input.TextLength && 0 != state.Text.Length;
if (!wasEditing || shouldCopyText)
{
Input.TextRope = Rope.Leaf.Empty;
Input.CursorPosition = new TextEdit.CursorPos();
Input.InsertAtCursor(state.Text);
}
WrittenTextLabel.SetMessage(msg, _allowedTags, DefaultTextColor);
WrittenTextLabel.Visible = !isEditing && state.Text.Length > 0;
BlankIndicator.Visible = !isEditing && state.Text.Length == 0;
}
protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
{
var mode = DragMode.None;
if (relativeMousePos.Y < MarginSize)
{
mode |= DragMode.Top;
}
else if (relativeMousePos.Y > Size.Y - MarginSize)
{
mode |= DragMode.Bottom;
}
if (relativeMousePos.X < MarginSize)
{
mode |= DragMode.Left;
}
else if (relativeMousePos.X > Size.X - MarginSize)
{
mode |= DragMode.Right;
}
if((mode & _allowedResizeModes) == DragMode.None)
{
return DragMode.Move;
}
return mode & _allowedResizeModes;
}
private void CopyToClipboard()
{
if (WrittenTextLabel.GetMessage() == null)
return;
if (InputContainer.Visible)
{
InputContainer.Visible = false;
Input.Editable = true;
WrittenTextLabel.Visible = true;
return;
}
InputContainer.Visible = true;
Input.Editable = false;
WrittenTextLabel.Visible = false;
}
}
}

View File

@@ -0,0 +1,14 @@
using Content.Shared._White.InteractiveBoard;
using Robust.Shared.GameStates;
namespace Content.Server._White.InteractiveBoard;
[NetworkedComponent, RegisterComponent]
public sealed partial class InteractiveBoardComponent : SharedInteractiveBoardComponent
{
public InteractiveBoardAction Mode;
public string Content { get; set; } = "";
public int ContentSize { get; set; } = 6000;
}

View File

@@ -0,0 +1,221 @@
using Content.Server._White.Other;
using Content.Server.Hands.Systems;
using Content.Server.Popups;
using Content.Shared.Access.Components;
using Content.Shared.Access.Systems;
using Content.Shared.Coordinates;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Content.Shared.UserInterface;
using Content.Shared.Verbs;
using Content.Shared.Wall;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
using static Content.Shared._White.InteractiveBoard.SharedInteractiveBoardComponent;
namespace Content.Server._White.InteractiveBoard;
public sealed class InteractiveBoardSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedInteractionSystem _interaction = default!;
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly TransformSystem _transformSystem = default!;
[Dependency] private readonly HandsSystem _handsSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<InteractiveBoardComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<InteractiveBoardComponent, BeforeActivatableUIOpenEvent>(BeforeUIOpen);
SubscribeLocalEvent<InteractiveBoardComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<InteractiveBoardComponent, InteractiveBoardInputTextMessage>(OnInputTextMessage);
SubscribeLocalEvent<InteractiveBoardComponent, GetVerbsEvent<AlternativeVerb>>(OnAltVerb);
SubscribeLocalEvent<InteractiveBoardComponent, BeforeRangedInteractEvent>(BeforeRangedInteract);
SubscribeLocalEvent<OnInteractiveBoardWriteComponent, InteractiveBoardWriteEvent>(OnInteractiveBoardWrite);
}
private void OnInit(EntityUid uid, InteractiveBoardComponent component, ComponentInit args)
{
component.Mode = InteractiveBoardAction.Read;
UpdateUserInterface(uid, component);
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
if (component.Content != "")
_appearance.SetData(uid, InteractiveBoardVisuals.Status, InteractiveBoardStatus.Written, appearance);
}
private void OnAltVerb(EntityUid uid, InteractiveBoardComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;
if(!HasComp<WallMountComponent>(args.Target))
return;
AlternativeVerb verb = new()
{
Act = () =>
{
TakeOffInteractiveBoard(args.User, args.Target);
},
Disabled = false,
Priority = 1,
Text = Loc.GetString("interactive-board-take-off"),
};
args.Verbs.Add(verb);
}
private void TakeOffInteractiveBoard(EntityUid uid, EntityUid target)
{
if(!TryComp<TransformComponent>(target, out var transformComponent))
return;
if(!HasComp<WallMountComponent>(target))
return;
if(!transformComponent.Anchored)
return;
_transformSystem.Unanchor(target, transformComponent);
RemComp<WallMountComponent>(target);
if (!_handsSystem.TryPickupAnyHand(uid, target))
{
_transformSystem.SetCoordinates(target, uid.ToCoordinates());
}
}
private void BeforeUIOpen(EntityUid uid, InteractiveBoardComponent component, BeforeActivatableUIOpenEvent args)
{
component.Mode = InteractiveBoardAction.Read;
if (!TryComp<ActorComponent>(args.User, out var actor))
return;
UpdateUserInterface(uid, component, actor.PlayerSession);
}
private void BeforeRangedInteract(EntityUid uid, InteractiveBoardComponent component, BeforeRangedInteractEvent args)
{
if (_tagSystem.HasTag(args.Used, "InteractiveBoard"))
{
if (!HasComp<WallMarkComponent>(args.Target) && !HasComp<WindowMarkComponent>(args.Target))
return;
if(!TryComp<TransformComponent>(args.Target, out var transformComponent))
return;
if (!TryComp<TransformComponent>(args.Used, out var xform))
return;
_handsSystem.TryDrop(args.User, args.Used);
_transformSystem.SetCoordinates(args.Used, transformComponent.Coordinates);
_transformSystem.AnchorEntity(args.Used, xform);
_transformSystem.AttachToGridOrMap(args.Used, xform);
AddComp<WallMountComponent>(args.Used).Arc = new Angle(360);
}
}
private void OnInteractUsing(EntityUid uid, InteractiveBoardComponent component, InteractUsingEvent args)
{
if (!_tagSystem.HasTag(args.Used, "InteractivePen"))
return;
if(!TryComp<AccessReaderComponent>(args.Target, out var accessReaderComponent))
return;
if (!_accessReaderSystem.IsAllowed(args.User, args.Target, accessReaderComponent))
{
_popupSystem.PopupEntity(Loc.GetString("interactive-board-not-allowed"), args.User, args.User, PopupType.Medium);
return;
}
var writeEvent = new InteractiveBoardWriteEvent(uid, args.User);
RaiseLocalEvent(args.Used, ref writeEvent);
if (!TryComp<ActorComponent>(args.User, out var actor))
return;
component.Mode = InteractiveBoardAction.Write;
_uiSystem.TryOpen(uid, InteractiveBoardUiKey.Key, actor.PlayerSession);
UpdateUserInterface(uid, component, actor.PlayerSession);
args.Handled = true;
}
private void OnInputTextMessage(EntityUid uid, InteractiveBoardComponent component, InteractiveBoardInputTextMessage args)
{
if (args.Text.Length <= component.ContentSize)
{
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
component.Content = args.Text.Replace("[", "(").Replace("]", ")");
if (string.IsNullOrWhiteSpace(component.Content))
{
component.Mode = InteractiveBoardAction.Read;
_appearance.SetData(uid, InteractiveBoardVisuals.Status, InteractiveBoardStatus.Blank, appearance);
return;
}
_appearance.SetData(uid, InteractiveBoardVisuals.Status, InteractiveBoardStatus.Written, appearance);
}
if (args.Text.Length > component.ContentSize)
{
component.Content = args.Text.Remove(component.ContentSize, (args.Text.Length - component.ContentSize));
if (TryComp<AppearanceComponent>(uid, out var appearance))
_appearance.SetData(uid, InteractiveBoardVisuals.Status, InteractiveBoardStatus.Written, appearance);
}
component.Mode = InteractiveBoardAction.Read;
UpdateUserInterface(uid, component);
}
private void OnInteractiveBoardWrite(EntityUid uid, OnInteractiveBoardWriteComponent comp, ref InteractiveBoardWriteEvent args)
{
_interaction.UseInHandInteraction(args.User, uid);
}
public void SetContent(EntityUid uid, string content, InteractiveBoardComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
component.Content = content + '\n';
UpdateUserInterface(uid, component);
if (!TryComp<AppearanceComponent>(uid, out var appearance))
return;
var status = string.IsNullOrWhiteSpace(content)
? InteractiveBoardStatus.Blank
: InteractiveBoardStatus.Written;
_appearance.SetData(uid, InteractiveBoardVisuals.Status, status, appearance);
}
public void UpdateUserInterface(EntityUid uid, InteractiveBoardComponent? component = null, ICommonSession? session = null)
{
if (!Resolve(uid, ref component))
return;
if (_uiSystem.TryGetUi(uid, InteractiveBoardUiKey.Key, out var bui))
_uiSystem.SetUiState(bui, new InteractiveBoardBoundUserInterfaceState(component.Content, component.Mode), session);
}
}
[ByRefEvent]
public record struct InteractiveBoardWriteEvent(EntityUid User, EntityUid InteractiveBoard);

View File

@@ -0,0 +1,7 @@
namespace Content.Server._White.InteractiveBoard;
[RegisterComponent]
[Access(typeof(InteractiveBoardSystem))]
public sealed partial class OnInteractiveBoardWriteComponent : Component
{
}

View File

@@ -0,0 +1,55 @@
using Robust.Shared.Serialization;
namespace Content.Shared._White.InteractiveBoard;
public abstract partial class SharedInteractiveBoardComponent : Component
{
[Serializable, NetSerializable]
public sealed class InteractiveBoardBoundUserInterfaceState : BoundUserInterfaceState
{
public readonly string Text;
public readonly InteractiveBoardAction Mode;
public InteractiveBoardBoundUserInterfaceState(string text, InteractiveBoardAction mode = InteractiveBoardAction.Read)
{
Text = text;
Mode = mode;
}
}
[Serializable, NetSerializable]
public sealed class InteractiveBoardInputTextMessage : BoundUserInterfaceMessage
{
public readonly string Text;
public InteractiveBoardInputTextMessage(string text)
{
Text = text;
}
}
[Serializable, NetSerializable]
public enum InteractiveBoardUiKey
{
Key
}
[Serializable, NetSerializable]
public enum InteractiveBoardAction
{
Read,
Write,
}
[Serializable, NetSerializable]
public enum InteractiveBoardVisuals : byte
{
Status
}
[Serializable, NetSerializable]
public enum InteractiveBoardStatus : byte
{
Blank,
Written
}
}

View File

@@ -0,0 +1,6 @@
interactive-board-not-allowed = Недостаточный доступ для редактирования!
interactive-board-take-off = Снять доску
ent-InteractiveBoard = интерактивная доска
.desc = Имеется поле для текста. Создано специально для бюрократии! Можно прикрепить на стену.
ent-InteractivePen = контактная ручка
.desc = Позволяет редактировать интерактивную доску.

View File

@@ -99,7 +99,7 @@
gasMolesVisible: 0.6 gasMolesVisible: 0.6
color: 3a758c color: 3a758c
reagent: Frezon reagent: Frezon
pricePerMole: 0.3 pricePerMole: 8
- type: gas - type: gas
id: 9 id: 9

View File

@@ -107,6 +107,8 @@
- id: BoxEncryptionKeyPassenger - id: BoxEncryptionKeyPassenger
- id: BoxEncryptionKeyService - id: BoxEncryptionKeyService
- id: BoxFolderClipboard - id: BoxFolderClipboard
- id: InteractiveBoard
- id: InteractivePen
- type: entity - type: entity
id: LockerHeadOfPersonnelFilledHardsuit id: LockerHeadOfPersonnelFilledHardsuit

View File

@@ -0,0 +1,49 @@
- type: entity
name: interactive board
parent: BaseItem
id: InteractiveBoard
description: 'Have field for edit. Created special for burocracy!'
components:
- type: Sprite
sprite: /Textures/White/Objects/Devices/interactiveboard.rsi
layers:
- state: interactiveboard
- state: interactiveboard_with_words
map: ["enum.InteractiveBoardVisualLayers.Writing"]
visible: false
- type: Item
size: Huge
- type: InteractiveBoard
- type: Tag
tags:
- InteractiveBoard
- type: ActivatableUI
key: enum.InteractiveBoardUiKey.Key
- type: UserInterface
interfaces:
- key: enum.InteractiveBoardUiKey.Key
type: InteractiveBoardBoundUserInterface
- type: Appearance
- type: InteractiveBoardVisuals
- type: AccessReader
access: [ [ "Command" ] ]
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 150
- type: entity
name: interactive pen
parent: BaseItem
id: InteractivePen
description: 'Edit interactive board!'
components:
- type: Sprite
sprite: /Textures/White/Objects/Devices/interactiveboard.rsi
state: pen
- type: Item
size: Tiny
- type: Tag
tags:
- InteractivePen

View File

@@ -60,3 +60,9 @@
- type: Tag - type: Tag
id: NeuroControl id: NeuroControl
- type: Tag
id: InteractivePen
- type: Tag
id: InteractiveBoard

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

View File

@@ -0,0 +1,2 @@
sample:
filter: true

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

View File

@@ -0,0 +1,20 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "https://github.com/frosty-dev/ss14-core/",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "interactiveboard"
},
{
"name": "interactiveboard_with_words"
},
{
"name": "pen"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 B