jamesperet 3 роки тому
коміт
999c8bad70
30 змінених файлів з 1035 додано та 0 видалено
  1. 71 0
      .gitignore
  2. 9 0
      ChangeLog.md
  3. 7 0
      ChangeLog.md.meta
  4. 8 0
      Prefabs.meta
  5. 309 0
      Prefabs/SelectableActionButtonPrefab.prefab
  6. 7 0
      Prefabs/SelectableActionButtonPrefab.prefab.meta
  7. 23 0
      Readme.md
  8. 7 0
      Readme.md.meta
  9. 8 0
      Runtime.meta
  10. 8 0
      Runtime/InteractionTools.meta
  11. 12 0
      Runtime/InteractionTools/IInteractionTool.cs
  12. 11 0
      Runtime/InteractionTools/IInteractionTool.cs.meta
  13. 53 0
      Runtime/InteractionTools/InteractionToolsManager.cs
  14. 11 0
      Runtime/InteractionTools/InteractionToolsManager.cs.meta
  15. 19 0
      Runtime/KairoEngine.GameTools.asmdef
  16. 7 0
      Runtime/KairoEngine.GameTools.asmdef.meta
  17. 8 0
      Runtime/SelectableObjects.meta
  18. 16 0
      Runtime/SelectableObjects/ISelectableObject.cs
  19. 11 0
      Runtime/SelectableObjects/ISelectableObject.cs.meta
  20. 24 0
      Runtime/SelectableObjects/SelectableObjectAction.cs
  21. 11 0
      Runtime/SelectableObjects/SelectableObjectAction.cs.meta
  22. 131 0
      Runtime/SelectableObjects/SelectableObjectTool.cs
  23. 11 0
      Runtime/SelectableObjects/SelectableObjectTool.cs.meta
  24. 79 0
      Runtime/SelectableObjects/SelectableObjectTrigger.cs
  25. 11 0
      Runtime/SelectableObjects/SelectableObjectTrigger.cs.meta
  26. 108 0
      Runtime/SelectableObjects/SelectionActionsView.cs
  27. 11 0
      Runtime/SelectableObjects/SelectionActionsView.cs.meta
  28. 14 0
      Runtime/SelectableObjects/SelectionView.cs
  29. 11 0
      Runtime/SelectableObjects/SelectionView.cs.meta
  30. 19 0
      package.json

+ 71 - 0
.gitignore

