Compare commits
7 Commits
f7de2290cb
...
1a417c8bcf
Author | SHA1 | Date | |
---|---|---|---|
1a417c8bcf | |||
29a54f8e89 | |||
40ce9dcb81 | |||
b7ecc1e6b5 | |||
a6097ae400 | |||
03ea64b021 | |||
334ffbfa48 |
@ -52,7 +52,8 @@ void RefreshBlocks() {
|
|||||||
pos.z = blocks[i].CoordZ * 32 + 16;
|
pos.z = blocks[i].CoordZ * 32 + 16;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pos = Dev::GetOffsetVec3(blocks[i], 0x6c);
|
uint16 offset = Reflection::GetType("CGameCtnBlock").GetMember("Dir").Offset + 0x8;
|
||||||
|
pos = Dev::GetOffsetVec3(blocks[i], offset);
|
||||||
// center the coordinates in the middle of the block
|
// center the coordinates in the middle of the block
|
||||||
pos.x += 16;
|
pos.x += 16;
|
||||||
pos.y += 4;
|
pos.y += 4;
|
||||||
@ -173,8 +174,6 @@ void AddNewObject(const string &in objectname, int trigger, const string &in typ
|
|||||||
bool FocusCam(const string &in objectname) {
|
bool FocusCam(const string &in objectname) {
|
||||||
auto editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
auto editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||||
auto camera = editor.OrbitalCameraControl;
|
auto camera = editor.OrbitalCameraControl;
|
||||||
auto map = GetApp().RootMap;
|
|
||||||
|
|
||||||
|
|
||||||
if (camera !is null) {
|
if (camera !is null) {
|
||||||
int index = objectsindex.Find(objectname);
|
int index = objectsindex.Find(objectname);
|
||||||
@ -187,8 +186,11 @@ bool FocusCam(const string &in objectname) {
|
|||||||
|
|
||||||
camera.m_TargetedPosition = objects[index].positions[camerafocusindex];
|
camera.m_TargetedPosition = objects[index].positions[camerafocusindex];
|
||||||
// Workaround to update camera TargetedPosition
|
// Workaround to update camera TargetedPosition
|
||||||
|
auto m_ParamScrollZoomPowe = camera.m_ParamScrollZoomPower;
|
||||||
|
camera.m_ParamScrollZoomPower = 0;
|
||||||
editor.ButtonZoomInOnClick();
|
editor.ButtonZoomInOnClick();
|
||||||
editor.ButtonZoomOutOnClick();
|
camera.m_ParamScrollZoomPower = m_ParamScrollZoomPowe;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -3,5 +3,5 @@ name = "Blocks & Items Counter"
|
|||||||
author = "Beu"
|
author = "Beu"
|
||||||
category = "Map Editor"
|
category = "Map Editor"
|
||||||
siteid = 97
|
siteid = 97
|
||||||
version = "1.5"
|
version = "1.6"
|
||||||
blocks = [ "Plugin_Blocks&ItemsCounter" ]
|
blocks = [ "Plugin_Blocks&ItemsCounter" ]
|
||||||
|
9
DuplicateFinder/info.toml
Normal file
9
DuplicateFinder/info.toml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[meta]
|
||||||
|
name = "DuplicateFinder"
|
||||||
|
author = "Beu"
|
||||||
|
category = "Map Editor"
|
||||||
|
version = "1.1"
|
||||||
|
siteid = 220
|
||||||
|
|
||||||
|
[script]
|
||||||
|
timeout = 0
|
302
DuplicateFinder/main.as
Normal file
302
DuplicateFinder/main.as
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
class Objects { //Items or Blocks
|
||||||
|
string name;
|
||||||
|
string type;
|
||||||
|
int count;
|
||||||
|
vec3 position;
|
||||||
|
vec3 rotation;
|
||||||
|
Objects(string name, string type, vec3 pos, vec3 rot ) {
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.count = 2; // Object if added only if duplicate
|
||||||
|
this.position = pos;
|
||||||
|
this.rotation = rot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ESortColumn {
|
||||||
|
ItemName,
|
||||||
|
Count
|
||||||
|
}
|
||||||
|
|
||||||
|
const float pi = 3.14159265359;
|
||||||
|
|
||||||
|
bool include_default_blocks;
|
||||||
|
bool menu_visibility = false;
|
||||||
|
bool refreshobject;
|
||||||
|
|
||||||
|
bool sort_reverse;
|
||||||
|
bool forcesort;
|
||||||
|
string infotext;
|
||||||
|
|
||||||
|
array<Objects@> objects = {};
|
||||||
|
array<Objects@> sortableobjects = {};
|
||||||
|
array<string> objectsindex = {};
|
||||||
|
|
||||||
|
int totalobjects;
|
||||||
|
int computedobjects;
|
||||||
|
|
||||||
|
ESortColumn sortCol = ESortColumn(-1);
|
||||||
|
|
||||||
|
void Main() {
|
||||||
|
while (true) {
|
||||||
|
if (refreshobject) {
|
||||||
|
objects.Resize(0);
|
||||||
|
objectsindex.Resize(0);
|
||||||
|
sortableobjects.Resize(0);
|
||||||
|
RefreshBlocksAndItems();
|
||||||
|
sortableobjects = objects;
|
||||||
|
refreshobject = false;
|
||||||
|
}
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force to split the refresh functions to bypass the script execution delay on heavy maps
|
||||||
|
void RefreshBlocksAndItems() {
|
||||||
|
auto map = GetApp().RootMap;
|
||||||
|
dictionary singleobjectdico = {};
|
||||||
|
|
||||||
|
if (map !is null) {
|
||||||
|
totalobjects = map.Blocks.Length + map.AnchoredObjects.Length;
|
||||||
|
computedobjects = 0;
|
||||||
|
|
||||||
|
// Blocks
|
||||||
|
auto blocks = map.Blocks;
|
||||||
|
|
||||||
|
// Editor plugin API for GetVec3FromCoord function
|
||||||
|
auto pluginmaptype = cast<CGameEditorPluginMapMapType>(cast<CGameCtnEditorFree>(GetApp().Editor).PluginMapType);
|
||||||
|
|
||||||
|
for(uint i = 0; i < blocks.Length; i++) {
|
||||||
|
if (i % 1000 == 0) yield(); // to avoid timeout
|
||||||
|
computedobjects++;
|
||||||
|
|
||||||
|
string blockname;
|
||||||
|
blockname = blocks[i].BlockModel.IdName;
|
||||||
|
if (blockname.ToLower().SubStr(blockname.Length - 22, 22) == ".block.gbx_customblock") blockname = blockname.SubStr(0, blockname.Length - 12);
|
||||||
|
|
||||||
|
vec3 pos;
|
||||||
|
vec3 rot;
|
||||||
|
if (blocks[i].CoordX != 4294967295 && blocks[i].CoordZ != 4294967295) { // Not placed in free mapping
|
||||||
|
if (!include_default_blocks) continue;
|
||||||
|
if (pluginmaptype !is null) { // Editor plugin is available
|
||||||
|
pos = pluginmaptype.GetVec3FromCoord(blocks[i].Coord);
|
||||||
|
} else {
|
||||||
|
pos.x = blocks[i].CoordX * 32;
|
||||||
|
pos.y = (blocks[i].CoordY - 8) * 8;
|
||||||
|
pos.z = blocks[i].CoordZ * 32;
|
||||||
|
}
|
||||||
|
switch(blocks[i].BlockDir) {
|
||||||
|
case CGameCtnBlock::ECardinalDirections::East:
|
||||||
|
rot.x = 90;
|
||||||
|
break;
|
||||||
|
case CGameCtnBlock::ECardinalDirections::South:
|
||||||
|
rot.x = 180;
|
||||||
|
break;
|
||||||
|
case CGameCtnBlock::ECardinalDirections::West:
|
||||||
|
rot.x = 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
uint16 FreeBlockPosOffset = Reflection::GetType("CGameCtnBlock").GetMember("Dir").Offset + 0x8;
|
||||||
|
uint16 FreeBlockRotOffset = FreeBlockPosOffset + 0xC;
|
||||||
|
|
||||||
|
pos = Dev::GetOffsetVec3(blocks[i], FreeBlockPosOffset);
|
||||||
|
rot = Dev::GetOffsetVec3(blocks[i], FreeBlockRotOffset) / pi * 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
string uniqueid = pos.x + ";" + pos.y + ";" + pos.z + ";;" + rot.x + ";" + rot.y + ";" + rot.z + ";;"+ blockname;
|
||||||
|
|
||||||
|
if (singleobjectdico.Exists(uniqueid)) {
|
||||||
|
int index = objectsindex.Find(uniqueid);
|
||||||
|
if (index >= 0) {
|
||||||
|
objects[index].count++;
|
||||||
|
} else {
|
||||||
|
objects.InsertLast(Objects(blockname, "Block", pos, rot));
|
||||||
|
objectsindex.InsertLast(uniqueid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
singleobjectdico.Set(uniqueid, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
singleobjectdico.DeleteAll();
|
||||||
|
|
||||||
|
auto items = map.AnchoredObjects;
|
||||||
|
|
||||||
|
for(uint i = 0; i < items.Length; i++) {
|
||||||
|
if (i % 1000 == 0) yield(); // to avoid timeout
|
||||||
|
computedobjects++;
|
||||||
|
|
||||||
|
string itemname = items[i].ItemModel.IdName;
|
||||||
|
|
||||||
|
vec3 pos = items[i].AbsolutePositionInMap;
|
||||||
|
vec3 rot;
|
||||||
|
rot.x = items[i].Yaw;
|
||||||
|
rot.y = items[i].Pitch;
|
||||||
|
rot.z = items[i].Roll;
|
||||||
|
|
||||||
|
string uniqueid = pos.x + ";" + pos.y + ";" + pos.z + ";;" + rot.x + ";" + rot.y + ";" + rot.z + ";;"+ itemname;
|
||||||
|
|
||||||
|
if (singleobjectdico.Exists(uniqueid)) {
|
||||||
|
int index = objectsindex.Find(uniqueid);
|
||||||
|
if (index >= 0) {
|
||||||
|
objects[index].count++;
|
||||||
|
} else {
|
||||||
|
objects.InsertLast(Objects(itemname, "Item", pos, rot));
|
||||||
|
objectsindex.InsertLast(uniqueid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
singleobjectdico.Set(uniqueid, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FocusCam(vec3 position) {
|
||||||
|
auto editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||||
|
auto camera = editor.OrbitalCameraControl;
|
||||||
|
auto map = GetApp().RootMap;
|
||||||
|
|
||||||
|
|
||||||
|
if (camera !is null) {
|
||||||
|
camera.m_TargetedPosition = position;
|
||||||
|
// Workaround to update camera TargetedPosition
|
||||||
|
auto m_ParamScrollZoomPowe = camera.m_ParamScrollZoomPower;
|
||||||
|
camera.m_ParamScrollZoomPower = 0;
|
||||||
|
editor.ButtonZoomInOnClick();
|
||||||
|
camera.m_ParamScrollZoomPower = m_ParamScrollZoomPowe;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenerateRow(Objects@ object) {
|
||||||
|
if (object.count <= 1) return;
|
||||||
|
UI::TableNextRow();
|
||||||
|
UI::TableNextColumn();
|
||||||
|
if (UI::Button(Icons::Search + "###Search;" + object.position.x + ";" + object.position.y + ";" + object.position.z)) {
|
||||||
|
FocusCam(object.position);
|
||||||
|
}
|
||||||
|
if (UI::IsItemHovered() && cast<CGameEditorPluginMapMapType>(cast<CGameCtnEditorFree>(GetApp().Editor).PluginMapType) is null) infotext = "Editor plugins are disabled, the coordinates of the blocks are estimated and can be imprecise";
|
||||||
|
UI::SameLine();
|
||||||
|
UI::Text(object.name);
|
||||||
|
UI::TableNextColumn();
|
||||||
|
UI::Text(object.type);
|
||||||
|
UI::TableNextColumn();
|
||||||
|
UI::Text("<" + object.position.x + ", " + object.position.y + ", " + object.position.z +">");
|
||||||
|
UI::TableNextColumn();
|
||||||
|
UI::Text("<" + object.rotation.x + ", " + object.rotation.y + ", " + object.rotation.z +">");
|
||||||
|
UI::TableNextColumn();
|
||||||
|
UI::Text(Text::Format("%lld",object.count));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render() {
|
||||||
|
if (!menu_visibility) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||||
|
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||||
|
|
||||||
|
if (map is null && editor is null) {
|
||||||
|
menu_visibility = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
infotext = "";
|
||||||
|
|
||||||
|
UI::SetNextWindowSize(600, 400);
|
||||||
|
UI::SetNextWindowPos(200, 200, UI::Cond::Once);
|
||||||
|
UI::Begin("\\$cf9" + Icons::Table + "\\$z DuplicateFinder###DuplicateFinder", menu_visibility);
|
||||||
|
if (editor !is null) {
|
||||||
|
if (refreshobject) {
|
||||||
|
if (Time::get_Now() % 3000 > 2000) {
|
||||||
|
UI::Button("Loading...");
|
||||||
|
} else if (Time::get_Now() % 3000 > 1000) {
|
||||||
|
UI::Button("Loading.. ");
|
||||||
|
} else {
|
||||||
|
UI::Button("Loading. ");
|
||||||
|
}
|
||||||
|
if (UI::IsItemHovered()) infotext = "Parsing all blocks and items to generate the table. Please wait... (" + computedobjects + "/" + totalobjects + ")";
|
||||||
|
} else {
|
||||||
|
if (UI::Button(Icons::Refresh + " Refresh")) {
|
||||||
|
refreshobject = true;
|
||||||
|
forcesort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UI::SameLine();
|
||||||
|
include_default_blocks = UI::Checkbox("Include Blocks not placed in Free Mapping", include_default_blocks);
|
||||||
|
UI::Separator();
|
||||||
|
vec2 winsize = UI::GetWindowSize();
|
||||||
|
winsize.x = winsize.x - 10;
|
||||||
|
winsize.y = winsize.y - 105;
|
||||||
|
if (UI::BeginTable("DuplicateBlocksTable", 5, UI::TableFlags(UI::TableFlags::Resizable | UI::TableFlags::Sortable | UI::TableFlags::NoSavedSettings | UI::TableFlags::BordersInnerV | UI::TableFlags::SizingStretchProp | UI::TableFlags::ScrollY),winsize )) {
|
||||||
|
UI::TableSetupScrollFreeze(0, 1);
|
||||||
|
UI::TableSetupColumn("Block Name", UI::TableColumnFlags::None, 40.f, ESortColumn::ItemName);
|
||||||
|
UI::TableSetupColumn("Type", UI::TableColumnFlags::NoSort, 10.f);
|
||||||
|
UI::TableSetupColumn("Position", UI::TableColumnFlags::NoSort, 20.f);
|
||||||
|
UI::TableSetupColumn("Rotation", UI::TableColumnFlags::NoSort, 20.f);
|
||||||
|
UI::TableSetupColumn("Count", UI::TableColumnFlags::DefaultSort, 10.f, ESortColumn::Count);
|
||||||
|
UI::TableHeadersRow();
|
||||||
|
|
||||||
|
UI::TableSortSpecs@ sortSpecs = UI::TableGetSortSpecs();
|
||||||
|
if(sortSpecs !is null && sortSpecs.Specs.Length == 1 && sortableobjects.Length > 1) {
|
||||||
|
if(sortSpecs.Dirty || (forcesort && !refreshobject)) {
|
||||||
|
if(sortCol != ESortColumn(sortSpecs.Specs[0].ColumnUserID) || (forcesort && !refreshobject)) {
|
||||||
|
sortCol = ESortColumn(sortSpecs.Specs[0].ColumnUserID);
|
||||||
|
switch(sortCol) {
|
||||||
|
case ESortColumn::ItemName:
|
||||||
|
sortableobjects.Sort(function(a,b) { return a.name < b.name; });
|
||||||
|
break;
|
||||||
|
case ESortColumn::Count:
|
||||||
|
sortableobjects.Sort(function(a,b) { return a.count < b.count; });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (forcesort && sort_reverse) {
|
||||||
|
sortableobjects.Reverse();
|
||||||
|
} else {
|
||||||
|
sort_reverse = false;
|
||||||
|
}
|
||||||
|
} else if (sortCol == ESortColumn(sortSpecs.Specs[0].ColumnUserID)) {
|
||||||
|
sortableobjects.Reverse();
|
||||||
|
sort_reverse = !sort_reverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
sortSpecs.Dirty = false;
|
||||||
|
forcesort = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sortableobjects.Length > 0 ) {
|
||||||
|
for(uint i = 0; i < sortableobjects.Length; i++) {
|
||||||
|
GenerateRow(sortableobjects[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(uint i = 0; i < objects.Length; i++) {
|
||||||
|
GenerateRow(objects[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UI::EndTable();
|
||||||
|
UI::Separator();
|
||||||
|
UI::Text(Icons::Info + " " + infotext);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UI::Text("Open this plugin in the map editor");
|
||||||
|
}
|
||||||
|
UI::End();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderMenu() {
|
||||||
|
CGameCtnEditorFree@ editor = cast<CGameCtnEditorFree>(GetApp().Editor);
|
||||||
|
CGameCtnChallenge@ map = cast<CGameCtnChallenge>(GetApp().RootMap);
|
||||||
|
|
||||||
|
if (map is null && editor is null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(UI::MenuItem("\\$cf9" + Icons::Table + "\\$z DuplicateFinder", "", menu_visibility)) {
|
||||||
|
menu_visibility = !menu_visibility;
|
||||||
|
refreshobject = true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,80 @@
|
|||||||
bool menu_visibility = false;
|
[Setting name="Number of links saved in cache"]
|
||||||
string quickURL;
|
uint S_NbOfLinksInCache = 5;
|
||||||
|
|
||||||
void Main() {}
|
const string C_LinksCache = "LinksCache.txt";
|
||||||
|
|
||||||
void Render() {
|
string G_QuickURL = "";
|
||||||
if (!menu_visibility) {
|
bool G_PressEnter = false;
|
||||||
return;
|
bool G_WasEditing = false;
|
||||||
}
|
|
||||||
UI::Begin("\\$cf9" + Icons::ExternalLinkAlt + "\\$z Quick Link Opener###Quick Link Opener", menu_visibility, UI::WindowFlags::NoResize | UI::WindowFlags::AlwaysAutoResize | UI::WindowFlags::NoCollapse);
|
|
||||||
quickURL = UI::InputText("", quickURL);
|
|
||||||
UI::SameLine();
|
|
||||||
if (UI::Button(Icons::ExternalLinkAlt + " Go !###QuickURL")) {
|
|
||||||
string parsedURL = Regex::Replace(quickURL,'uplay:\\/\\/launch\\/5595\\/0\\/','maniaplanet://');
|
|
||||||
CTrackMania@ app = cast<CTrackMania>(GetApp());
|
|
||||||
app.ManiaPlanetScriptAPI.OpenLink(parsedURL, CGameManiaPlanetScriptAPI::ELinkType::ManialinkBrowser);
|
|
||||||
menu_visibility = false;
|
|
||||||
}
|
|
||||||
UI::End();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderMenu() {
|
array<string> G_LinksCache;
|
||||||
if(UI::MenuItem("\\$cf9" + Icons::ExternalLinkAlt + "\\$z Quick Link Opener", "", menu_visibility)) {
|
|
||||||
menu_visibility = !menu_visibility;
|
void Main() {
|
||||||
|
trace("Loading links cache");
|
||||||
|
string filepath = IO::FromStorageFolder(C_LinksCache);
|
||||||
|
IO::File file(filepath);
|
||||||
|
|
||||||
|
file.Open(IO::FileMode::Read);
|
||||||
|
while(!file.EOF()) {
|
||||||
|
G_LinksCache.InsertLast(file.ReadLine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderMenuMain() {
|
||||||
|
if (!G_PressEnter && UI::BeginMenu("\\$cf9" + Icons::ExternalLink + "\\$z Quick Link Opener##QuickLinkOpenerMenu")) {
|
||||||
|
G_QuickURL = UI::InputText("###quickURL", G_QuickURL, G_PressEnter, UI::InputTextFlags::EnterReturnsTrue + UI::InputTextFlags::CallbackAlways, UI::InputTextCallback(ITCB));
|
||||||
|
|
||||||
|
if (G_LinksCache.Length > 0) {
|
||||||
|
UI::Separator();
|
||||||
|
|
||||||
|
for(uint i = 0; i < G_LinksCache.Length; i++ ) {
|
||||||
|
if (UI::MenuItem(G_LinksCache[i] + "###" + i)) {
|
||||||
|
LoadLink(G_LinksCache[i], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UI::EndMenu();
|
||||||
|
} else if (G_PressEnter || G_WasEditing) {
|
||||||
|
G_PressEnter = false;
|
||||||
|
G_WasEditing = false;
|
||||||
|
LoadLink(G_QuickURL, true);
|
||||||
|
G_QuickURL = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITCB(UI::InputTextCallbackData@ d) {
|
||||||
|
G_WasEditing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadLink(string _Url, bool _NewUrl) {
|
||||||
|
if (_Url == "") return;
|
||||||
|
|
||||||
|
string parsedURL = "";
|
||||||
|
if (_NewUrl) {
|
||||||
|
parsedURL = Regex::Replace(_Url,'uplay:\\/\\/launch\\/5595\\/0\\/','maniaplanet://');
|
||||||
|
|
||||||
|
G_LinksCache.InsertAt(0, parsedURL);
|
||||||
|
|
||||||
|
// Clear cache if too long
|
||||||
|
if (G_LinksCache.Length > S_NbOfLinksInCache) {
|
||||||
|
G_LinksCache.RemoveRange(S_NbOfLinksInCache, G_LinksCache.Length - S_NbOfLinksInCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute text for the cache file
|
||||||
|
string content;
|
||||||
|
for(uint i = 0; i < G_LinksCache.Length; i++ ) {
|
||||||
|
content = content + G_LinksCache[i] + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("Writing links cache");
|
||||||
|
string filepath = IO::FromStorageFolder(C_LinksCache);
|
||||||
|
IO::File file(filepath, IO::FileMode::Write);
|
||||||
|
file.Write(content);
|
||||||
|
} else {
|
||||||
|
parsedURL = _Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTrackMania@ app = cast<CTrackMania>(GetApp());
|
||||||
|
app.ManiaPlanetScriptAPI.OpenLink(parsedURL, CGameManiaPlanetScriptAPI::ELinkType::ManialinkBrowser);
|
||||||
|
}
|
||||||
|
@ -1 +0,0 @@
|
|||||||
щ╧╓╧╨g└ЩС г│Вбс⌡╘· ╥fЦJс%⌡]иJ_аP╨╨ah⌠кВ5┴'NNпZЭ2аДrМ≤TЕ
|
|
@ -4,11 +4,6 @@ author = "Beu"
|
|||||||
category = "Utilities"
|
category = "Utilities"
|
||||||
|
|
||||||
siteid = 101
|
siteid = 101
|
||||||
version = "1.1"
|
version = "2.0"
|
||||||
|
|
||||||
perms = "paid"
|
|
||||||
|
|
||||||
blocks = [ "Plugin_QuickLinkOpener" ]
|
blocks = [ "Plugin_QuickLinkOpener" ]
|
||||||
|
|
||||||
[script]
|
|
||||||
imports = [ "Icons.as" ]
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user