├── .gitignore
├── Assets
└── Live2D
│ └── Cubism
│ └── Viewer
│ ├── CubismViewer.cs
│ ├── CubismViewerConfig.cs
│ ├── CubismViewerIo.cs
│ ├── CubismViewerKeyboardHotkey.cs
│ ├── CubismViewerMouseButtonHotkey.cs
│ ├── CubismViewerMouseScrollHotkey.cs
│ ├── Gems
│ ├── Animating
│ │ └── SimpleAnimator.cs
│ ├── CameraControls.cs
│ └── Theming
│ │ ├── TwoColorTheme.cs
│ │ └── TwoColorThemer.cs
│ ├── ICubismViewerHotkey.cs
│ └── Plugins
│ └── System.Windows.Forms.txt
└── Readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.*
2 | [Ll]ibrary
3 | [Tt]emp
4 | !Assets/Live2D/Cubism/Viewer/**/*.cs
5 | !Assets/Live2D/Cubism/Viewer/**/*.txt
6 | !.gitignore
7 | !Readme.md
8 | Assets/**/*.md
9 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/CubismViewer.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using Live2D.Cubism.Core;
10 | using Live2D.Cubism.Framework.Json;
11 | using Live2D.Cubism.Rendering;
12 | using System.Windows.Forms;
13 | using UnityEngine;
14 |
15 |
16 | using EventSystem = UnityEngine.EventSystems.EventSystem;
17 | using Screen = UnityEngine.Screen;
18 |
19 |
20 | namespace Live2D.Cubism.Viewer
21 | {
22 | ///
23 | /// Unity-based viewer.
24 | ///
25 | public sealed class CubismViewer : MonoBehaviour
26 | {
27 | #region Events
28 |
29 | ///
30 | /// Handles model load events.
31 | ///
32 | /// Event source.
33 | /// New model.
34 | public delegate void NewModelHandler(CubismViewer sender, CubismModel model);
35 |
36 | ///
37 | /// Handles non-model JSON file drops.
38 | ///
39 | /// Events source.
40 | /// Absolute path to dropped file.
41 | public delegate void FileDropHandler(CubismViewer sender, string absolutePath);
42 |
43 |
44 | ///
45 | /// Called when new model loaded.
46 | ///
47 | public event NewModelHandler OnNewModel;
48 |
49 | ///
50 | /// Called on file drop.
51 | ///
52 | public event FileDropHandler OnFileDrop;
53 |
54 | #endregion
55 |
56 | ///
57 | /// backing field.
58 | ///
59 | [SerializeField]
60 | private Camera _camera;
61 |
62 | ///
63 | /// Viewer camera.
64 | ///
65 | public Camera Camera
66 | {
67 | get { return _camera; }
68 | }
69 |
70 | ///
71 | /// Model JSON of current model.
72 | ///
73 | public CubismModel3Json ModelJson { get; set; }
74 |
75 | ///
76 | /// Current model.
77 | ///
78 | public CubismModel Model { get; set; }
79 |
80 | ///
81 | /// File dialog.
82 | ///
83 | private OpenFileDialog FileDialog { get; set; }
84 |
85 | ///
86 | /// Config.
87 | ///
88 | private CubismViewerConfig Config { get; set; }
89 |
90 |
91 | ///
92 | /// Shows dialog for opening files.
93 | ///
94 | public void ShowFileDialog()
95 | {
96 | // HACK Deselect active UI element.
97 | EventSystem.current.SetSelectedGameObject(null);
98 |
99 |
100 | // Pre-filter for motions in case a model is loaded.
101 | if (Model != null)
102 | {
103 | FileDialog.FilterIndex = 2;
104 | }
105 |
106 |
107 | // Return unless a file was selected.
108 | if (FileDialog.ShowDialog() != DialogResult.OK)
109 | {
110 | return;
111 | }
112 |
113 |
114 | var absoluteFilePath = FileDialog.FileName;
115 |
116 |
117 | // Store path.
118 | Config.LastFileDialogPath = absoluteFilePath;
119 |
120 |
121 | // Handle model JSON files.
122 | if (absoluteFilePath.EndsWith(".model3.json"))
123 | {
124 | var lastModel = Model;
125 |
126 |
127 | // Load model.
128 | ModelJson = CubismModel3Json.LoadAtPath(absoluteFilePath, CubismViewerIo.LoadAsset);
129 | Model = ModelJson.ToModel();
130 |
131 |
132 | // Trigger event.
133 | if (OnNewModel != null)
134 | {
135 | OnNewModel(this, Model);
136 | }
137 |
138 |
139 | // Remove previous model.
140 | if (lastModel != null)
141 | {
142 | Destroy(lastModel.gameObject);
143 | }
144 |
145 |
146 | // Guess best zoom and position.
147 | // TODO Improve if necessary.
148 | var modelBounds = Model
149 | .GetComponent()
150 | .Renderers
151 | .GetMeshRendererBounds();
152 |
153 |
154 | Camera.transform.position = new Vector3(0f, 0f, -10f);
155 | Camera.orthographicSize = modelBounds.extents.y * 1.1f;
156 |
157 |
158 | return;
159 | }
160 |
161 |
162 | // Trigger event for other files.
163 | if (OnFileDrop != null)
164 | {
165 | OnFileDrop(this, absoluteFilePath);
166 | }
167 | }
168 |
169 | #region Unity Event Handling
170 |
171 | ///
172 | /// Called by Unity. Initializes viewer.
173 | ///
174 | private void Awake()
175 | {
176 | // Load config.
177 | Config = CubismViewerIo.LoadConfig();
178 |
179 |
180 | // Initialize screen size.
181 | Screen.SetResolution(Config.ScreenWidth, Config.ScreenHeight, false);
182 |
183 |
184 | // Initialize file dialog.
185 | FileDialog = new OpenFileDialog();
186 |
187 | if (!string.IsNullOrEmpty(Config.LastFileDialogPath))
188 | {
189 | FileDialog.InitialDirectory = CubismViewerIo.GetDirectoryName(Config.LastFileDialogPath);
190 | }
191 |
192 | FileDialog.Filter = "Models (*.model3.json)|*.model3.json|Motions (*.motion3.json)|*.motion3.json|Others (*.*)|*.*";
193 | FileDialog.FilterIndex = 1;
194 | FileDialog.RestoreDirectory = true;
195 | }
196 |
197 |
198 | ///
199 | /// Called by Unity. Stores config.
200 | ///
201 | private void OnDestroy()
202 | {
203 | Config.ScreenWidth = Screen.width;
204 | Config.ScreenHeight = Screen.height;
205 |
206 |
207 | CubismViewerIo.SaveConfig(Config);
208 | }
209 |
210 | #endregion
211 | }
212 | }
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/CubismViewerConfig.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using System;
10 | using UnityEngine;
11 |
12 |
13 | namespace Live2D.Cubism.Viewer
14 | {
15 | ///
16 | /// Viewer config file.
17 | ///
18 | [Serializable]
19 | public class CubismViewerConfig
20 | {
21 | ///
22 | /// Screen width.
23 | ///
24 | [SerializeField]
25 | public int ScreenWidth = 540;
26 |
27 | ///
28 | /// Screen height.
29 | ///
30 | [SerializeField]
31 | public int ScreenHeight = 720;
32 |
33 | ///
34 | /// Last path gotten via file dialog.
35 | ///
36 | [SerializeField]
37 | public string LastFileDialogPath;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/CubismViewerIo.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using System;
10 | using System.IO;
11 | using UnityEngine;
12 |
13 |
14 | namespace Live2D.Cubism.Viewer
15 | {
16 | ///
17 | /// IO helpers.
18 | ///
19 | public static class CubismViewerIo
20 | {
21 | ///
22 | /// Gets file name.
23 | ///
24 | /// Path to query against.
25 | /// File name.
26 | public static string GetFileName(string path)
27 | {
28 | return Path.GetFileName(path);
29 | }
30 |
31 | ///
32 | /// Gets directory name.
33 | ///
34 | /// Path to query against.
35 | /// Directory name.
36 | public static string GetDirectoryName(string path)
37 | {
38 | return Path.GetDirectoryName(path);
39 | }
40 |
41 |
42 | ///
43 | /// Loads asset.
44 | ///
45 | /// Asset type.
46 | /// Path to asset.
47 | /// The asset on success; otherwise.
48 | public static T LoadAsset(string absolutePath) where T : class
49 | {
50 | return LoadAsset(typeof(T), absolutePath) as T;
51 | }
52 |
53 | ///
54 | /// Loads asset.
55 | ///
56 | /// Asset type.
57 | /// Path to asset.
58 | /// The asset on success; otherwise.
59 | public static object LoadAsset(Type assetType, string absolutePath)
60 | {
61 | if (assetType == typeof(byte[]))
62 | {
63 | return File.ReadAllBytes(absolutePath);
64 | }
65 | else if (assetType == typeof(string))
66 | {
67 | return File.ReadAllText(absolutePath);
68 | }
69 | else if (assetType == typeof(Texture2D))
70 | {
71 | var texture = new Texture2D(1, 1);
72 |
73 |
74 | texture.LoadImage(File.ReadAllBytes(absolutePath));
75 |
76 |
77 | return texture;
78 | }
79 |
80 |
81 | // Fail hard.
82 | throw new NotSupportedException();
83 | }
84 |
85 |
86 | ///
87 | /// Loads config for given type.
88 | ///
89 | /// Type to querey against
90 | /// Config.
91 | // HACK The whole thing is a hack for the lazy...
92 | public static T LoadConfig() where T : class, new()
93 | {
94 | // Always return new config in editor.
95 | if (Application.isEditor)
96 | {
97 | return new T();
98 | }
99 |
100 |
101 | try
102 | {
103 | var serializedConfig = File.ReadAllText(Path.Combine(Application.persistentDataPath, typeof(T).Name + ".json"));
104 |
105 |
106 | return JsonUtility.FromJson(serializedConfig);
107 | }
108 | catch
109 | {
110 | return new T();
111 | }
112 | }
113 |
114 | ///
115 | /// Saves config for given type.
116 | ///
117 | /// Type to querey against
118 | /// Config.
119 | // HACK The whole thing is a hack for the lazy...
120 | public static void SaveConfig(T config) where T : class
121 | {
122 | // Never save in editor.
123 | if (Application.isEditor)
124 | {
125 | return;
126 | }
127 |
128 |
129 | var serializedConfig = JsonUtility.ToJson(config);
130 |
131 |
132 | if (string.IsNullOrEmpty(serializedConfig))
133 | {
134 | return;
135 | }
136 |
137 |
138 | File.WriteAllText(Path.Combine(Application.persistentDataPath, typeof(T).Name + ".json"), serializedConfig);
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/CubismViewerKeyboardHotkey.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using System;
10 | using UnityEngine;
11 |
12 |
13 | namespace Live2D.Cubism.Viewer
14 | {
15 | ///
16 | /// Keyobard hotkey.
17 | ///
18 | [Serializable]
19 | public struct CubismViewerKeyboardHotkey: ICubismViewerHotkey
20 | {
21 | ///
22 | /// Auxuliary condition.
23 | ///
24 | [SerializeField]
25 | public KeyCode Modifier;
26 |
27 | ///
28 | /// Primary condition.
29 | ///
30 | [SerializeField]
31 | public KeyCode Key;
32 |
33 |
34 | ///
35 | /// Evaluates hotkey.
36 | ///
37 | /// if hotkey pressed; otherwise.
38 | public bool Evaluate()
39 | {
40 | if (Modifier != KeyCode.None && !Input.GetKey(Modifier))
41 | {
42 | return false;
43 | }
44 |
45 | if (Key != KeyCode.None && !Input.GetKey(Key))
46 | {
47 | return false;
48 | }
49 |
50 |
51 | return true;
52 | }
53 |
54 | ///
55 | /// Evaluates if hotkey just pressed.
56 | ///
57 | /// if hotkey pressed; otherwise.
58 | public bool EvaluateJust()
59 | {
60 | if (Modifier != KeyCode.None && !Input.GetKey(Modifier))
61 | {
62 | return false;
63 | }
64 |
65 | if (!Input.GetKeyDown(Key))
66 | {
67 | return false;
68 | }
69 |
70 |
71 | return true;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/CubismViewerMouseButtonHotkey.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using System;
10 | using UnityEngine;
11 |
12 |
13 | namespace Live2D.Cubism.Viewer
14 | {
15 | ///
16 | /// Keyobard hotkey.
17 | ///
18 | [Serializable]
19 | public struct CubismViewerMouseButtonHotkey : ICubismViewerHotkey
20 | {
21 | ///
22 | /// Key condition.
23 | ///
24 | [SerializeField]
25 | public KeyCode Modifier;
26 |
27 | ///
28 | /// Button condition.
29 | ///
30 | [SerializeField]
31 | public int Button;
32 |
33 |
34 | ///
35 | /// Evaluates hotkey.
36 | ///
37 | /// if hotkey pressed; otherwise.
38 | public bool Evaluate()
39 | {
40 | if (Modifier != KeyCode.None && !Input.GetKey(Modifier))
41 | {
42 | return false;
43 | }
44 |
45 |
46 | return Input.GetMouseButton(Button);
47 | }
48 |
49 | ///
50 | /// Evaluates if hotkey just pressed.
51 | ///
52 | /// if hotkey pressed; otherwise.
53 | public bool EvaluateJust()
54 | {
55 | if (Modifier != KeyCode.None && !Input.GetKey(Modifier))
56 | {
57 | return false;
58 | }
59 |
60 |
61 | return Input.GetMouseButtonDown(Button);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/CubismViewerMouseScrollHotkey.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using System;
10 | using UnityEngine;
11 |
12 |
13 | namespace Live2D.Cubism.Viewer
14 | {
15 | ///
16 | /// Keyobard hotkey.
17 | ///
18 | [Serializable]
19 | public struct CubismViewerMouseScrollHotkey : ICubismViewerHotkey
20 | {
21 | ///
22 | /// Key condition.
23 | ///
24 | [SerializeField]
25 | public KeyCode Modifier;
26 |
27 |
28 | ///
29 | /// Evaluates hotkey.
30 | ///
31 | /// if hotkey pressed; otherwise.
32 | public bool Evaluate()
33 | {
34 | if (Modifier != KeyCode.None && !Input.GetKey(Modifier))
35 | {
36 | return false;
37 | }
38 |
39 |
40 | return Input.mouseScrollDelta != Vector2.zero;
41 | }
42 |
43 | ///
44 | /// Evaluates if hotkey just pressed.
45 | ///
46 | /// if hotkey pressed; otherwise.
47 | public bool EvaluateJust()
48 | {
49 | return Evaluate();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/Gems/Animating/SimpleAnimator.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using Live2D.Cubism.Framework.Json;
10 | using UnityEngine;
11 |
12 |
13 | namespace Live2D.Cubism.Viewer.Gems.Animating
14 | {
15 | ///
16 | /// Loops the last animation dropped.
17 | ///
18 | // TODO Clean up clips as necessary
19 | public sealed class SimpleAnimator : MonoBehaviour
20 | {
21 | ///
22 | /// Called by Unity. Registers handler.
23 | ///
24 | private void Start()
25 | {
26 | var viewer = GetComponent();
27 |
28 |
29 | // Fail silently in release.
30 | if (viewer == null)
31 | {
32 | Debug.LogWarning("Not attached to viewer!");
33 |
34 |
35 | return;
36 | }
37 |
38 |
39 | // Register event handler.
40 | viewer.OnFileDrop += HandleFileDrop;
41 | }
42 |
43 | #region CubismViewer Event Handling
44 |
45 | ///
46 | /// Handles file drops.
47 | ///
48 | /// Event source.
49 | /// Absolute path of dropped file.
50 | private void HandleFileDrop(CubismViewer sender, string absolutePath)
51 | {
52 | // Skip non-motion files.
53 | if (!absolutePath.EndsWith("motion3.json"))
54 | {
55 | return;
56 | }
57 |
58 |
59 | var model = sender.Model;
60 |
61 |
62 | // Make sure animation component is attached to model.
63 | var animator = model.GetComponent();
64 |
65 |
66 | if (animator == null)
67 | {
68 | animator = model.gameObject.AddComponent();
69 | }
70 |
71 |
72 | // Deserialize animation.
73 | var model3Json = CubismMotion3Json.LoadFrom(CubismViewerIo.LoadAsset(absolutePath));
74 | var clipName = CubismViewerIo.GetFileName(absolutePath);
75 | var clip = model3Json.ToAnimationClip();
76 | clip.wrapMode = WrapMode.Loop;
77 | clip.legacy = true;
78 |
79 |
80 | // Play animation.
81 | animator.AddClip(clip, clipName);
82 | animator.Play(clipName);
83 | }
84 |
85 | #endregion
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/Gems/CameraControls.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using UnityEngine;
10 |
11 |
12 | namespace Live2D.Cubism.Viewer.Gems
13 | {
14 | ///
15 | /// Controls .
16 | ///
17 | public sealed class CameraControls : MonoBehaviour
18 | {
19 | ///
20 | /// Hotkey for moving camera.
21 | ///
22 | [SerializeField]
23 | CubismViewerMouseButtonHotkey MoveHotkey = new CubismViewerMouseButtonHotkey
24 | {
25 | Modifier = KeyCode.LeftControl,
26 | Button = 0
27 | };
28 |
29 | ///
30 | /// Scale to apply to mouse movement on move.
31 | ///
32 | [SerializeField, Range(-1f, 1f)]
33 | float MoveScale = 1.0f;
34 |
35 | ///
36 | /// Hotkey for zooming in.
37 | ///
38 | [SerializeField]
39 | CubismViewerMouseScrollHotkey ZoomHotkey = new CubismViewerMouseScrollHotkey
40 | {
41 | Modifier = KeyCode.LeftAlt
42 | };
43 |
44 | ///
45 | /// Scale to apply to mouse movement on zoom.
46 | ///
47 | [SerializeField, Range(-10f, 10f)]
48 | float ZoomScale = -5f;
49 |
50 | ///
51 | /// Maximum zoom in value.
52 | ///
53 | [SerializeField, Range(0.1f, 10f)]
54 | float ZoomInLimit = 0.1f;
55 |
56 |
57 | ///
58 | /// Target camera.
59 | ///
60 | private Camera Camera { get; set; }
61 |
62 | ///
63 | /// Last mouse position to compute mouse delta.
64 | ///
65 | private Vector3 LastMousePosition { get; set; }
66 |
67 | #region Unity Event Handling
68 |
69 | ///
70 | /// Called by Unity. Initializes instance.
71 | ///
72 | private void Start()
73 | {
74 | var viewer = GetComponent();
75 |
76 |
77 | // Fail silently in release.
78 | if (viewer == null)
79 | {
80 | Debug.LogWarning("Not attached to viewer!");
81 |
82 |
83 | return;
84 | }
85 |
86 |
87 | Camera = viewer.Camera;
88 | }
89 |
90 | ///
91 | /// Called by Unity. Updates controls.
92 | ///
93 | private void Update()
94 | {
95 | // Return if nothing to control.
96 | if (Camera == null)
97 | {
98 | return;
99 | }
100 |
101 |
102 | // Handle move.
103 | if (MoveHotkey.Evaluate())
104 | {
105 | var position = Camera.transform.position;
106 |
107 |
108 | position += ((LastMousePosition - Input.mousePosition) * Time.deltaTime * MoveScale);
109 |
110 |
111 | Camera.transform.position = position;
112 | }
113 |
114 |
115 | // Handle zoom.
116 | else if (ZoomHotkey.Evaluate())
117 | {
118 | var size = Camera.orthographicSize;
119 |
120 |
121 | size += (Input.mouseScrollDelta.y * Time.deltaTime * ZoomScale);
122 |
123 |
124 | // Apply limit.
125 | if (size < ZoomInLimit)
126 | {
127 | size = ZoomInLimit;
128 | }
129 |
130 |
131 | Camera.orthographicSize = size;
132 | }
133 |
134 |
135 | // Keep track of mouse position.
136 | LastMousePosition = Input.mousePosition;
137 | }
138 |
139 | #endregion
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/Gems/Theming/TwoColorTheme.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using System;
10 | using UnityEngine;
11 |
12 |
13 | namespace Live2D.Cubism.Viewer.Gems.Theming
14 | {
15 | ///
16 | /// 2-color theme
17 | ///
18 | [Serializable]
19 | public struct TwoColorTheme
20 | {
21 | ///
22 | /// Primary color.
23 | ///
24 | ///
25 | /// This color will be used for the background, too.
26 | ///
27 | public Color Primary;
28 |
29 | ///
30 | /// Secondary color.
31 | ///
32 | public Color Secondary;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/Gems/Theming/TwoColorThemer.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | using UnityEngine;
10 |
11 |
12 | namespace Live2D.Cubism.Viewer.Gems.Theming
13 | {
14 | ///
15 | /// 2-color themer.
16 | ///
17 | public sealed class TwoColorThemer : MonoBehaviour
18 | {
19 | ///
20 | /// Hotkey for triggering theme switches.
21 | ///
22 | [SerializeField]
23 | CubismViewerKeyboardHotkey NextThemeHotkey = new CubismViewerKeyboardHotkey
24 | {
25 | Modifier = KeyCode.LeftControl,
26 | Key = KeyCode.T
27 | };
28 |
29 | ///
30 | /// Themes.
31 | ///
32 | [SerializeField]
33 | public TwoColorTheme[] Themes =
34 | {
35 | new TwoColorTheme
36 | {
37 | Primary = Color.white,
38 | Secondary = Color.black
39 | }
40 | };
41 |
42 | ///
43 | /// Primary color UI elements.
44 | ///
45 | [SerializeField]
46 | public UnityEngine.UI.Graphic[] PrimaryColorElements;
47 |
48 | ///
49 | /// Secondary color UI elements.
50 | ///
51 | [SerializeField]
52 | public UnityEngine.UI.Graphic[] SecondaryColorElements;
53 |
54 |
55 | ///
56 | /// Currently active theme.
57 | ///
58 | private int ActiveTheme { get; set; }
59 |
60 |
61 | ///
62 | /// Switches to next scene.
63 | ///
64 | private void NextTheme()
65 | {
66 | ++ActiveTheme;
67 |
68 |
69 | if (ActiveTheme >= Themes.Length)
70 | {
71 | ActiveTheme = 0;
72 | }
73 |
74 |
75 | // Try update camera.
76 | var viewer = GetComponent();
77 |
78 |
79 | if (viewer != null)
80 | {
81 | viewer.Camera.backgroundColor = Themes[ActiveTheme].Primary;
82 | }
83 |
84 |
85 | // Update primary color elements.
86 | if (PrimaryColorElements != null)
87 | {
88 | for (var e = 0; e < PrimaryColorElements.Length; ++e)
89 | {
90 | PrimaryColorElements[e].color = Themes[ActiveTheme].Primary;
91 | }
92 | }
93 |
94 |
95 | // Update secondary color elements.
96 | if (SecondaryColorElements != null)
97 | {
98 | for (var e = 0; e < SecondaryColorElements.Length; ++e)
99 | {
100 | SecondaryColorElements[e].color = Themes[ActiveTheme].Secondary;
101 | }
102 | }
103 | }
104 |
105 | #region Unity Event Handling
106 |
107 | ///
108 | /// Called by Unity. Initializes themer.
109 | ///
110 | private void Start()
111 | {
112 | ActiveTheme = -1;
113 |
114 |
115 | NextTheme();
116 | }
117 |
118 | ///
119 | /// Called by Unity. Handles hotkeys.
120 | ///
121 | private void Update()
122 | {
123 | if (NextThemeHotkey.EvaluateJust())
124 | {
125 | NextTheme();
126 | }
127 | }
128 |
129 | #endregion
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/ICubismViewerHotkey.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright(c) Live2D Inc. All rights reserved.
3 | *
4 | * Use of this source code is governed by the Live2D Open Software license
5 | * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
6 | */
7 |
8 |
9 | namespace Live2D.Cubism.Viewer
10 | {
11 | ///
12 | /// Common hotkey interface.
13 | ///
14 | public interface ICubismViewerHotkey
15 | {
16 | ///
17 | /// Evaluates hotkey.
18 | ///
19 | /// if hotkey pressed; otherwise.
20 | bool Evaluate();
21 |
22 | ///
23 | /// Evaluates if hotkey just pressed.
24 | ///
25 | /// if hotkey pressed; otherwise.
26 | bool EvaluateJust();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Assets/Live2D/Cubism/Viewer/Plugins/System.Windows.Forms.txt:
--------------------------------------------------------------------------------
1 | Make sure to copy the Mono 'System.Windows.Forms.dll' into this directory.
2 | A good place to start your search might be '/Editor/Data/Mono/lib/mono/2.0/'.
3 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Cubism DIY Viewer
2 |
3 | Welcome to the *Unity*-based Cubism 3 do-it-yourself viewer. Came here looking for the official Live2D homepage?
4 | Go [here](http://www.live2d.com/products/cubism3).
5 |
6 |
7 | ## Do-it-yourself!?
8 |
9 | Instead of providing a complete solution like the 2.x viewers did,
10 | this project aims to serve as a starting point and to provide common functionality
11 | for making it easy to create a viewer tailored to your needs.
12 |
13 | Want to preview models easily without access to *Unity*? Create a viewer with built-in functionality.
14 |
15 | Need model related data in your app that you can't create in Cubism itself?
16 | Customize the viewer to create just the data you need.
17 |
18 |
19 | ## Design
20 |
21 | The viewer itself basically is a single `MonoBehaviour`.
22 | You customize the viewer by attaching other `MonoBehaviour`s to it.
23 | As *Plugin* is a somewhat reserved term in *Unity* (and because I like *Ruby*),
24 | let's call such custom behaviours *gem*s.
25 |
26 |
27 | ## Built-in *Gem*s
28 |
29 | This project contains a few *gem*s to get you started.
30 |
31 |
32 | ### `CameraControls`
33 |
34 | This *gem* allows you to move the canvas and zoom-in.
35 | Hotkeys default to `Spacebar + Left Mouse Button + Drag` for navigating the canvas, and
36 | `Mouse Wheel Scroll Up/Down` for zooming.
37 |
38 |
39 | ### `SimpleAnimator`
40 |
41 | This *gem* allows you to play back a single animation at a time.
42 |
43 |
44 | ### `TwoColorThemer`
45 |
46 | This *gem* allows you to quickly theme the viewer using a 2 color theme.
47 | The background color will be set to the primary color of the theme.
48 | You can register any number of UI elements you want themed, too, through the *Inspector*.
49 | Hotkey defaults to `Left Control + T` for switching between themes.
50 |
51 |
52 | ## User *Gem*s
53 |
54 | - [DenchiSoft/CubismViewerGems](https://github.com/DenchiSoft/CubismViewerGems)
55 |
56 |
57 | ## Getting Started
58 |
59 | First, you have to download a few files and get them into a *Unity* project:
60 |
61 | 1. Download the latest [SDK](https://live2d.github.io/#unity) and import it into your project.
62 | 1. Make sure to restart *Unity*.
63 | 1. Download the latest [Components for Unity](https://github.com/Live2D/CubismUnityComponents/tree/develop) into your project. Overwrite any previous SDK files with the new ones.
64 | 1. Download/Clone this repository into your project.
65 | 1. Copy the *Mono* `System.Windows.Forms.dll` into your project. (Check out `./Assets/Live2D/Cubism/Viewer/Plugins/System.Windows.Forms.txt` for instructions).
66 | 1. Set `API Compability Level` to *.NET 2.0* (default is *.NET 2.0 Subset*) in the *Player Settings*.
67 |
68 | From here things are easy because you do the rest completely inside the *Unity Editor*:
69 |
70 | 6. Create an empty *GameObject* and add the `CubismViewer` component to it.
71 | 1. Assign the `Main Camera` in your scene to the `CubismViewer` through the *Inspector*.
72 | 1. Create an UI button and add the `CubismViewer.ShowFileDialog` method of the `CubismViewer` object to `On Click ()`.
73 | 1. Hit play, click the UI button. A file dialog should open.
74 | 1. Select a `model3.json` file via the file dialog. The model should be displayed.
75 | 1. Add *gem*s to the `CubismViewer` object for additional functionality.
76 |
77 |
78 | ## Contributing
79 |
80 | Wrote a cool *gem*? We're looking forward to it.
81 | You can either submit its source code or a link (as Live2D Community or as pull requests).
82 |
83 | Besides that, there are many other ways to contribute to the project, too:
84 | logging bugs, submitting pull requests on this GitHub, and reporting issues and making suggestions at Live2D Community.
85 |
86 |
87 | ### Forking And Pull Requests
88 |
89 | We very appreciate your pull requests whether they bring fixes, improvements, or even new features.
90 | Note, however, that the wrapper is designed to be as lightweight and shallow as possible and
91 | should therefore only be subject to bug fixes and memory/performance improvements.
92 | To keep the main repository as clean as possible, create a personal fork and feature branches there as needed.
93 |
94 |
95 | ### Bugs
96 |
97 | We are regularly checking issue-reports and feature requests at Live2D Community.
98 | Before filing a bug report, please do a search in Live2D Community to see if the issue-report or feature request has already been posted.
99 | If you find your issue already exists, make relevant comments and add your reaction.
100 |
101 |
102 | ### Discussion Etiquette
103 |
104 | Please limit the discussion to English and keep it professional and things on topic.
105 |
106 |
107 | ## License
108 |
109 | If you plan on using this project or parts of it for non-personal or non-in-house use,
110 | make sure to read the [license](http://live2d.com/eula/live2d-open-software-license-agreement_en.html) carefully.
111 | Otherwise, you shouldn't have to worry to much as the license that applies to the source code in this project
112 | allows you to modify all sources without the need to submit any changes you made.
113 |
--------------------------------------------------------------------------------