@@ -0,0 +1,71 @@
+# This .gitignore file should be placed at the root of your Unity project directory
+#
+# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
+#
+/[Ll]ibrary/
+/[Tt]emp/
+/[Oo]bj/
+/[Bb]uild/
+/[Bb]uilds/
+/[Ll]ogs/
+/[Uu]ser[Ss]ettings/
+
+# MemoryCaptures can get excessive in size.
+# They also could contain extremely sensitive data
+/[Mm]emoryCaptures/
+
+# Asset meta data should only be ignored when the corresponding asset is also ignored
+!/[Aa]ssets/**/*.meta
+
+# Uncomment this line if you wish to ignore the asset store tools plugin
+# /[Aa]ssets/AssetStoreTools*
+
+# Autogenerated Jetbrains Rider plugin
+/[Aa]ssets/Plugins/Editor/JetBrains*
+
+# Visual Studio cache directory
+.vs/
+
+# Gradle cache directory
+.gradle/
+
+# Autogenerated VS/MD/Consulo solution and project files
+ExportedObj/
+.consulo/
+*.csproj
+*.unityproj
+*.sln
+*.suo
+*.tmp
+*.user
+*.userprefs
+*.pidb
+*.booproj
+*.svd
+*.pdb
+*.mdb
+*.opendb
+*.VC.db
+
+# Unity3D generated meta files
+*.pidb.meta
+*.pdb.meta
+*.mdb.meta
+
+# Unity3D generated file on crash reports
+sysinfo.txt
+
+# Builds
+*.apk
+*.aab
+*.unitypackage
+
+# Crashlytics generated file
+crashlytics-build.properties
+
+# Packed Addressables
+/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
+
+# Temporary auto-generated Android Assets
+/[Aa]ssets/[Ss]treamingAssets/aa.meta
+/[Aa]ssets/[Ss]treamingAssets/aa/*

+ 9 - 0
ChangeLog.md

@@ -0,0 +1,9 @@
+# GameTools Change Log
+
+### v0.1.0
+
+- Consolidaded the project. *06/27/21 - 01:24* 
+
+- 
+
+

+ 7 - 0
ChangeLog.md.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: dd9393d3057119044b432163e3638782
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Prefabs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: eb8fbe0333932ea45b3f652607845668
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 309 - 0
Prefabs/SelectableActionButtonPrefab.prefab

@@ -0,0 +1,309 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &4645305705816878757
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 4343454027240251526}
+  - component: {fileID: 3237756694349720561}
+  - component: {fileID: 2845122171005829875}
+  m_Layer: 0
+  m_Name: Text (TMP)
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &4343454027240251526
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4645305705816878757}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children: []
+  m_Father: {fileID: 337997096451719972}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 1, y: 1}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0.5, y: 0.5}
+--- !u!222 &3237756694349720561
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4645305705816878757}
+  m_CullTransparentMesh: 0
+--- !u!114 &2845122171005829875
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4645305705816878757}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 1, g: 1, b: 1, a: 1}
+  m_RaycastTarget: 1
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_text: Button
+  m_isRightToLeft: 0
+  m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
+  m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
+  m_fontSharedMaterials: []
+  m_fontMaterial: {fileID: 0}
+  m_fontMaterials: []
+  m_fontColor32:
+    serializedVersion: 2
+    rgba: 4294967295
+  m_fontColor: {r: 1, g: 1, b: 1, a: 1}
+  m_enableVertexGradient: 0
+  m_colorMode: 3
+  m_fontColorGradient:
+    topLeft: {r: 1, g: 1, b: 1, a: 1}
+    topRight: {r: 1, g: 1, b: 1, a: 1}
+    bottomLeft: {r: 1, g: 1, b: 1, a: 1}
+    bottomRight: {r: 1, g: 1, b: 1, a: 1}
+  m_fontColorGradientPreset: {fileID: 0}
+  m_spriteAsset: {fileID: 0}
+  m_tintAllSprites: 0
+  m_StyleSheet: {fileID: 0}
+  m_TextStyleHashCode: -1183493901
+  m_overrideHtmlColors: 0
+  m_faceColor:
+    serializedVersion: 2
+    rgba: 4294967295
+  m_fontSize: 14
+  m_fontSizeBase: 14
+  m_fontWeight: 400
+  m_enableAutoSizing: 0
+  m_fontSizeMin: 18
+  m_fontSizeMax: 72
+  m_fontStyle: 1
+  m_HorizontalAlignment: 2
+  m_VerticalAlignment: 512
+  m_textAlignment: 65535
+  m_characterSpacing: 0
+  m_wordSpacing: 0
+  m_lineSpacing: 0
+  m_lineSpacingMax: 0
+  m_paragraphSpacing: 0
+  m_charWidthMaxAdj: 0
+  m_enableWordWrapping: 1
+  m_wordWrappingRatios: 0.4
+  m_overflowMode: 0
+  m_linkedTextComponent: {fileID: 0}
+  parentLinkedComponent: {fileID: 0}
+  m_enableKerning: 1
+  m_enableExtraPadding: 0
+  checkPaddingRequired: 0
+  m_isRichText: 1
+  m_parseCtrlCharacters: 1
+  m_isOrthographic: 1
+  m_isCullingEnabled: 0
+  m_horizontalMapping: 0
+  m_verticalMapping: 0
+  m_uvLineOffset: 0
+  m_geometrySortingOrder: 0
+  m_IsTextObjectScaleStatic: 0
+  m_VertexBufferAutoSizeReduction: 1
+  m_useMaxVisibleDescender: 1
+  m_pageToDisplay: 1
+  m_margin: {x: 0, y: 0, z: 0, w: 0}
+  m_isUsingLegacyAnimationComponent: 0
+  m_isVolumetricText: 0
+  m_hasFontAssetChanged: 0
+  m_baseMaterial: {fileID: 0}
+  m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
+--- !u!1 &4829916165997224620
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 337997096451719972}
+  - component: {fileID: 8942225441379847300}
+  - component: {fileID: 3796121682672810588}
+  - component: {fileID: 8550027733724131984}
+  - component: {fileID: 7111908960206650674}
+  - component: {fileID: 7111908960206650677}
+  - component: {fileID: -3546092901590019188}
+  m_Layer: 0
+  m_Name: SelectableActionButtonPrefab
+  m_TagString: Untagged
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!224 &337997096451719972
+RectTransform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: 0}
+  m_LocalScale: {x: 1, y: 1, z: 1}
+  m_Children:
+  - {fileID: 4343454027240251526}
+  m_Father: {fileID: 0}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+  m_AnchorMin: {x: 0, y: 0}
+  m_AnchorMax: {x: 0, y: 0}
+  m_AnchoredPosition: {x: 0, y: 0}
+  m_SizeDelta: {x: 0, y: 0}
+  m_Pivot: {x: 0, y: 0.5}
+--- !u!222 &8942225441379847300
+CanvasRenderer:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_CullTransparentMesh: 0
+--- !u!114 &3796121682672810588
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Material: {fileID: 0}
+  m_Color: {r: 0.16981131, g: 0.16981131, b: 0.16981131, a: 1}
+  m_RaycastTarget: 1
+  m_Maskable: 1
+  m_OnCullStateChanged:
+    m_PersistentCalls:
+      m_Calls: []
+  m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
+  m_Type: 1
+  m_PreserveAspect: 0
+  m_FillCenter: 1
+  m_FillMethod: 4
+  m_FillAmount: 1
+  m_FillClockwise: 1
+  m_FillOrigin: 0
+  m_UseSpriteMesh: 0
+  m_PixelsPerUnitMultiplier: 1
+--- !u!114 &8550027733724131984
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Navigation:
+    m_Mode: 3
+    m_SelectOnUp: {fileID: 0}
+    m_SelectOnDown: {fileID: 0}
+    m_SelectOnLeft: {fileID: 0}
+    m_SelectOnRight: {fileID: 0}
+  m_Transition: 1
+  m_Colors:
+    m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
+    m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
+    m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
+    m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
+    m_ColorMultiplier: 1
+    m_FadeDuration: 0.1
+  m_SpriteState:
+    m_HighlightedSprite: {fileID: 0}
+    m_PressedSprite: {fileID: 0}
+    m_SelectedSprite: {fileID: 0}
+    m_DisabledSprite: {fileID: 0}
+  m_AnimationTriggers:
+    m_NormalTrigger: Normal
+    m_HighlightedTrigger: Highlighted
+    m_PressedTrigger: Pressed
+    m_SelectedTrigger: Selected
+    m_DisabledTrigger: Disabled
+  m_Interactable: 1
+  m_TargetGraphic: {fileID: 3796121682672810588}
+  m_OnClick:
+    m_PersistentCalls:
+      m_Calls:
+      - m_Target: {fileID: 7111908960206650674}
+        m_MethodName: OnClick
+        m_Mode: 1
+        m_Arguments:
+          m_ObjectArgument: {fileID: 0}
+          m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
+          m_IntArgument: 0
+          m_FloatArgument: 0
+          m_StringArgument: 
+          m_BoolArgument: 0
+        m_CallState: 2
+--- !u!114 &7111908960206650674
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: b7f39340cf67bdf43b12a74681b8b05a, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  title: 
+--- !u!114 &7111908960206650677
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: aba906f73151edb44ad3e23a912a4c55, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  headerComponent: {fileID: 2845122171005829875}
+  graphicComponent: {fileID: 3796121682672810588}
+--- !u!114 &-3546092901590019188
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 4829916165997224620}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 460bbea74d2a0b1459abb106bd7882d4, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  header: 
+  content: 

+ 7 - 0
Prefabs/SelectableActionButtonPrefab.prefab.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 90dd0b180411dd9439173542998ee27d
+PrefabImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 23 - 0
Readme.md

@@ -0,0 +1,23 @@
+# 📦 KairoEngine.GameTools.v0.1.1
+
+This package contains the **Game Tools System**, used in strategy type games. It consists of a interaction tool that can hold many different custom tools. Another built in tool is the selection tool, used to select objects and execute actions.
+
+This package ties in with the **Grid Building System**, which adds the ``GridBuildTool`` and builds are selectable.
+
+### 🛑Dependencies
+
+- KairoEngine.Core
+
+- KairoEngine.Stockpiles
+
+- KairoEngine.UI
+
+- Sirenix.OdinInspector
+
+- EasyPerformantOutline
+
+### 📄Namespaces
+
+- `KairoEngine.GameTools.InteractionTools`
+
+- `KairoEngine.GameTools.Selectables`

+ 7 - 0
Readme.md.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 1ff3e537aabf83542b65a43a97bece2e
+TextScriptImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Runtime.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6e76f46557ab17845a2d088448622872
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Runtime/InteractionTools.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1c172d059a37aa74fa38af5582f5f99a
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 12 - 0
Runtime/InteractionTools/IInteractionTool.cs

@@ -0,0 +1,12 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace KairoEngine.GameTools.InteractionTools
+{
+    public interface IInteractionTool
+    {
+        void EnableTool();
+        void DisableTool();
+    }
+}

+ 11 - 0
Runtime/InteractionTools/IInteractionTool.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: e53677ccabd62f0498b8a6f03a9790eb
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 53 - 0
Runtime/InteractionTools/InteractionToolsManager.cs

@@ -0,0 +1,53 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using Sirenix.OdinInspector;
+
+namespace KairoEngine.GameTools.InteractionTools
+{
+    /// <summary>
+    /// Manages which interaction tool is currently on.
+    /// </summary>
+    public class InteractionToolsManager : MonoBehaviour
+    {
+        public static InteractionToolsManager instance;
+        [ReadOnly] public int currentTools = 0;
+        public List<GameObject> tools = new List<GameObject>();
+        private List<IInteractionTool> toolInterfaces = new List<IInteractionTool>();
+
+        private void Awake()
+        {
+            if(instance == null) instance = this;
+            else Destroy(this);
+        }
+
+        private void Start()
+        {
+            RegisterInterfaces();
+            ChangeTool(currentTools);
+        }
+
+        private void RegisterInterfaces()
+        {
+            toolInterfaces = new List<IInteractionTool>();
+            for (int i = 0; i < tools.Count; i++)
+            {
+                IInteractionTool toolInterface = tools[i].GetComponent<IInteractionTool>();
+                if(toolInterface == null) toolInterface = tools[i].GetComponentInChildren<IInteractionTool>();
+                if(toolInterface != null) toolInterfaces.Add(toolInterface);
+                else Debug.LogError($"No Interaction tool interface found in components on \"{tools[i].name}\"", tools[i]);
+            }
+        }
+
+        public void ChangeTool(int toolIndex)
+        {
+            currentTools = toolIndex;
+            for (int i = 0; i < toolInterfaces.Count; i++)
+            {
+                if(i != toolIndex) toolInterfaces[i].DisableTool();
+                else toolInterfaces[i].EnableTool();
+            }
+        }
+    }
+}
+

+ 11 - 0
Runtime/InteractionTools/InteractionToolsManager.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f0c56d381b99a95488fceb8a4baec3e8
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
Runtime/KairoEngine.GameTools.asmdef

@@ -0,0 +1,19 @@
+{
+    "name": "KairoEngine.GameTools",
+    "references": [
+        "GUID:7e5ae6a38d1532248b4c890eca668b06",
+        "GUID:b5398ac4f2218bd4ba186b0baff7fb21",
+        "GUID:142285d3db5e7e849b02ea3a75bc2de7",
+        "GUID:5f03fc37b95cb644599751ca563336b2",
+        "GUID:ed7bf2f4272e1b74a98086f77f3ae14c"
+    ],
+    "includePlatforms": [],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false,
+    "overrideReferences": false,
+    "precompiledReferences": [],
+    "autoReferenced": true,
+    "defineConstraints": [],
+    "versionDefines": [],
+    "noEngineReferences": false
+}

+ 7 - 0
Runtime/KairoEngine.GameTools.asmdef.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: f452697229e6bcc469c0eff1574ac090
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Runtime/SelectableObjects.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6084568973b1e2548b1443512d76904d
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 16 - 0
Runtime/SelectableObjects/ISelectableObject.cs

@@ -0,0 +1,16 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace KairoEngine.GameTools.Selectables
+{
+    /// <summary>
+    /// An interface that represents and object that can be selected and has actions.
+    /// </summary>
+    public interface ISelectableObject
+    {
+        List<SelectableObjectAction> actions { get; }
+        void ExecuteAction(SelectableObjectAction action);
+    }
+}
+

+ 11 - 0
Runtime/SelectableObjects/ISelectableObject.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7815dec52268bdf4391849ef636b0f7e
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 24 - 0
Runtime/SelectableObjects/SelectableObjectAction.cs

@@ -0,0 +1,24 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using KairoEngine.Core.GameActions;
+using KairoEngine.Stockpiles;
+using Sirenix.OdinInspector;
+
+namespace KairoEngine.GameTools.Selectables
+{
+    /// <summary>
+    /// Represents an action that is contained in a component implementing the SelectableObject interface.
+    /// </summary>
+    [System.Serializable]
+    public class SelectableObjectAction
+    {
+        [FoldoutGroup("@title")] public string title = "New SelectableObjectAction";
+        [FoldoutGroup("@title")] public bool showAction = true;
+        [FoldoutGroup("@title")] public Sprite icon;
+        [FoldoutGroup("@title")] public string description;
+        [FoldoutGroup("@title"), PropertySpace(1, 1)] public List<KairoEngine.Stockpiles.Stockpile> cost = new List<KairoEngine.Stockpiles.Stockpile>();
+        [FoldoutGroup("@title"), InlineProperty, HideLabel] public GameActionsController actions;
+    }
+}
+

+ 11 - 0
Runtime/SelectableObjects/SelectableObjectAction.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 380eead34ce9baf48b739a51cd834632
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 131 - 0
Runtime/SelectableObjects/SelectableObjectTool.cs

@@ -0,0 +1,131 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using KairoEngine.GameTools.InteractionTools;
+using Sirenix.OdinInspector;
+using KairoEngine.UI;
+
+namespace KairoEngine.GameTools.Selectables
+{
+    /// <summary>
+    /// The selectableObject tools controls input for selecting objects in the game and visualizing its properties and actions.
+    /// </summary>
+    public class SelectableObjectTool : MonoBehaviour, IInteractionTool
+    {
+        public bool allowMultiSelection = true;
+        public KeyCode multiSelectionKey = KeyCode.LeftControl;
+        public LayerMask layerMask;
+        public bool selectableObjectToolEnabled = true;
+
+        [ShowInInspector, ReadOnly] public List<SelectableObjectTrigger> selectedObjects = new List<SelectableObjectTrigger>();
+
+        private void Update()
+        {
+            SelectObjects();
+        }
+
+        public void DisableTool()
+        {
+            selectableObjectToolEnabled = false;
+        }
+
+        public void EnableTool()
+        {
+            selectableObjectToolEnabled = true;
+        }
+
+        private void SelectObjects()
+        {
+            actionListChanged = false;
+            if(!selectableObjectToolEnabled) return;
+            if(Input.GetMouseButtonDown(0) && !MouseInputUIBlocker.BlockedByUI)
+            {
+                if(Camera.main == null) return;
+                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
+                if(Physics.Raycast(ray, out RaycastHit raycastHit, 999f, layerMask))
+                {
+                    var selectableObjectTrigger = raycastHit.collider.gameObject.GetComponent<SelectableObjectTrigger>();
+                    if(selectableObjectTrigger != null)
+                    {
+                        if(allowMultiSelection && Input.GetKey(multiSelectionKey)) AddToSelection(selectableObjectTrigger);
+                        else 
+                        {
+                            ClearSelection();
+                            AddToSelection(selectableObjectTrigger);
+                        }
+                    }
+                }
+            }
+        }
+
+        public void AddToSelection(SelectableObjectTrigger selectableObjectTrigger)
+        {
+            bool alreadySelected = false;
+            for (int i = 0; i < selectedObjects.Count; i++)
+            {
+                if(selectedObjects[i] == selectableObjectTrigger) alreadySelected = true;
+            }
+            if(alreadySelected == false) 
+            {
+                selectableObjectTrigger.Select();
+                selectedObjects.Add(selectableObjectTrigger);
+            }
+            else
+            {
+                selectableObjectTrigger.Deselect();
+                selectedObjects.Remove(selectableObjectTrigger);
+            }
+            actionListChanged = true;
+        }
+
+        public void ClearSelection()
+        {
+            for (int i = 0; i < selectedObjects.Count; i++)
+            {
+                if(selectedObjects[i] != null) selectedObjects[i].Deselect();
+            }
+            selectedObjects.Clear();
+            actionListChanged = true;
+        }
+
+        public bool ActionListChanged() => actionListChanged;
+        private bool actionListChanged = false;
+
+        public List<SelectableObjectAction> GetActions()
+        {
+            List<SelectableObjectAction> actions = new List<SelectableObjectAction>();
+            for (int i = 0; i < selectedObjects.Count; i++)
+            {
+                if(selectedObjects[i].selectableObject == null) continue;
+                if(selectedObjects[i].selectableObject.actions == null) continue;
+                for (int a = 0; a < selectedObjects[i].selectableObject.actions.Count; a++)
+                {
+                    bool duplicate = false;
+                    for (int v = 0; v < actions.Count; v++)
+                    {
+                        if(actions[v].title == selectedObjects[i].selectableObject.actions[a].title) duplicate = true;
+                    }
+                    if(!duplicate) actions.Add(selectedObjects[i].selectableObject.actions[a]);
+                }
+            }
+            return actions;
+        }
+
+        public void ExecuteAction(SelectableObjectAction action)
+        {
+            for (int i = 0; i < selectedObjects.Count; i++)
+            {
+                if(selectedObjects[i].selectableObject == null) continue;
+                if(selectedObjects[i].selectableObject.actions == null) continue;
+                for (int a = 0; a < selectedObjects[i].selectableObject.actions.Count; a++)
+                {
+                    if(selectedObjects[i].selectableObject.actions[a].title == action.title)
+                    {
+                        selectedObjects[i].selectableObject.ExecuteAction(action);
+                    }
+                }
+            }
+        }
+    }
+}
+

+ 11 - 0
Runtime/SelectableObjects/SelectableObjectTool.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 1916e1fac34aa9741b95153f2509427a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 79 - 0
Runtime/SelectableObjects/SelectableObjectTrigger.cs

@@ -0,0 +1,79 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.EventSystems;
+using EPOOutline;
+using KairoEngine.GameTools.InteractionTools;
+using KairoEngine.UI;
+
+namespace KairoEngine.GameTools.Selectables
+{
+    /// <summary>
+    /// Trigger for an ISelectableOnject. This component needs to be placed with a collider component.
+    /// </summary>
+    public class SelectableObjectTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
+    {
+        private InteractionToolsManager toolsManager;
+        public Outlinable outlinable;
+
+        public ISelectableObject selectableObject;
+
+        public bool isSelected = false;
+
+        private void Start()
+        {
+            toolsManager = InteractionToolsManager.instance;
+            if(outlinable == null) outlinable = GetComponent<Outlinable>();
+            if(outlinable == null) outlinable = GetComponentInParent<Outlinable>();
+            if(outlinable == null) outlinable = GetComponentInChildren<Outlinable>();
+            if(outlinable == null) Debug.LogError($"Could not find Outlinable component in {gameObject.name} hierarchy", this.gameObject);
+            if(outlinable != null) outlinable.enabled = false;
+            if(selectableObject == null) gameObject.transform.parent.GetComponent<ISelectableObject>();
+            if(selectableObject == null) gameObject.transform.parent.GetComponentInChildren<ISelectableObject>();
+        }
+
+        public void Select()
+        {
+            if(MouseInputUIBlocker.BlockedByUI) return;
+            isSelected = true;
+            ShowOutline();
+        } 
+
+        public void Deselect() 
+        {
+            isSelected = false;
+            HideOutline();
+        }
+
+        public void OnPointerEnter(PointerEventData eventData) => ShowOutline();
+
+        public void OnPointerExit(PointerEventData eventData) => HideOutline();
+
+        public void OnMouseEnter() => ShowOutline();
+
+        public void OnMouseExit() => HideOutline();
+
+        private void ShowOutline()
+        {
+            bool hasTool = toolsManager.currentTools == 0 || toolsManager.currentTools == 2;
+            if(hasTool && !MouseInputUIBlocker.BlockedByUI)
+            {
+                outlinable.enabled = true;
+                if(toolsManager.currentTools == 2)
+                {
+                    outlinable.OutlineParameters.Color = Color.red;
+                }
+                else
+                {
+                    outlinable.OutlineParameters.Color = Color.white;
+                }
+            }
+        }
+
+        private void HideOutline()
+        {
+            if(!isSelected) outlinable.enabled = false;
+        }
+    }
+}
+

+ 11 - 0
Runtime/SelectableObjects/SelectableObjectTrigger.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: eb23e0b8b8b55384fb9696aa586b5b30
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 108 - 0
Runtime/SelectableObjects/SelectionActionsView.cs

@@ -0,0 +1,108 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using KairoEngine.UI;
+using KairoEngine.UI.InteractionHandler;
+using KairoEngine.UI.Tooltips;
+
+namespace KairoEngine.GameTools.Selectables
+{
+    /// <summary>
+    /// A UI component that shows the actions for a given selected object or objects. 
+    /// </summary>
+    public class SelectionActionsView : MonoBehaviour, IUiSystemElement, IClickHandler
+    {
+        public bool hideWhenEmpty = true;
+        public SelectableObjectTool selectableObjectTool;
+        public GameObject panel;
+        public RectTransform container;
+        public GameObject actionButtonPrefab;
+
+        private List<SelectableObjectAction> actions = new List<SelectableObjectAction>();
+        private List<GameObject> buttons = new List<GameObject>();
+        private bool hidden = false;
+
+        private void Start()
+        {
+            if(actionButtonPrefab == null) Debug.LogError("Missing Action Button Prefab in SelectionActionsView", this.gameObject);
+            if(container == null) Debug.LogError("Missing container in SelectionActionsView", this.gameObject);   
+            UiManager.RegisterElement("SelectionActions", this, this.transform, true);
+            if(hideWhenEmpty) panel.SetActive(false);
+        }
+
+        private void Update()
+        {
+            if(selectableObjectTool.ActionListChanged())
+            {
+                actions = selectableObjectTool.GetActions();
+                UpdateActionButtons();
+            }
+            if(!hidden)
+            {
+                if(actions.Count == 0 && hideWhenEmpty) panel.SetActive(false);
+                else panel.SetActive(true);
+            }
+            else panel.SetActive(false);
+        }
+
+        public void Hide()
+        {
+            hidden = true;
+            panel.SetActive(false);
+        }
+
+        public bool IsVisible()
+        {
+            return panel.activeSelf;
+        }
+
+        public void Show()
+        {
+            hidden = false;
+            panel.SetActive(true);
+        }
+
+        private void UpdateActionButtons()
+        {
+            for (int i = 0; i < buttons.Count; i++)
+            {
+                Destroy(buttons[i].gameObject);
+            }
+            buttons = new List<GameObject>();
+            if(actionButtonPrefab == null || container == null) return;
+            for (int i = 0; i < actions.Count; i++)
+            {
+                var obj = Instantiate(actionButtonPrefab, container);
+                buttons.Add(obj);
+                ClickHandler handler = obj.GetComponent<ClickHandler>();
+                if(handler != null)
+                {
+                    handler.title = actions[i].title;
+                    handler.receiver = this;
+                }
+                ButtonData buttonData = obj.GetComponent<ButtonData>();
+                if(buttonData != null) buttonData.Setup(actions[i].title, actions[i].icon);
+                TooltipTrigger tooltip = obj.GetComponent<TooltipTrigger>();
+                if(tooltip != null) 
+                {
+                    tooltip.header = actions[i].title;
+                    tooltip.content = actions[i].description;
+                }
+            }
+            
+        }
+
+        public void OnClick(string title)
+        {
+            for (int i = 0; i < actions.Count; i++)
+            {
+                if(actions[i].title == title) 
+                {
+                    selectableObjectTool.ExecuteAction(actions[i]);
+                    return;
+                }
+            }
+        }
+    }
+}
+

+ 11 - 0
Runtime/SelectableObjects/SelectionActionsView.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b16495536d883e84982634c224cbd4f0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 0
Runtime/SelectableObjects/SelectionView.cs

@@ -0,0 +1,14 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace KairoEngine.GameTools.Selectables
+{
+    /// <summary>
+    /// The SelectionView is a UI component that shows the current selected object or objects.
+    /// </summary>
+    public class SelectionView : MonoBehaviour
+    {
+    
+    }
+}

+ 11 - 0
Runtime/SelectableObjects/SelectionView.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f9556635601a083428241beebeeb2b18
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 19 - 0
package.json

@@ -0,0 +1,19 @@
+{
+    "name": "at.kairoscope.kairoengine.game-tools",
+    "displayName": "KairoEngine Game Tools",
+    "version": "0.1.1",
+    "unity": "2020.3",
+    "description": "Kairoengine game tools library.",
+    "dependencies": {
+        "at.kairoscope.thirdparty.sirenix":"1.0.0",
+        "at.kairoscope.thirdparty.easy-performant-outline":"1.0.0",
+        "at.kairoscope.kairoengine.core":"0.1.6",
+        "at.kairoscope.kairoengine.ui":"0.1.2",
+        "at.kairoscope.kairoengine.stockpiles":"0.1.1"
+    },
+    "repository": {
+      "type": "git",
+      "url": "https://git.kairoscope.net/kairoengine/game-tools.git"
+    },
+    "author": "Kairoscope"
+  }