open properties dialog if mapper hasn't opened it prior for this chart
fix memory copy bug when making new chart
This commit is contained in:
parent
e0c01488e4
commit
b8dc68cbae
|
|
@ -551,9 +551,9 @@ RectTransform:
|
||||||
m_Father: {fileID: 574002313}
|
m_Father: {fileID: 574002313}
|
||||||
m_RootOrder: 0
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 0, y: -21}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 32, y: 32}
|
m_SizeDelta: {x: 32, y: 32}
|
||||||
m_Pivot: {x: 0, y: 0.5}
|
m_Pivot: {x: 0, y: 0.5}
|
||||||
--- !u!114 &9435782
|
--- !u!114 &9435782
|
||||||
|
|
@ -4384,9 +4384,9 @@ RectTransform:
|
||||||
m_Father: {fileID: 539838476}
|
m_Father: {fileID: 539838476}
|
||||||
m_RootOrder: 0
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 32, y: -21}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 32, y: 32}
|
m_SizeDelta: {x: 32, y: 32}
|
||||||
m_Pivot: {x: 1, y: 0.5}
|
m_Pivot: {x: 1, y: 0.5}
|
||||||
--- !u!114 &121871281
|
--- !u!114 &121871281
|
||||||
|
|
@ -4608,9 +4608,9 @@ RectTransform:
|
||||||
m_Father: {fileID: 539838476}
|
m_Father: {fileID: 539838476}
|
||||||
m_RootOrder: 1
|
m_RootOrder: 1
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 72, y: -21}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 32, y: 32}
|
m_SizeDelta: {x: 32, y: 32}
|
||||||
m_Pivot: {x: 1, y: 0.5}
|
m_Pivot: {x: 1, y: 0.5}
|
||||||
--- !u!114 &129013734
|
--- !u!114 &129013734
|
||||||
|
|
@ -4744,9 +4744,9 @@ RectTransform:
|
||||||
m_Father: {fileID: 539838476}
|
m_Father: {fileID: 539838476}
|
||||||
m_RootOrder: 2
|
m_RootOrder: 2
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 112, y: -21}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 32, y: 32}
|
m_SizeDelta: {x: 32, y: 32}
|
||||||
m_Pivot: {x: 1, y: 0.5}
|
m_Pivot: {x: 1, y: 0.5}
|
||||||
--- !u!114 &151246938
|
--- !u!114 &151246938
|
||||||
|
|
@ -36540,6 +36540,11 @@ MonoBehaviour:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
dialog: {fileID: 1336470761}
|
dialog: {fileID: 1336470761}
|
||||||
tabsManager: {fileID: 1523610372}
|
tabsManager: {fileID: 1523610372}
|
||||||
|
returnIcon: {fileID: 21300000, guid: 348825b5c77b9d143961119fc008e631, type: 3}
|
||||||
|
returnColor: {r: 1, g: 0, b: 0, a: 1}
|
||||||
|
saveIcon: {fileID: 21300000, guid: 9ae7ecf2cc001d14595ec03e1d4d86a6, type: 3}
|
||||||
|
saveColor: {r: 1, g: 1, b: 1, a: 1}
|
||||||
|
returnButtonImage: {fileID: 1089381436}
|
||||||
containers:
|
containers:
|
||||||
- {fileID: 0}
|
- {fileID: 0}
|
||||||
- {fileID: 0}
|
- {fileID: 0}
|
||||||
|
|
@ -36761,9 +36766,9 @@ RectTransform:
|
||||||
m_Father: {fileID: 574002313}
|
m_Father: {fileID: 574002313}
|
||||||
m_RootOrder: 1
|
m_RootOrder: 1
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 40, y: -21}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 32, y: 32}
|
m_SizeDelta: {x: 32, y: 32}
|
||||||
m_Pivot: {x: 0, y: 0.5}
|
m_Pivot: {x: 0, y: 0.5}
|
||||||
--- !u!114 &1345846031
|
--- !u!114 &1345846031
|
||||||
|
|
@ -38133,6 +38138,8 @@ MonoBehaviour:
|
||||||
- {fileID: 1265865542}
|
- {fileID: 1265865542}
|
||||||
- {fileID: 1336470763}
|
- {fileID: 1336470763}
|
||||||
- {fileID: 1946344932}
|
- {fileID: 1946344932}
|
||||||
|
- {fileID: 992457124}
|
||||||
|
- {fileID: 1851635078}
|
||||||
- {fileID: 292323699}
|
- {fileID: 292323699}
|
||||||
tooltipText: {fileID: 1196204504}
|
tooltipText: {fileID: 1196204504}
|
||||||
fullscreen: 0
|
fullscreen: 0
|
||||||
|
|
@ -46417,9 +46424,9 @@ RectTransform:
|
||||||
m_Father: {fileID: 574002313}
|
m_Father: {fileID: 574002313}
|
||||||
m_RootOrder: 2
|
m_RootOrder: 2
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 1}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 1}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
m_AnchoredPosition: {x: 80, y: -21}
|
m_AnchoredPosition: {x: 0, y: 0}
|
||||||
m_SizeDelta: {x: 32, y: 32}
|
m_SizeDelta: {x: 32, y: 32}
|
||||||
m_Pivot: {x: 0, y: 0.5}
|
m_Pivot: {x: 0, y: 0.5}
|
||||||
--- !u!114 &1783491359
|
--- !u!114 &1783491359
|
||||||
|
|
|
||||||
|
|
@ -239,7 +239,7 @@ namespace HeavenStudio
|
||||||
Debug.Log("Creating new remix");
|
Debug.Log("Creating new remix");
|
||||||
AudioLoadDone = false;
|
AudioLoadDone = false;
|
||||||
Beatmap = new("1", "HeavenStudio");
|
Beatmap = new("1", "HeavenStudio");
|
||||||
Beatmap.data.properties = Minigames.propertiesModel;
|
Beatmap.data.properties = new(Minigames.propertiesModel);
|
||||||
Beatmap.AddNewTempoChange(0, 120f);
|
Beatmap.AddNewTempoChange(0, 120f);
|
||||||
Beatmap.AddNewVolumeChange(0, 100f);
|
Beatmap.AddNewVolumeChange(0, 100f);
|
||||||
Beatmap.data.offset = 0f;
|
Beatmap.data.offset = 0f;
|
||||||
|
|
|
||||||
|
|
@ -359,19 +359,36 @@ namespace HeavenStudio.Editor
|
||||||
|
|
||||||
public void SaveRemix(bool saveAs = true)
|
public void SaveRemix(bool saveAs = true)
|
||||||
{
|
{
|
||||||
if (saveAs == true)
|
Debug.Log(GameManager.instance.Beatmap["propertiesmodified"]);
|
||||||
|
if (!(bool)GameManager.instance.Beatmap["propertiesmodified"])
|
||||||
{
|
{
|
||||||
SaveRemixFilePanel();
|
foreach (var dialog in Dialogs)
|
||||||
|
{
|
||||||
|
if (dialog.GetType() == typeof(RemixPropertiesDialog))
|
||||||
|
{
|
||||||
|
GlobalGameManager.ShowErrorMessage("Set Remix Properties", "Set remix properties before saving.");
|
||||||
|
(dialog as RemixPropertiesDialog).SwitchPropertiesDialog();
|
||||||
|
(dialog as RemixPropertiesDialog).SetSaveOnClose(true, saveAs);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (currentRemixPath == string.Empty || currentRemixPath == null)
|
if (saveAs == true)
|
||||||
{
|
{
|
||||||
SaveRemixFilePanel();
|
SaveRemixFilePanel();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SaveRemixFile(currentRemixPath);
|
if (currentRemixPath == string.Empty || currentRemixPath == null)
|
||||||
|
{
|
||||||
|
SaveRemixFilePanel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SaveRemixFile(currentRemixPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
using HeavenStudio.Editor.Track;
|
using HeavenStudio.Editor.Track;
|
||||||
using Jukebox;
|
using Jukebox;
|
||||||
using Jukebox.Legacy;
|
using Jukebox.Legacy;
|
||||||
|
|
@ -14,6 +15,11 @@ namespace HeavenStudio.Editor
|
||||||
{
|
{
|
||||||
[Header("General References")]
|
[Header("General References")]
|
||||||
[SerializeField] TabsManager tabsManager;
|
[SerializeField] TabsManager tabsManager;
|
||||||
|
[SerializeField] Sprite returnIcon;
|
||||||
|
[SerializeField] Color returnColor;
|
||||||
|
[SerializeField] Sprite saveIcon;
|
||||||
|
[SerializeField] Color saveColor;
|
||||||
|
[SerializeField] Image returnButtonImage;
|
||||||
|
|
||||||
[Header("Containers")]
|
[Header("Containers")]
|
||||||
[SerializeField] ChartInfoProperties[] containers;
|
[SerializeField] ChartInfoProperties[] containers;
|
||||||
|
|
@ -38,6 +44,7 @@ namespace HeavenStudio.Editor
|
||||||
|
|
||||||
[NonSerialized] public RiqBeatmap chart;
|
[NonSerialized] public RiqBeatmap chart;
|
||||||
List<GameObject> tabContents;
|
List<GameObject> tabContents;
|
||||||
|
bool saveAfterClose = false, saveAs = false;
|
||||||
|
|
||||||
private void Start() { }
|
private void Start() { }
|
||||||
|
|
||||||
|
|
@ -52,6 +59,11 @@ namespace HeavenStudio.Editor
|
||||||
|
|
||||||
tabsManager.CleanTabs();
|
tabsManager.CleanTabs();
|
||||||
tabContents = null;
|
tabContents = null;
|
||||||
|
|
||||||
|
if (saveAfterClose)
|
||||||
|
{
|
||||||
|
Editor.instance.SaveRemix(saveAs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -63,6 +75,7 @@ namespace HeavenStudio.Editor
|
||||||
|
|
||||||
chart = GameManager.instance.Beatmap;
|
chart = GameManager.instance.Beatmap;
|
||||||
chart["propertiesmodified"] = true;
|
chart["propertiesmodified"] = true;
|
||||||
|
SetSaveOnClose(false);
|
||||||
|
|
||||||
tabContents = tabsManager.GenerateTabs(tabs);
|
tabContents = tabsManager.GenerateTabs(tabs);
|
||||||
foreach (var tab in tabContents)
|
foreach (var tab in tabContents)
|
||||||
|
|
@ -72,6 +85,14 @@ namespace HeavenStudio.Editor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetSaveOnClose(bool saveAfterClose, bool saveAs = false)
|
||||||
|
{
|
||||||
|
this.saveAfterClose = saveAfterClose;
|
||||||
|
this.saveAs = saveAs;
|
||||||
|
returnButtonImage.sprite = saveAfterClose ? saveIcon : returnIcon;
|
||||||
|
returnButtonImage.color = saveAfterClose ? saveColor : returnColor;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetupDialog(PropertyTag[] tags, ChartInfoProperties container)
|
public void SetupDialog(PropertyTag[] tags, ChartInfoProperties container)
|
||||||
{
|
{
|
||||||
chart = GameManager.instance.Beatmap;
|
chart = GameManager.instance.Beatmap;
|
||||||
|
|
|
||||||
|
|
@ -36,75 +36,75 @@ namespace HeavenStudio
|
||||||
RiqFileHandler.AudioConverter = JukeboxAudioConverter;
|
RiqFileHandler.AudioConverter = JukeboxAudioConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, object> propertiesModel = new()
|
readonly public static Dictionary<string, object> propertiesModel = new()
|
||||||
{
|
{
|
||||||
// mapper set properties? (future: use this to flash the button)
|
// mapper set properties? (future: use this to flash the button)
|
||||||
{"propertiesmodified", false},
|
{"propertiesmodified", false},
|
||||||
|
|
||||||
////// CATEGORY 1: SONG INFO
|
////// CATEGORY 1: SONG INFO
|
||||||
// general chart info
|
// general chart info
|
||||||
{"remixtitle", "New Remix"}, // chart name
|
{"remixtitle", "New Remix"}, // chart name
|
||||||
{"remixauthor", "Your Name"}, // charter's name
|
{"remixauthor", "Your Name"}, // charter's name
|
||||||
{"remixdesc", "Remix Description"}, // chart description
|
{"remixdesc", "Remix Description"}, // chart description
|
||||||
{"remixlevel", 1}, // chart difficulty (maybe offer a suggestion but still have the mapper determine it)
|
{"remixlevel", 1}, // chart difficulty (maybe offer a suggestion but still have the mapper determine it)
|
||||||
{"remixtempo", 120f}, // avg. chart tempo
|
{"remixtempo", 120f}, // avg. chart tempo
|
||||||
{"remixtags", ""}, // chart tags
|
{"remixtags", ""}, // chart tags
|
||||||
{"icontype", 0}, // chart icon (presets, custom - future)
|
{"icontype", 0}, // chart icon (presets, custom - future)
|
||||||
{"iconres", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Select/", "Icon")}, // custom icon location (future)
|
{"iconres", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Select/", "Icon")}, // custom icon location (future)
|
||||||
{"challengetype", 0}, // perfect challenge type
|
{"challengetype", 0}, // perfect challenge type
|
||||||
{"playstyle", RecommendedControlStyle.Any}, // recommended control style
|
{"playstyle", RecommendedControlStyle.Any}, // recommended control style
|
||||||
|
|
||||||
// chart song info
|
// chart song info
|
||||||
{"idolgenre", "Song Genre"}, // song genre
|
{"idolgenre", "Song Genre"}, // song genre
|
||||||
{"idolsong", "Song Name"}, // song name
|
{"idolsong", "Song Name"}, // song name
|
||||||
{"idolcredit", "Artist"}, // song artist
|
{"idolcredit", "Artist"}, // song artist
|
||||||
|
|
||||||
////// CATEGORY 2: PROLOGUE AND EPILOGUE
|
////// CATEGORY 2: PROLOGUE AND EPILOGUE
|
||||||
// chart prologue
|
// chart prologue
|
||||||
{"prologuetype", 0}, // prologue card animation (future)
|
{"prologuetype", 0}, // prologue card animation (future)
|
||||||
{"prologuecaption", "Remix"}, // prologue card sub-title (future)
|
{"prologuecaption", "Remix"}, // prologue card sub-title (future)
|
||||||
|
|
||||||
// chart results screen messages
|
// chart results screen messages
|
||||||
{"resultcaption", "Rhythm League Notes"}, // result screen header
|
{"resultcaption", "Rhythm League Notes"}, // result screen header
|
||||||
{"resultcommon_hi", "Good rhythm."}, // generic "Superb" message (one-liner)
|
{"resultcommon_hi", "Good rhythm."}, // generic "Superb" message (one-liner)
|
||||||
{"resultcommon_ok", "Eh. Passable."}, // generic "OK" message (one-liner)
|
{"resultcommon_ok", "Eh. Passable."}, // generic "OK" message (one-liner)
|
||||||
{"resultcommon_ng", "Try harder next time."}, // generic "Try Again" message (one-liner)
|
{"resultcommon_ng", "Try harder next time."}, // generic "Try Again" message (one-liner)
|
||||||
|
|
||||||
{"resultcat0_hi", "You show strong fundamentals."}, // "Superb" message for input category 0 "normal" (two-liner)
|
{"resultcat0_hi", "You show strong fundamentals."}, // "Superb" message for input category 0 "normal" (two-liner)
|
||||||
{"resultcat0_ng", "Work on your fundamentals."}, // "Try Again" message for input category 0 "normal" (two-liner)
|
{"resultcat0_ng", "Work on your fundamentals."}, // "Try Again" message for input category 0 "normal" (two-liner)
|
||||||
|
|
||||||
{"resultcat1_hi", "You kept the beat well."}, // "Superb" message for input category 1 "keep" (two-liner)
|
{"resultcat1_hi", "You kept the beat well."}, // "Superb" message for input category 1 "keep" (two-liner)
|
||||||
{"resultcat1_ng", "You had trouble keeping the beat."}, // "Try Again" message for input category 1 "keep" (two-liner)
|
{"resultcat1_ng", "You had trouble keeping the beat."}, // "Try Again" message for input category 1 "keep" (two-liner)
|
||||||
|
|
||||||
{"resultcat2_hi", "You had great aim."}, // "Superb" message for input category 2 "aim" (two-liner)
|
{"resultcat2_hi", "You had great aim."}, // "Superb" message for input category 2 "aim" (two-liner)
|
||||||
{"resultcat2_ng", "Your aim was a little shaky."}, // "Try Again" message for input category 2 "aim" (two-liner)
|
{"resultcat2_ng", "Your aim was a little shaky."}, // "Try Again" message for input category 2 "aim" (two-liner)
|
||||||
|
|
||||||
{"resultcat3_hi", "You followed the example well."}, // "Superb" message for input category 3 "repeat" (two-liner)
|
{"resultcat3_hi", "You followed the example well."}, // "Superb" message for input category 3 "repeat" (two-liner)
|
||||||
{"resultcat3_ng", "Next time, follow the example better."}, // "Try Again" message for input category 3 "repeat" (two-liner)
|
{"resultcat3_ng", "Next time, follow the example better."}, // "Try Again" message for input category 3 "repeat" (two-liner)
|
||||||
|
|
||||||
{"epilogue_hi", "Superb picture"}, // epilogue "Superb" message
|
{"epilogue_hi", "Superb picture"}, // epilogue "Superb" message
|
||||||
{"epilogue_ok", "OK picture"}, // epilogue "OK" message
|
{"epilogue_ok", "OK picture"}, // epilogue "OK" message
|
||||||
{"epilogue_ng", "Try Again picture"}, // epilogue "Try Again" message
|
{"epilogue_ng", "Try Again picture"}, // epilogue "Try Again" message
|
||||||
|
|
||||||
{"epilogue_hi_res", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Epilogue/", "Hi")}, // epilogue "Superb" image resource path
|
{"epilogue_hi_res", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Epilogue/", "Hi")}, // epilogue "Superb" image resource path
|
||||||
{"epilogue_ok_res", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Epilogue/", "Ok")}, // epilogue "OK" image resource path
|
{"epilogue_ok_res", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Epilogue/", "Ok")}, // epilogue "OK" image resource path
|
||||||
{"epilogue_ng_res", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Epilogue/", "Ng")}, // epilogue "Try Again" image resource path
|
{"epilogue_ng_res", new EntityTypes.Resource(EntityTypes.Resource.ResourceType.Image, "Images/Epilogue/", "Ng")}, // epilogue "Try Again" image resource path
|
||||||
};
|
};
|
||||||
|
|
||||||
static Dictionary<string, object> tempoChangeModel = new()
|
readonly static Dictionary<string, object> tempoChangeModel = new()
|
||||||
{
|
{
|
||||||
{"tempo", 120f},
|
{"tempo", 120f},
|
||||||
{"swing", 0f},
|
{"swing", 0f},
|
||||||
{"timeSignature", new Vector2(4, 4)},
|
{"timeSignature", new Vector2(4, 4)},
|
||||||
};
|
};
|
||||||
|
|
||||||
static Dictionary<string, object> volumeChangeModel = new()
|
readonly static Dictionary<string, object> volumeChangeModel = new()
|
||||||
{
|
{
|
||||||
{"volume", 1f},
|
{"volume", 1f},
|
||||||
{"fade", Util.EasingFunction.Ease.Instant},
|
{"fade", Util.EasingFunction.Ease.Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
static Dictionary<string, object> sectionMarkModel = new()
|
readonly static Dictionary<string, object> sectionMarkModel = new()
|
||||||
{
|
{
|
||||||
{"sectionName", ""},
|
{"sectionName", ""},
|
||||||
{"startPerfect", false},
|
{"startPerfect", false},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue