mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Add experimental export with Cocos2d
This commit is contained in:
@@ -29,7 +29,8 @@ public:
|
||||
|
||||
GetObjectMetadata("PanelSpriteObject::PanelSprite")
|
||||
.SetIncludeFile("PanelSpriteObject/panelspriteruntimeobject.js")
|
||||
.AddIncludeFile("PanelSpriteObject/panelspriteruntimeobject-pixi-renderer.js");
|
||||
.AddIncludeFile("PanelSpriteObject/panelspriteruntimeobject-pixi-renderer.js")
|
||||
.AddIncludeFile("PanelSpriteObject/panelspriteruntimeobject-cocos-renderer.js");
|
||||
|
||||
GetAllActionsForObject("PanelSpriteObject::PanelSprite")["PanelSpriteObject::Width"].SetFunctionName("setWidth").SetGetter("getWidth");
|
||||
GetAllConditionsForObject("PanelSpriteObject::PanelSprite")["PanelSpriteObject::Width"].SetFunctionName("getWidth");
|
||||
|
@@ -30,7 +30,8 @@ public:
|
||||
|
||||
GetObjectMetadata("TextObject::Text")
|
||||
.SetIncludeFile("TextObject/textruntimeobject.js")
|
||||
.AddIncludeFile("TextObject/textruntimeobject-pixi-renderer.js");
|
||||
.AddIncludeFile("TextObject/textruntimeobject-pixi-renderer.js")
|
||||
.AddIncludeFile("TextObject/textruntimeobject-cocos-renderer.js");
|
||||
|
||||
GetAllActionsForObject("TextObject::Text")["TextObject::String"].SetFunctionName("setString").SetGetter("getString").SetIncludeFile("TextObject/textruntimeobject.js");
|
||||
GetAllConditionsForObject("TextObject::Text")["TextObject::String"].SetFunctionName("getString").SetIncludeFile("TextObject/textruntimeobject.js");
|
||||
|
@@ -31,7 +31,8 @@ public:
|
||||
|
||||
GetObjectMetadata("TiledSpriteObject::TiledSprite")
|
||||
.SetIncludeFile("TiledSpriteObject/tiledspriteruntimeobject.js")
|
||||
.AddIncludeFile("TiledSpriteObject/tiledspriteruntimeobject-pixi-renderer.js");
|
||||
.AddIncludeFile("TiledSpriteObject/tiledspriteruntimeobject-pixi-renderer.js")
|
||||
.AddIncludeFile("TiledSpriteObject/tiledspriteruntimeobject-cocos-renderer.js");
|
||||
|
||||
GetAllActionsForObject("TiledSpriteObject::TiledSprite")["TiledSpriteObject::Width"].SetFunctionName("setWidth").SetGetter("getWidth").SetIncludeFile("TiledSpriteObject/tiledspriteruntimeobject.js");
|
||||
GetAllConditionsForObject("TiledSpriteObject::TiledSprite")["TiledSpriteObject::Width"].SetFunctionName("getWidth").SetIncludeFile("TiledSpriteObject/tiledspriteruntimeobject.js");
|
||||
|
@@ -71,8 +71,8 @@ public:
|
||||
|
||||
Exporter exporter(gd::NativeFileSystem::Get());
|
||||
bool exportSuccessed = externalLayout ?
|
||||
exporter.ExportExternalLayoutForPreview(project, layout, *externalLayout, exportDir) :
|
||||
exporter.ExportLayoutForPreview(project, layout, exportDir);
|
||||
exporter.ExportExternalLayoutForPixiPreview(project, layout, *externalLayout, exportDir) :
|
||||
exporter.ExportLayoutForPixiPreview(project, layout, exportDir);
|
||||
|
||||
if (!exportSuccessed)
|
||||
{
|
||||
|
@@ -180,48 +180,88 @@ BaseProjectExportDialog::BaseProjectExportDialog(wxWindow* parent, wxWindowID id
|
||||
|
||||
flexGridSizer1147->Add(m_staticText6768, 0, wxALL|wxEXPAND|wxALIGN_CENTER|wxALIGN_LEFT, 5);
|
||||
|
||||
m_panel71 = new wxPanel(exportChoice, wxID_ANY, wxDefaultPosition, wxSize(-1,-1), wxTAB_TRAVERSAL);
|
||||
exportChoice->AddPage(m_panel71, _("Mobile and web stores using CocoonJS (Experimental)"), false);
|
||||
m_panel611 = new wxPanel(exportChoice, wxID_ANY, wxDefaultPosition, wxSize(-1,-1), wxTAB_TRAVERSAL);
|
||||
exportChoice->AddPage(m_panel611, _("Export to a website or native game with Cocos2d (experimental)"), false);
|
||||
|
||||
wxFlexGridSizer* flexGridSizer551 = new wxFlexGridSizer(0, 1, 0, 0);
|
||||
flexGridSizer551->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer551->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer551->AddGrowableCol(0);
|
||||
flexGridSizer551->AddGrowableRow(1);
|
||||
m_panel71->SetSizer(flexGridSizer551);
|
||||
wxFlexGridSizer* flexGridSizer342 = new wxFlexGridSizer(0, 1, 0, 0);
|
||||
flexGridSizer342->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer342->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer342->AddGrowableCol(0);
|
||||
m_panel611->SetSizer(flexGridSizer342);
|
||||
|
||||
cocoonjslogoPanel2 = new wxPanel(m_panel71, wxID_ANY, wxDefaultPosition, wxSize(-1,-1), wxTAB_TRAVERSAL|wxBORDER_SIMPLE);
|
||||
cocoonjslogoPanel2->SetBackgroundColour(wxColour(wxT("rgb(51,16,69)")));
|
||||
wxFlexGridSizer* flexGridSizer353 = new wxFlexGridSizer(0, 3, 0, 0);
|
||||
flexGridSizer353->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer353->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer353->AddGrowableCol(0);
|
||||
flexGridSizer353->AddGrowableRow(0);
|
||||
|
||||
flexGridSizer551->Add(cocoonjslogoPanel2, 0, wxALL|wxALIGN_CENTER, 0);
|
||||
flexGridSizer342->Add(flexGridSizer353, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
||||
wxFlexGridSizer* flexGridSizer633 = new wxFlexGridSizer(0, 2, 0, 0);
|
||||
flexGridSizer633->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer633->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
cocoonjslogoPanel2->SetSizer(flexGridSizer633);
|
||||
wxFlexGridSizer* flexGridSizer364 = new wxFlexGridSizer(0, 2, 0, 0);
|
||||
flexGridSizer364->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer364->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer364->AddGrowableCol(1);
|
||||
|
||||
m_staticBitmap574 = new wxStaticBitmap(cocoonjslogoPanel2, wxID_ANY, wxXmlResource::Get()->LoadBitmap(wxT("cocoonjslogo")), wxDefaultPosition, wxSize(-1,-1), 0 );
|
||||
flexGridSizer353->Add(flexGridSizer364, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
||||
flexGridSizer633->Add(m_staticBitmap574, 0, wxALL, 0);
|
||||
ID_STATICTEXT45 = new wxStaticText(m_panel611, wxID_ANY, _("Export folder:"), wxDefaultPosition, wxSize(-1,-1), 0);
|
||||
|
||||
m_staticText655 = new wxStaticText(m_panel71, wxID_ANY, _("CocoonJS is a technology that helps HTML5 developers\npublish their web-based games and apps in the most\nimportant mobile and web stores."), wxDefaultPosition, wxSize(-1,-1), wxALIGN_CENTRE);
|
||||
flexGridSizer364->Add(ID_STATICTEXT45, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
flexGridSizer551->Add(m_staticText655, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_TOP, 10);
|
||||
wxFlexGridSizer* flexGridSizer386 = new wxFlexGridSizer(0, 3, 0, 0);
|
||||
flexGridSizer386->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer386->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer386->AddGrowableCol(0);
|
||||
flexGridSizer386->AddGrowableRow(0);
|
||||
|
||||
wxStaticBoxSizer* staticBoxSizer112 = new wxStaticBoxSizer( new wxStaticBox(m_panel71, wxID_ANY, _("Note")), wxVERTICAL);
|
||||
flexGridSizer364->Add(flexGridSizer386, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
||||
flexGridSizer551->Add(staticBoxSizer112, 1, wxALL|wxEXPAND, 5);
|
||||
cocosExportFolderEdit = new wxTextCtrl(m_panel611, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(-1,-1), 0);
|
||||
#if wxVERSION_NUMBER >= 3000
|
||||
cocosExportFolderEdit->SetHint(wxT(""));
|
||||
#endif
|
||||
|
||||
wxFlexGridSizer* flexGridSizer114 = new wxFlexGridSizer(0, 2, 0, 0);
|
||||
flexGridSizer114->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer114->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer114->AddGrowableCol(0);
|
||||
flexGridSizer386->Add(cocosExportFolderEdit, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
staticBoxSizer112->Add(flexGridSizer114, 1, wxALL|wxEXPAND, 0);
|
||||
cocosExportBrowseBt = new wxButton(m_panel611, wxID_ANY, _("..."), wxDefaultPosition, wxSize(30,-1), 0);
|
||||
|
||||
m_staticText676 = new wxStaticText(m_panel71, wxID_ANY, _("Just click on the \"Export\" button and GDevelop will\npackage your game in a single zip file.\nYou'll then be able to upload this file on the cloud compiler\nat cloud.ludei.com, which will allows you to compile\nthe game into an iOS/Android app."), wxDefaultPosition, wxSize(-1,-1), wxALIGN_LEFT);
|
||||
flexGridSizer386->Add(cocosExportBrowseBt, 1, wxRIGHT|wxTOP|wxBOTTOM|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
flexGridSizer114->Add(m_staticText676, 0, wxALL|wxEXPAND|wxALIGN_CENTER|wxALIGN_LEFT, 5);
|
||||
ID_STATICTEXT213 = new wxStaticText(m_panel611, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(-1,-1), 0);
|
||||
|
||||
flexGridSizer342->Add(ID_STATICTEXT213, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
ID_STATICTEXT114 = new wxStaticText(m_panel611, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(-1,-1), 0);
|
||||
|
||||
flexGridSizer342->Add(ID_STATICTEXT114, 1, wxLEFT|wxRIGHT|wxBOTTOM|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
wxStaticBoxSizer* staticBoxSizer4515 = new wxStaticBoxSizer( new wxStaticBox(m_panel611, wxID_ANY, _("Note")), wxVERTICAL);
|
||||
|
||||
flexGridSizer342->Add(staticBoxSizer4515, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
wxFlexGridSizer* flexGridSizer4616 = new wxFlexGridSizer(0, 1, 0, 0);
|
||||
flexGridSizer4616->SetFlexibleDirection( wxBOTH );
|
||||
flexGridSizer4616->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
flexGridSizer4616->AddGrowableCol(0);
|
||||
|
||||
staticBoxSizer4515->Add(flexGridSizer4616, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
|
||||
|
||||
ID_STATICTEXT31719 = new wxStaticText(m_panel611, wxID_ANY, _("When the exportation is done, send the files to your website (you need a web hosting) and just go to the website to start the game."), wxDefaultPosition, wxSize(-1,-1), 0);
|
||||
ID_STATICTEXT31719->Wrap(450);
|
||||
|
||||
flexGridSizer4616->Add(ID_STATICTEXT31719, 1, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
ID_STATICTEXT317 = new wxStaticText(m_panel611, wxID_ANY, _("If you install Cocos2d-x, you can also use it to export the game to Android, iOS, Windows, Mac or Linux."), wxDefaultPosition, wxSize(-1,-1), 0);
|
||||
ID_STATICTEXT317->Wrap(450);
|
||||
|
||||
flexGridSizer4616->Add(ID_STATICTEXT317, 1, wxALL|wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
ID_HYPERLINKCTRL218 = new wxHyperlinkCtrl(m_panel611, wxID_ANY, _("Click here to learn more about Cocos2d export"), wxT("http://wiki.compilgames.net/doku.php/en/game_develop/tutorials/howtoexportwithcocos2dx"), wxDefaultPosition, wxSize(-1,-1), wxHL_DEFAULT_STYLE);
|
||||
ID_HYPERLINKCTRL218->SetNormalColour(wxColour(wxT("#0000FF")));
|
||||
ID_HYPERLINKCTRL218->SetHoverColour(wxColour(wxT("#0000FF")));
|
||||
ID_HYPERLINKCTRL218->SetVisitedColour(wxColour(wxT("#FF0000")));
|
||||
|
||||
flexGridSizer4616->Add(ID_HYPERLINKCTRL218, 1, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
wxFlexGridSizer* flexGridSizer50 = new wxFlexGridSizer(0, 3, 0, 0);
|
||||
flexGridSizer50->SetFlexibleDirection( wxBOTH );
|
||||
@@ -281,6 +321,7 @@ BaseProjectExportDialog::BaseProjectExportDialog(wxWindow* parent, wxWindowID id
|
||||
#endif
|
||||
// Connect events
|
||||
browseBt->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnBrowseBtClick), NULL, this);
|
||||
cocosExportBrowseBt->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnCocosExportBrowseBtClick), NULL, this);
|
||||
closeBt->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnCloseBtClicked), NULL, this);
|
||||
exportBt->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnExportBtClicked), NULL, this);
|
||||
|
||||
@@ -289,6 +330,7 @@ BaseProjectExportDialog::BaseProjectExportDialog(wxWindow* parent, wxWindowID id
|
||||
BaseProjectExportDialog::~BaseProjectExportDialog()
|
||||
{
|
||||
browseBt->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnBrowseBtClick), NULL, this);
|
||||
cocosExportBrowseBt->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnCocosExportBrowseBtClick), NULL, this);
|
||||
closeBt->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnCloseBtClicked), NULL, this);
|
||||
exportBt->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BaseProjectExportDialog::OnExportBtClicked), NULL, this);
|
||||
|
||||
|
@@ -53,11 +53,15 @@ protected:
|
||||
wxStaticBitmap* m_staticBitmap5744;
|
||||
wxStaticText* m_staticText6555;
|
||||
wxStaticText* m_staticText6768;
|
||||
wxPanel* m_panel71;
|
||||
wxPanel* cocoonjslogoPanel2;
|
||||
wxStaticBitmap* m_staticBitmap574;
|
||||
wxStaticText* m_staticText655;
|
||||
wxStaticText* m_staticText676;
|
||||
wxPanel* m_panel611;
|
||||
wxStaticText* ID_STATICTEXT45;
|
||||
wxTextCtrl* cocosExportFolderEdit;
|
||||
wxButton* cocosExportBrowseBt;
|
||||
wxStaticText* ID_STATICTEXT213;
|
||||
wxStaticText* ID_STATICTEXT114;
|
||||
wxStaticText* ID_STATICTEXT31719;
|
||||
wxStaticText* ID_STATICTEXT317;
|
||||
wxHyperlinkCtrl* ID_HYPERLINKCTRL218;
|
||||
wxStaticBitmap* ID_STATICBITMAP2;
|
||||
wxHyperlinkCtrl* ID_HYPERLINKCTRL1;
|
||||
wxButton* closeBt;
|
||||
@@ -65,6 +69,7 @@ protected:
|
||||
|
||||
protected:
|
||||
virtual void OnBrowseBtClick(wxCommandEvent& event) { event.Skip(); }
|
||||
virtual void OnCocosExportBrowseBtClick(wxCommandEvent& event) { event.Skip(); }
|
||||
virtual void OnCloseBtClicked(wxCommandEvent& event) { event.Skip(); }
|
||||
virtual void OnExportBtClicked(wxCommandEvent& event) { event.Skip(); }
|
||||
|
||||
@@ -85,11 +90,15 @@ public:
|
||||
wxStaticText* GetStaticText6555() { return m_staticText6555; }
|
||||
wxStaticText* GetStaticText6768() { return m_staticText6768; }
|
||||
wxPanel* GetPanel118() { return m_panel118; }
|
||||
wxStaticBitmap* GetStaticBitmap574() { return m_staticBitmap574; }
|
||||
wxPanel* GetCocoonjslogoPanel2() { return cocoonjslogoPanel2; }
|
||||
wxStaticText* GetStaticText655() { return m_staticText655; }
|
||||
wxStaticText* GetStaticText676() { return m_staticText676; }
|
||||
wxPanel* GetPanel71() { return m_panel71; }
|
||||
wxStaticText* GetID_STATICTEXT45() { return ID_STATICTEXT45; }
|
||||
wxTextCtrl* GetCocosExportFolderEdit() { return cocosExportFolderEdit; }
|
||||
wxButton* GetCocosExportBrowseBt() { return cocosExportBrowseBt; }
|
||||
wxStaticText* GetID_STATICTEXT213() { return ID_STATICTEXT213; }
|
||||
wxStaticText* GetID_STATICTEXT114() { return ID_STATICTEXT114; }
|
||||
wxStaticText* GetID_STATICTEXT31719() { return ID_STATICTEXT31719; }
|
||||
wxStaticText* GetID_STATICTEXT317() { return ID_STATICTEXT317; }
|
||||
wxHyperlinkCtrl* GetID_HYPERLINKCTRL218() { return ID_HYPERLINKCTRL218; }
|
||||
wxPanel* GetPanel611() { return m_panel611; }
|
||||
wxChoicebook* GetExportChoice() { return exportChoice; }
|
||||
wxStaticBitmap* GetID_STATICBITMAP2() { return ID_STATICBITMAP2; }
|
||||
wxHyperlinkCtrl* GetID_HYPERLINKCTRL1() { return ID_HYPERLINKCTRL1; }
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include "GDCore/Tools/HelpFileAccess.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDJS/IDE/Exporter.h"
|
||||
#include "GDJS/IDE/ExporterHelper.h"
|
||||
#include "GDCore/IDE/wxTools/SkinHelper.h"
|
||||
|
||||
namespace gdjs
|
||||
@@ -23,15 +23,17 @@ ProjectExportDialog::ProjectExportDialog(wxWindow* parent, gd::Project & project
|
||||
BaseProjectExportDialog(parent),
|
||||
project(project_)
|
||||
{
|
||||
//TODO: Remove when CocoonJS support is fully working.
|
||||
exportChoice->RemovePage(2);
|
||||
|
||||
exportFolderEdit->AutoCompleteDirectories();
|
||||
cocosExportFolderEdit->AutoCompleteDirectories();
|
||||
if ( wxDirExists(project.GetLastCompilationDirectory()) )
|
||||
{
|
||||
exportFolderEdit->SetValue(project.GetLastCompilationDirectory());
|
||||
cocosExportFolderEdit->SetValue(project.GetLastCompilationDirectory());
|
||||
}
|
||||
else
|
||||
{
|
||||
exportFolderEdit->SetValue(wxFileName::GetHomeDir()+wxFileName::GetPathSeparator()+DeleteInvalidCharacters(project.GetName()));
|
||||
cocosExportFolderEdit->SetValue(wxFileName::GetHomeDir()+wxFileName::GetPathSeparator()+DeleteInvalidCharacters(project.GetName()));
|
||||
}
|
||||
|
||||
//Open the latest used export type.
|
||||
@@ -39,7 +41,7 @@ ProjectExportDialog::ProjectExportDialog(wxWindow* parent, gd::Project & project
|
||||
wxConfigBase::Get()->Read("Export/JS platform/LatestExportType", &latestPage, 0);
|
||||
exportChoice->SetSelection(latestPage);
|
||||
|
||||
hasNode = !Exporter::GetNodeExecutablePath().empty();
|
||||
hasNode = !ExporterHelper::GetNodeExecutablePath().empty();
|
||||
nodejsLink->Show(!hasNode);
|
||||
if ( !hasNode )
|
||||
{
|
||||
@@ -57,11 +59,11 @@ ProjectExportDialog::ExportType ProjectExportDialog::GetExportType()
|
||||
switch(exportChoice->GetSelection())
|
||||
{
|
||||
case 1:
|
||||
return Cordova;
|
||||
return PixiCordova;
|
||||
case 2:
|
||||
return CocoonJS;
|
||||
return Cocos2d;
|
||||
default:
|
||||
return Normal;
|
||||
return Pixi;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,18 +109,27 @@ void ProjectExportDialog::OnBrowseBtClick(wxCommandEvent& event)
|
||||
exportFolderEdit->SetValue(dialog.GetPath());
|
||||
}
|
||||
|
||||
void ProjectExportDialog::OnCocosExportBrowseBtClick(wxCommandEvent& event)
|
||||
{
|
||||
wxDirDialog dialog(this, _("Choose a folder, empty if possible, where the game should be exported."));
|
||||
if ( dialog.ShowModal() == wxID_OK )
|
||||
cocosExportFolderEdit->SetValue(dialog.GetPath());
|
||||
}
|
||||
|
||||
gd::String ProjectExportDialog::GetExportDir()
|
||||
{
|
||||
if ( GetExportType() == Normal )
|
||||
return gd::String(exportFolderEdit->GetValue());
|
||||
else
|
||||
if ( GetExportType() == PixiCordova )
|
||||
return gd::String(wxFileName::GetHomeDir())+wxString(wxFileName::GetPathSeparator())+gd::String(DeleteInvalidCharacters(project.GetName()));
|
||||
if ( GetExportType() == Cocos2d )
|
||||
return gd::String(cocosExportFolderEdit->GetValue());
|
||||
else
|
||||
return gd::String(exportFolderEdit->GetValue());
|
||||
}
|
||||
|
||||
bool ProjectExportDialog::RequestMinify()
|
||||
{
|
||||
if (!hasNode) return false;
|
||||
return GetExportType() != Normal || minifyCheck->GetValue();
|
||||
return GetExportType() == PixiCordova || minifyCheck->GetValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,9 +28,9 @@ public:
|
||||
|
||||
enum ExportType
|
||||
{
|
||||
Normal,
|
||||
Cordova,
|
||||
CocoonJS
|
||||
Pixi,
|
||||
PixiCordova,
|
||||
Cocos2d
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
bool RequestMinify();
|
||||
|
||||
protected:
|
||||
virtual void OnCocosExportBrowseBtClick(wxCommandEvent& event);
|
||||
virtual void OnBrowseBtClick(wxCommandEvent& event);
|
||||
virtual void OnCloseBtClicked(wxCommandEvent& event);
|
||||
virtual void OnExportBtClicked(wxCommandEvent& event);
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "GDCore/IDE/ProjectStripper.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDJS/IDE/Exporter.h"
|
||||
#include "GDJS/IDE/ExporterHelper.h"
|
||||
#include "GDJS/Events/CodeGeneration/EventsCodeGenerator.h"
|
||||
#include "GDJS/IDE/Dialogs/ProjectExportDialog.h"
|
||||
#include "GDJS/IDE/Dialogs/CocoonJSUploadDialog.h"
|
||||
@@ -41,418 +42,73 @@
|
||||
namespace gdjs
|
||||
{
|
||||
|
||||
//Nice tools functions
|
||||
static void InsertUnique(std::vector<gd::String> & container, gd::String str)
|
||||
{
|
||||
if ( std::find(container.begin(), container.end(), str) == container.end() )
|
||||
container.push_back(str);
|
||||
}
|
||||
|
||||
static void GenerateFontsDeclaration(gd::AbstractFileSystem & fs, const gd::String & outputDir, gd::String & css, gd::String & html)
|
||||
{
|
||||
std::vector<gd::String> ttfFiles = fs.ReadDir(outputDir, ".TTF");
|
||||
for(std::size_t i = 0; i<ttfFiles.size();++i) {
|
||||
gd::String relativeFile = ttfFiles[i];
|
||||
fs.MakeRelative(relativeFile, outputDir);
|
||||
css += "@font-face{ font-family : \"gdjs_font_";
|
||||
css += relativeFile;
|
||||
css += "\"; src : url('";
|
||||
css += relativeFile;
|
||||
css +="') format('truetype'); }";
|
||||
|
||||
html += "<div style=\"font-family: 'gdjs_font_";
|
||||
html += relativeFile;
|
||||
html += "';\">.</div>";
|
||||
}
|
||||
}
|
||||
|
||||
Exporter::~Exporter()
|
||||
{
|
||||
}
|
||||
|
||||
bool Exporter::ExportLayoutForPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir)
|
||||
bool Exporter::ExportLayoutForPixiPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir)
|
||||
{
|
||||
return ExportLayoutForPreview(project, layout, exportDir, "");
|
||||
ExporterHelper helper(fs);
|
||||
return helper.ExportLayoutForPixiPreview(project, layout, exportDir, "");
|
||||
}
|
||||
|
||||
bool Exporter::ExportExternalLayoutForPreview(gd::Project & project, gd::Layout & layout,
|
||||
bool Exporter::ExportExternalLayoutForPixiPreview(gd::Project & project, gd::Layout & layout,
|
||||
gd::ExternalLayout & externalLayout, gd::String exportDir)
|
||||
{
|
||||
gd::SerializerElement options;
|
||||
options.AddChild("injectExternalLayout").SetValue(externalLayout.GetName());
|
||||
|
||||
return ExportLayoutForPreview(project, layout, exportDir,
|
||||
ExporterHelper helper(fs);
|
||||
return helper.ExportLayoutForPixiPreview(project, layout, exportDir,
|
||||
gd::Serializer::ToJSON(options)
|
||||
);
|
||||
}
|
||||
|
||||
bool Exporter::ExportLayoutForPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir, gd::String additionalSpec)
|
||||
{
|
||||
fs.MkDir(exportDir);
|
||||
fs.ClearDir(exportDir);
|
||||
fs.MkDir(exportDir+"/libs");
|
||||
fs.MkDir(exportDir+"/Extensions");
|
||||
std::vector<gd::String> includesFiles;
|
||||
|
||||
gd::Project exportedProject = project;
|
||||
|
||||
//Export resources (*before* generating events as some resources filenames may be updated)
|
||||
ExportResources(fs, exportedProject, exportDir);
|
||||
//Generate events code
|
||||
if ( !ExportEventsCode(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
return false;
|
||||
|
||||
//Export source files
|
||||
if ( !ExportExternalSourceFiles(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
{
|
||||
gd::LogError(_("Error during exporting! Unable to export source files:\n")+lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Strip the project (*after* generating events as the events may use stripped things (objects groups...))
|
||||
gd::ProjectStripper::StripProject(exportedProject);
|
||||
exportedProject.SetFirstLayout(layout.GetName());
|
||||
|
||||
//Export the project
|
||||
ExportToJSON(fs, exportedProject, fs.GetTempDir() + "/GDTemporaries/JSCodeTemp/data.js",
|
||||
"gdjs.projectData");
|
||||
includesFiles.push_back(fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/data.js");
|
||||
|
||||
//Copy all the dependencies
|
||||
ExportIncludesAndLibs(includesFiles, exportDir, false);
|
||||
|
||||
//Create the index file
|
||||
if (!ExportIndexFile("./JsPlatform/Runtime/index.html", exportDir, includesFiles, additionalSpec))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gd::String Exporter::ExportToJSON(gd::AbstractFileSystem &fs, const gd::Project &project, gd::String filename,
|
||||
gd::String wrapIntoVariable)
|
||||
{
|
||||
fs.MkDir(fs.DirNameFrom(filename));
|
||||
|
||||
//Save the project to JSON
|
||||
gd::SerializerElement rootElement;
|
||||
project.SerializeTo(rootElement);
|
||||
|
||||
gd::String output = gd::Serializer::ToJSON(rootElement);
|
||||
if (!wrapIntoVariable.empty()) output = wrapIntoVariable + " = " + output + ";";
|
||||
|
||||
if (!fs.WriteToFile(filename, output))
|
||||
return "Unable to write "+filename;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Exporter::ExportIndexFile(gd::String source, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec)
|
||||
{
|
||||
gd::String str = fs.ReadFile(source);
|
||||
|
||||
//Generate custom declarations for font resources
|
||||
gd::String customCss;
|
||||
gd::String customHtml;
|
||||
GenerateFontsDeclaration(fs, exportDir, customCss, customHtml);
|
||||
|
||||
//Generate the file
|
||||
if (!CompleteIndexFile(str, customCss, customHtml, exportDir, includesFiles, additionalSpec))
|
||||
return false;
|
||||
|
||||
//Write the index.html file
|
||||
if (!fs.WriteToFile(exportDir + "/index.html", str))
|
||||
{
|
||||
lastError = "Unable to write index file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Exporter::ExportCordovaConfigFile(const gd::Project & project, gd::String exportDir)
|
||||
{
|
||||
gd::String str = fs.ReadFile("./JsPlatform/Runtime/Cordova/config.xml")
|
||||
.FindAndReplace("GDJS_PROJECTNAME", project.GetName())
|
||||
.FindAndReplace("GDJS_PACKAGENAME", project.GetPackageName())
|
||||
.FindAndReplace("GDJS_ORIENTATION", "default");
|
||||
|
||||
if (!fs.WriteToFile(exportDir + "/config.xml", str))
|
||||
{
|
||||
lastError = "Unable to write configuration file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Exporter::CompleteIndexFile(gd::String & str, gd::String customCss, gd::String customHtml, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec)
|
||||
{
|
||||
if (additionalSpec.empty()) additionalSpec = "{}";
|
||||
|
||||
gd::String codeFilesIncludes;
|
||||
for (std::vector<gd::String>::const_iterator it = includesFiles.begin(); it != includesFiles.end(); ++it)
|
||||
{
|
||||
if ( !fs.FileExists(exportDir + "/" + *it) )
|
||||
{
|
||||
std::cout << "Warning: Unable to found " << exportDir+"/"+*it << "." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
gd::String relativeFile = exportDir+"/"+*it;
|
||||
fs.MakeRelative(relativeFile, exportDir);
|
||||
codeFilesIncludes += "\t<script src=\""+relativeFile+"\"></script>\n";
|
||||
}
|
||||
|
||||
str = str.FindAndReplace("/* GDJS_CUSTOM_STYLE */", customCss)
|
||||
.FindAndReplace("<!-- GDJS_CUSTOM_HTML -->", customHtml)
|
||||
.FindAndReplace("<!-- GDJS_CODE_FILES -->", codeFilesIncludes)
|
||||
.FindAndReplace("{}/*GDJS_ADDITIONAL_SPEC*/", additionalSpec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Exporter::ExportEventsCode(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
fs.MkDir(outputDir);
|
||||
|
||||
//First, do not forget common includes (they must be included before events generated code files).
|
||||
InsertUnique(includesFiles, "libs/jshashtable.js");
|
||||
InsertUnique(includesFiles, "gd.js");
|
||||
InsertUnique(includesFiles, "libs/hshg.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/pixi.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/runtimegame-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/runtimescene-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/layer-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/pixi-image-manager.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/spriteruntimeobject-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/loadingscreen-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "howler-sound-manager/howler.min.js");
|
||||
InsertUnique(includesFiles, "howler-sound-manager/howler-sound-manager.js");
|
||||
InsertUnique(includesFiles, "inputmanager.js");
|
||||
InsertUnique(includesFiles, "timemanager.js");
|
||||
InsertUnique(includesFiles, "runtimeobject.js");
|
||||
InsertUnique(includesFiles, "profiler.js");
|
||||
InsertUnique(includesFiles, "runtimescene.js");
|
||||
InsertUnique(includesFiles, "scenestack.js");
|
||||
InsertUnique(includesFiles, "polygon.js");
|
||||
InsertUnique(includesFiles, "force.js");
|
||||
InsertUnique(includesFiles, "layer.js");
|
||||
InsertUnique(includesFiles, "timer.js");
|
||||
InsertUnique(includesFiles, "runtimegame.js");
|
||||
InsertUnique(includesFiles, "variable.js");
|
||||
InsertUnique(includesFiles, "variablescontainer.js");
|
||||
InsertUnique(includesFiles, "eventscontext.js");
|
||||
InsertUnique(includesFiles, "runtimebehavior.js");
|
||||
InsertUnique(includesFiles, "spriteruntimeobject.js");
|
||||
|
||||
//Common includes for events only.
|
||||
InsertUnique(includesFiles, "events-tools/commontools.js");
|
||||
InsertUnique(includesFiles, "events-tools/runtimescenetools.js");
|
||||
InsertUnique(includesFiles, "events-tools/inputtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/objecttools.js");
|
||||
InsertUnique(includesFiles, "events-tools/cameratools.js");
|
||||
InsertUnique(includesFiles, "events-tools/soundtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/storagetools.js");
|
||||
InsertUnique(includesFiles, "events-tools/stringtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/windowtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/networktools.js");
|
||||
|
||||
for (std::size_t i = 0;i<project.GetLayoutsCount();++i)
|
||||
{
|
||||
std::set<gd::String> eventsIncludes;
|
||||
gd::Layout & exportedLayout = project.GetLayout(i);
|
||||
gd::String eventsOutput = EventsCodeGenerator::GenerateSceneEventsCompleteCode(project, exportedLayout,
|
||||
exportedLayout.GetEvents(), eventsIncludes, false /*Export for edittime*/);
|
||||
gd::String filename = outputDir+"code"+gd::String::From(i)+".js";
|
||||
|
||||
//Export the code
|
||||
if (fs.WriteToFile(filename, eventsOutput))
|
||||
{
|
||||
for ( std::set<gd::String>::iterator include = eventsIncludes.begin() ; include != eventsIncludes.end(); ++include )
|
||||
InsertUnique(includesFiles, *include);
|
||||
|
||||
InsertUnique(includesFiles, filename);
|
||||
}
|
||||
else {
|
||||
lastError = _("Unable to write ") + filename;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Exporter::ExportExternalSourceFiles(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
const std::vector < std::shared_ptr<gd::SourceFile> > & allFiles = project.GetAllSourceFiles();
|
||||
for (std::size_t i = 0;i<allFiles.size();++i)
|
||||
{
|
||||
if (allFiles[i] == std::shared_ptr<gd::SourceFile>() ) continue;
|
||||
if (allFiles[i]->GetLanguage() != "Javascript" ) continue;
|
||||
|
||||
gd::SourceFile & file = *allFiles[i];
|
||||
|
||||
gd::String filename = file.GetFileName();
|
||||
fs.MakeAbsolute(filename, fs.DirNameFrom(project.GetProjectFile()));
|
||||
gd::String outFilename = "ext-code"+gd::String::From(i)+".js";
|
||||
if (!fs.CopyFile(filename, outputDir+outFilename))
|
||||
gd::LogWarning(_("Could not copy external file") + filename);
|
||||
|
||||
InsertUnique(includesFiles, outputDir+outFilename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Exporter::ExportIncludesAndLibs(std::vector<gd::String> & includesFiles, gd::String exportDir, bool minify)
|
||||
{
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
//Includes files :
|
||||
if ( minify )
|
||||
{
|
||||
gd::String nodeExec = GetNodeExecutablePath();
|
||||
if ( nodeExec.empty() || !fs.FileExists(nodeExec) )
|
||||
{
|
||||
std::cout << "Node.js executable not found." << std::endl;
|
||||
gd::LogWarning(_("The exported script could not be minified: Please check that you installed Node.js on your system."));
|
||||
minify = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gd::String jsPlatformDir = wxGetCwd()+"/JsPlatform/";
|
||||
gd::String cmd = nodeExec+" \""+jsPlatformDir+"Tools/uglify-js/bin/uglifyjs\" ";
|
||||
|
||||
gd::String allJsFiles;
|
||||
for ( std::vector<gd::String>::iterator include = includesFiles.begin() ; include != includesFiles.end(); ++include )
|
||||
{
|
||||
if ( fs.FileExists(jsPlatformDir+"Runtime/"+*include) )
|
||||
allJsFiles += "\""+jsPlatformDir+"Runtime/"+*include+"\" ";
|
||||
else if ( fs.FileExists(jsPlatformDir+"Runtime/Extensions/"+*include) )
|
||||
allJsFiles += "\""+jsPlatformDir+"Runtime/Extensions/"+*include+"\" ";
|
||||
else if ( fs.FileExists(*include) )
|
||||
allJsFiles += "\""+*include+"\" ";
|
||||
}
|
||||
|
||||
cmd += allJsFiles;
|
||||
cmd += "-o \""+exportDir+"/code.js\"";
|
||||
|
||||
wxArrayString output;
|
||||
wxArrayString errors;
|
||||
long res = wxExecute(cmd, output, errors);
|
||||
if ( res != 0 )
|
||||
{
|
||||
std::cout << "Execution of \"UglifyJS\" failed (Command line : " << cmd << ")." << std::endl;
|
||||
std::cout << "Output: ";
|
||||
for (size_t i = 0;i<output.size();++i)
|
||||
std::cout << output[i] << std::endl;
|
||||
for (size_t i = 0;i<errors.size();++i)
|
||||
std::cout << errors[i] << std::endl;
|
||||
|
||||
gd::LogWarning(_("The exported script could not be minified.\n\nMay be an extension is triggering this error: Try to contact the developer if you think it is the case."));
|
||||
minify = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
includesFiles.clear();
|
||||
InsertUnique(includesFiles, "code.js");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
minify = false;
|
||||
#endif
|
||||
|
||||
//If the closure compiler failed or was not request, simply copy all the include files.
|
||||
if ( !minify )
|
||||
{
|
||||
for ( std::vector<gd::String>::iterator include = includesFiles.begin() ; include != includesFiles.end(); ++include )
|
||||
{
|
||||
if ( fs.FileExists("./JsPlatform/Runtime/"+*include) )
|
||||
{
|
||||
gd::String path = fs.DirNameFrom(exportDir+"/"+*include);
|
||||
if ( !fs.DirExists(path) ) fs.MkDir(path);
|
||||
|
||||
fs.CopyFile("./JsPlatform/Runtime/"+*include, exportDir+"/"+*include);
|
||||
//Ok, the filename is relative to the export dir.
|
||||
}
|
||||
else if ( fs.FileExists("./JsPlatform/Runtime/Extensions/"+*include) )
|
||||
{
|
||||
gd::String path = fs.DirNameFrom(exportDir+"/Extensions/"+*include);
|
||||
if ( !fs.DirExists(path) ) fs.MkDir(path);
|
||||
|
||||
fs.CopyFile("./JsPlatform/Runtime/Extensions/"+*include, exportDir+"/Extensions/"+*include);
|
||||
*include = "Extensions/"+*include; //Ensure filename is relative to the export dir.
|
||||
}
|
||||
else if ( fs.FileExists(*include) )
|
||||
{
|
||||
fs.CopyFile(*include, exportDir+"/"+fs.FileNameFrom(*include));
|
||||
*include = fs.FileNameFrom(*include); //Ensure filename is relative to the export dir.
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Could not copy include file " << *include << " (File not found)." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Exporter::ExportResources(gd::AbstractFileSystem & fs, gd::Project & project, gd::String exportDir, wxProgressDialog * progressDialog)
|
||||
{
|
||||
gd::ProjectResourcesCopier::CopyAllResourcesTo(project, fs, exportDir, true, progressDialog, false, false);
|
||||
}
|
||||
|
||||
void Exporter::ShowProjectExportDialog(gd::Project & project)
|
||||
{
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
ProjectExportDialog dialog(NULL, project);
|
||||
if ( dialog.ShowModal() != 1 ) return;
|
||||
|
||||
bool exportForCocoonJS = dialog.GetExportType() == ProjectExportDialog::CocoonJS;
|
||||
bool exportForCordova = dialog.GetExportType() == ProjectExportDialog::Cordova;
|
||||
if (dialog.GetExportType() == ProjectExportDialog::Cocos2d)
|
||||
{
|
||||
ExportWholeCocos2dProject(project, dialog.GetExportDir());
|
||||
}
|
||||
else
|
||||
{
|
||||
bool exportForCordova = dialog.GetExportType() == ProjectExportDialog::PixiCordova;
|
||||
ExportWholePixiProject(project, dialog.GetExportDir(), dialog.RequestMinify(),
|
||||
exportForCordova);
|
||||
}
|
||||
|
||||
ExportWholeProject(project, dialog.GetExportDir(), dialog.RequestMinify(),
|
||||
exportForCocoonJS, exportForCordova);
|
||||
#else
|
||||
gd::LogError("BAD USE: Exporter::ShowProjectExportDialog is not available.");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Exporter::ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
bool minify, bool exportForCocoonJS, bool exportForCordova)
|
||||
bool Exporter::ExportWholePixiProject(gd::Project & project, gd::String exportDir,
|
||||
bool minify, bool exportForCordova)
|
||||
{
|
||||
ExporterHelper helper(fs);
|
||||
|
||||
auto exportProject = [this, &project, &minify,
|
||||
&exportForCocoonJS, &exportForCordova](gd::String exportDir)
|
||||
&exportForCordova, &helper](gd::String exportDir)
|
||||
{
|
||||
wxProgressDialog * progressDialogPtr = NULL;
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
wxProgressDialog progressDialog(_("Export in progress ( 1/2 )"), _("Exporting the project..."));
|
||||
progressDialogPtr = &progressDialog;
|
||||
#endif
|
||||
|
||||
//Prepare the export directory
|
||||
fs.MkDir(exportDir);
|
||||
fs.ClearDir(exportDir);
|
||||
fs.MkDir(exportDir+"/libs");
|
||||
fs.MkDir(exportDir+"/pixi-renderers");
|
||||
fs.MkDir(exportDir+"/Extensions");
|
||||
std::vector<gd::String> includesFiles;
|
||||
|
||||
if (exportForCocoonJS)
|
||||
{
|
||||
fs.MkDir(exportDir+"/libs/CocoonJS");
|
||||
includesFiles.push_back("libs/CocoonJS/cocoon.min.js");
|
||||
}
|
||||
|
||||
gd::Project exportedProject = project;
|
||||
|
||||
//Export the resources (before generating events as some resources filenames may be updated)
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
ExportResources(fs, exportedProject, exportDir, &progressDialog);
|
||||
#else
|
||||
ExportResources(fs, exportedProject, exportDir, NULL);
|
||||
#endif
|
||||
helper.ExportResources(fs, exportedProject, exportDir, progressDialogPtr);
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
progressDialog.SetTitle(_("Export in progress ( 2/2 )"));
|
||||
@@ -460,32 +116,25 @@ bool Exporter::ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
#endif
|
||||
|
||||
//Export events
|
||||
if ( !ExportEventsCode(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
if ( !helper.ExportEventsCode(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
{
|
||||
gd::LogError(_("Error during exporting! Unable to export events:\n")+lastError);
|
||||
return false;
|
||||
}
|
||||
helper.AddLibsInclude(true, false, includesFiles);
|
||||
|
||||
//Export source files
|
||||
if ( !ExportExternalSourceFiles(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
if ( !helper.ExportExternalSourceFiles(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
{
|
||||
gd::LogError(_("Error during exporting! Unable to export source files:\n")+lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
progressDialog.Update(60, _("Preparing the project..."));
|
||||
#endif
|
||||
|
||||
//Strip the project (*after* generating events as the events may use stripped things like objects groups...)...
|
||||
gd::ProjectStripper::StripProject(exportedProject);
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
progressDialog.Update(70, _("Exporting files..."));
|
||||
#endif
|
||||
|
||||
//...and export it
|
||||
ExportToJSON(fs, exportedProject, fs.GetTempDir() + "/GDTemporaries/JSCodeTemp/data.js",
|
||||
helper.ExportToJSON(fs, exportedProject, fs.GetTempDir() + "/GDTemporaries/JSCodeTemp/data.js",
|
||||
"gdjs.projectData");
|
||||
includesFiles.push_back(fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/data.js");
|
||||
|
||||
@@ -494,59 +143,19 @@ bool Exporter::ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
#endif
|
||||
|
||||
//Copy all dependencies and the index (or metadata) file.
|
||||
gd::String additionalSpec = exportForCocoonJS ? "{forceFullscreen:true}" : "";
|
||||
ExportIncludesAndLibs(includesFiles, exportDir, minify);
|
||||
helper.RemoveIncludes(false, true, includesFiles);
|
||||
helper.ExportIncludesAndLibs(includesFiles, exportDir, minify);
|
||||
|
||||
gd::String source = exportForCordova ?
|
||||
"./JsPlatform/Runtime/Cordova/www/index.html" :
|
||||
"./JsPlatform/Runtime/index.html";
|
||||
|
||||
if (!ExportIndexFile(source, exportDir, includesFiles, additionalSpec))
|
||||
if (!helper.ExportPixiIndexFile(source, exportDir, includesFiles, ""))
|
||||
{
|
||||
gd::LogError(_("Error during export:\n") + lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Exporting for online upload requires to zip the whole game.
|
||||
if (exportForCocoonJS)
|
||||
{
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
progressDialog.Update(90, _("Creating the zip file..."));
|
||||
|
||||
//Getting all the files to includes in the directory
|
||||
wxArrayString files;
|
||||
wxDir::GetAllFiles(exportDir, &files);
|
||||
|
||||
wxString zipTempName = fs.GetTempDir()+"/GDTemporaries/zipped_"+gd::String::From(&project)+".zip";
|
||||
wxFFileOutputStream out(zipTempName);
|
||||
wxZipOutputStream zip(out);
|
||||
for(std::size_t i = 0; i < files.size(); ++i)
|
||||
{
|
||||
wxFileName filename(files[i]);
|
||||
filename.MakeRelativeTo(exportDir);
|
||||
wxFileInputStream file(files[i]);
|
||||
if ( file.IsOk() )
|
||||
{
|
||||
zip.PutNextEntry(filename.GetFullPath());
|
||||
zip.Write(file);
|
||||
}
|
||||
}
|
||||
|
||||
if ( !zip.Close() || !out.Close() )
|
||||
gd::LogWarning(_("Unable to finalize the creation of the zip file!\n\nThe exported project won't be put in a zip file."));
|
||||
else
|
||||
{
|
||||
progressDialog.Update(95, _("Cleaning files..."));
|
||||
|
||||
fs.ClearDir(exportDir);
|
||||
fs.CopyFile(zipTempName, exportDir+"/packaged_game.zip");
|
||||
wxRemoveFile(zipTempName);
|
||||
}
|
||||
#else
|
||||
gd::LogError("BAD USE: Trying to export to a zip file, but this feature is not available when wxWidgets support is disabled.");
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -554,7 +163,7 @@ bool Exporter::ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
{
|
||||
//Prepare the export directory
|
||||
fs.MkDir(exportDir);
|
||||
if (!ExportCordovaConfigFile(project, exportDir))
|
||||
if (!helper.ExportCordovaConfigFile(project, exportDir))
|
||||
return false;
|
||||
|
||||
if (!exportProject(exportDir + "/www"))
|
||||
@@ -566,12 +175,7 @@ bool Exporter::ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
|
||||
//Finished!
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
if ( exportForCocoonJS )
|
||||
{
|
||||
CocoonJSUploadDialog uploadDialog(NULL, exportDir+wxString(wxFileName::GetPathSeparator())+"packaged_game.zip");
|
||||
uploadDialog.ShowModal();
|
||||
}
|
||||
else if ( exportForCordova )
|
||||
if ( exportForCordova )
|
||||
{
|
||||
CordovaPackageDialog packageDialog(NULL, exportDir);
|
||||
packageDialog.ShowModal();
|
||||
@@ -589,44 +193,86 @@ bool Exporter::ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Exporter::ExportWholeCocos2dProject(gd::Project & project, gd::String exportDir)
|
||||
{
|
||||
ExporterHelper helper(fs);
|
||||
|
||||
wxProgressDialog * progressDialogPtr = NULL;
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
wxProgressDialog progressDialog(_("Export in progress ( 1/2 )"), _("Exporting the project..."));
|
||||
progressDialogPtr = &progressDialog;
|
||||
#endif
|
||||
|
||||
//Prepare the export directory
|
||||
fs.MkDir(exportDir);
|
||||
fs.ClearDir(exportDir);
|
||||
std::vector<gd::String> includesFiles;
|
||||
|
||||
gd::Project exportedProject = project;
|
||||
|
||||
//Export the resources (before generating events as some resources filenames may be updated)
|
||||
helper.ExportResources(fs, exportedProject, exportDir + "/res", progressDialogPtr);
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
progressDialog.SetTitle(_("Export in progress ( 2/2 )"));
|
||||
progressDialog.Update(50, _("Exporting events..."));
|
||||
#endif
|
||||
|
||||
//Export events
|
||||
if ( !helper.ExportEventsCode(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
{
|
||||
gd::LogError(_("Error during exporting! Unable to export events:\n")+lastError);
|
||||
return false;
|
||||
}
|
||||
helper.AddLibsInclude(false, true, includesFiles);
|
||||
|
||||
//Export source files
|
||||
if ( !helper.ExportExternalSourceFiles(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
{
|
||||
gd::LogError(_("Error during exporting! Unable to export source files:\n")+lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Strip the project (*after* generating events as the events may use stripped things like objects groups...)...
|
||||
gd::ProjectStripper::StripProject(exportedProject);
|
||||
|
||||
//...and export it
|
||||
helper.ExportToJSON(fs, exportedProject, fs.GetTempDir() + "/GDTemporaries/JSCodeTemp/data.js",
|
||||
"gdjs.projectData");
|
||||
includesFiles.push_back(fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/data.js");
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
progressDialog.Update(80, _("Exporting files..."));
|
||||
#endif
|
||||
|
||||
//Copy all dependencies and the index (or metadata) file.
|
||||
helper.RemoveIncludes(true, false, includesFiles);
|
||||
helper.ExportIncludesAndLibs(includesFiles, exportDir + "/src", false);
|
||||
|
||||
gd::String source = "./JsPlatform/Runtime/index.html";
|
||||
|
||||
if (!helper.ExportCocos2dFiles(project, exportDir, includesFiles))
|
||||
{
|
||||
gd::LogError(_("Error during export:\n") + lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Finished!
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
//TODO: Factor/update message?
|
||||
if ( wxMessageBox(_("Compilation achieved. Do you want to open the folder where the project has been compiled\?"),
|
||||
_("Compilation finished"), wxYES_NO) == wxYES )
|
||||
{
|
||||
gd::ShowFolder(exportDir);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gd::String Exporter::GetProjectExportButtonLabel()
|
||||
{
|
||||
return _("Export to the web");
|
||||
}
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
gd::String Exporter::GetNodeExecutablePath()
|
||||
{
|
||||
std::vector<gd::String> guessPaths;
|
||||
wxString userPath;
|
||||
if ( wxConfigBase::Get()->Read("Paths/Node" , &userPath) && !userPath.empty() )
|
||||
guessPaths.push_back(userPath);
|
||||
else
|
||||
{
|
||||
//Try some common paths.
|
||||
#if defined(WINDOWS)
|
||||
guessPaths.push_back("C:/Program Files/nodejs/node.exe");
|
||||
guessPaths.push_back("C:/Program Files (x86)/nodejs/node.exe");
|
||||
#elif defined(LINUX) || defined(MACOS)
|
||||
guessPaths.push_back("/usr/bin/env/nodejs");
|
||||
guessPaths.push_back("/usr/bin/nodejs");
|
||||
guessPaths.push_back("/usr/local/bin/nodejs");
|
||||
guessPaths.push_back("/usr/bin/env/node");
|
||||
guessPaths.push_back("/usr/bin/node");
|
||||
guessPaths.push_back("/usr/local/bin/node");
|
||||
#else
|
||||
#warning Please complete this so as to return a path to the Node executable.
|
||||
#endif
|
||||
}
|
||||
|
||||
for (size_t i = 0;i<guessPaths.size();++i)
|
||||
{
|
||||
if ( wxFileExists(guessPaths[i]) )
|
||||
return guessPaths[i];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@ namespace gd { class Project; }
|
||||
namespace gd { class Layout; }
|
||||
namespace gd { class ExternalLayout; }
|
||||
namespace gd { class AbstractFileSystem; }
|
||||
class wxProgressDialog;
|
||||
|
||||
namespace gdjs
|
||||
{
|
||||
@@ -46,7 +45,7 @@ public:
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \return true if export was successful.
|
||||
*/
|
||||
bool ExportLayoutForPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir);
|
||||
bool ExportLayoutForPixiPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir);
|
||||
|
||||
/**
|
||||
* \brief Create a preview for the specified external layout and layout.
|
||||
@@ -57,135 +56,30 @@ public:
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \return true if export was successful.
|
||||
*/
|
||||
bool ExportExternalLayoutForPreview(gd::Project & project, gd::Layout & layout,
|
||||
bool ExportExternalLayoutForPixiPreview(gd::Project & project, gd::Layout & layout,
|
||||
gd::ExternalLayout & externalLayout, gd::String exportDir);
|
||||
|
||||
/**
|
||||
* \brief Export the specified project.
|
||||
* \brief Export the specified project, using Pixi.js.
|
||||
*
|
||||
* Called by ShowProjectExportDialog if the user clicked on Ok.
|
||||
*/
|
||||
bool ExportWholeProject(gd::Project & project, gd::String exportDir,
|
||||
bool minify, bool exportForCocoonJS, bool exportForCordova);
|
||||
bool ExportWholePixiProject(gd::Project & project, gd::String exportDir,
|
||||
bool minify, bool exportForCordova);
|
||||
|
||||
/**
|
||||
* \brief Export the specified project, using Cocos2d.
|
||||
*
|
||||
* Called by ShowProjectExportDialog if the user clicked on Ok.
|
||||
*/
|
||||
bool ExportWholeCocos2dProject(gd::Project & project, gd::String exportDir);
|
||||
|
||||
/**
|
||||
* \brief Return the error that occurred during the last export.
|
||||
*/
|
||||
const gd::String & GetLastError() const { return lastError; };
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
/**
|
||||
* \brief Try to locate the Node.js executable. (Node must be installed in a standard folder).
|
||||
* \return An empty string if not found, a full path to the node executable otherwise.
|
||||
*/
|
||||
static gd::String GetNodeExecutablePath();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* \brief Export a project to JSON
|
||||
*
|
||||
* \param fs The abstract file system to use to write the file
|
||||
* \param project The project to be exported.
|
||||
* \param filename The filename where export the project
|
||||
* \param wrapIntoVariable If not empty, the resulting json will be wrapped in this javascript
|
||||
* variable allowing to use it as a classical javascript object.
|
||||
* \return Empty string if everthing is ok, description of the error otherwise.
|
||||
*/
|
||||
static gd::String ExportToJSON(gd::AbstractFileSystem &fs, const gd::Project &project, gd::String filename,
|
||||
gd::String wrapIntoVariable);
|
||||
|
||||
/**
|
||||
* \brief Copy all the resources of the project to to the export directory, updating the resources filenames.
|
||||
*
|
||||
* \param fs The abstract file system to use
|
||||
* \param project The project with resources to be exported.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param progressDlg Optional wxProgressDialog which will be updated with the progress.
|
||||
*/
|
||||
static void ExportResources(gd::AbstractFileSystem & fs, gd::Project & project, gd::String exportDir,
|
||||
wxProgressDialog * progressDlg = NULL);
|
||||
|
||||
/**
|
||||
* \brief Copy all the includes files and the standard libraries files to the export directory.
|
||||
*
|
||||
* The includes files are also modified so as to be relative to the export directory
|
||||
* ( Files with absolute filenames are copied into the export directory and their path are stripped ).
|
||||
*
|
||||
* \param includesFiles A vector with filenames to be copied.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param minify If true, the includes files must be merged into one file using Google Closure Compiler.
|
||||
* ( includesFiles parameter will be updated with the new filename )
|
||||
*/
|
||||
bool ExportIncludesAndLibs(std::vector<gd::String> & includesFiles, gd::String exportDir, bool minify);
|
||||
|
||||
/**
|
||||
* \brief Generate the events JS code, and save them to the export directory.
|
||||
*
|
||||
* Files are named "codeX.js", X being the number of the layout in the project.
|
||||
* \param project The project with resources to be exported.
|
||||
* \param outputDir The directory where the events code must be generated.
|
||||
* \param includesFiles A reference to a vector that will be filled with JS files to be exported along with the project.
|
||||
* ( including "codeX.js" files ).
|
||||
*/
|
||||
bool ExportEventsCode(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Copy the external source files used by the game into the export directory, and add them into files
|
||||
* to be included.
|
||||
*
|
||||
* Files are named "ext-codeX.js", X being the index of the external source file in the project.
|
||||
* \param project The project with resources to be exported.
|
||||
* \param outputDir The directory where the events code must be generated.
|
||||
* \param includesFiles A reference to a vector that will be filled with JS files to be exported along with the project.
|
||||
* (including "ext-codeX.js" files).
|
||||
*/
|
||||
bool ExportExternalSourceFiles(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Generate the standard index file and save it to the export directory.
|
||||
*
|
||||
* The includes files must be relative to the export directory.
|
||||
*
|
||||
* \param project The project with layouts to be exported.
|
||||
* \param source The file to be used as a template for the final file.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param includesFiles The JS files to be included in the HTML file. Order is important.
|
||||
* \param additionalSpec JSON string that will be passed to the gdjs.RuntimeGame object.
|
||||
*/
|
||||
bool ExportIndexFile(gd::String source, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec = "");
|
||||
|
||||
/**
|
||||
* \brief Replace the annotations in a index.html file by the specified content.
|
||||
*
|
||||
* \param indexFileContent The source of the index.html file.
|
||||
* \param customCss "<!-- GDJS_CUSTOM_STYLE -->" will be replaced by the content of the string.
|
||||
* \param customHtml "<!-- GDJS_CUSTOM_HTML -->" will be replaced by the content of the string.
|
||||
* \param exportDir The directory where the project must be generated.
|
||||
* \param codeFilesIncludes "<!-- GDJS_CODE_FILES -->" will be replaced by HTML tags to include the filenames contained inside the vector.
|
||||
* \param additionalSpec The string "GDJS_ADDITIONAL_SPEC" surrounded by comments marks will be replaced by the content of the string.
|
||||
*/
|
||||
bool CompleteIndexFile(gd::String & indexFileContent, gd::String customCss, gd::String customHtml, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec);
|
||||
|
||||
/**
|
||||
* \brief Generate the Cordova configuration file and save it to the export directory.
|
||||
*
|
||||
* \param project The project to be used to generate the configuration file.
|
||||
* \param exportDir The directory where the config.xml must be created.
|
||||
*/
|
||||
bool ExportCordovaConfigFile(const gd::Project & project, gd::String exportDir);
|
||||
|
||||
/**
|
||||
* \brief Launch all export methods to generate a complete, stand-alone game for previewing.
|
||||
*
|
||||
* \param layout The layout to be previewed.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param additionalSpec Any additional parameters to be passed to the gdjs.RuntimeGame.
|
||||
* \return true if export was successful.
|
||||
*/
|
||||
bool ExportLayoutForPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir, gd::String additionalSpec);
|
||||
|
||||
gd::AbstractFileSystem & fs; ///< The abstract file system to be used for exportation.
|
||||
gd::String lastError; ///< The last error that occurred.
|
||||
};
|
||||
|
512
GDJS/GDJS/IDE/ExporterHelper.cpp
Normal file
512
GDJS/GDJS/IDE/ExporterHelper.cpp
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* GDevelop JS Platform
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
|
||||
* This project is released under the MIT License.
|
||||
*/
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
#include <wx/filename.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/config.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/zipstrm.h>
|
||||
#include <wx/wfstream.h>
|
||||
#endif
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/ExternalLayout.h"
|
||||
#include "GDCore/IDE/AbstractFileSystem.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
#include "GDCore/IDE/wxTools/ShowFolder.h"
|
||||
#include "GDCore/IDE/Project/ProjectResourcesCopier.h"
|
||||
#include "GDCore/IDE/ProjectStripper.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDJS/Events/CodeGeneration/EventsCodeGenerator.h"
|
||||
#include "GDJS/IDE/ExporterHelper.h"
|
||||
#undef CopyFile //Disable an annoying macro
|
||||
|
||||
namespace gdjs
|
||||
{
|
||||
|
||||
//Nice tools functions
|
||||
static void InsertUnique(std::vector<gd::String> & container, gd::String str)
|
||||
{
|
||||
if ( std::find(container.begin(), container.end(), str) == container.end() )
|
||||
container.push_back(str);
|
||||
}
|
||||
|
||||
static void GenerateFontsDeclaration(gd::AbstractFileSystem & fs, const gd::String & outputDir, gd::String & css, gd::String & html)
|
||||
{
|
||||
std::vector<gd::String> ttfFiles = fs.ReadDir(outputDir, ".TTF");
|
||||
for(std::size_t i = 0; i<ttfFiles.size();++i) {
|
||||
gd::String relativeFile = ttfFiles[i];
|
||||
fs.MakeRelative(relativeFile, outputDir);
|
||||
css += "@font-face{ font-family : \"gdjs_font_";
|
||||
css += relativeFile;
|
||||
css += "\"; src : url('";
|
||||
css += relativeFile;
|
||||
css +="') format('truetype'); }";
|
||||
|
||||
html += "<div style=\"font-family: 'gdjs_font_";
|
||||
html += relativeFile;
|
||||
html += "';\">.</div>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ExporterHelper::ExportLayoutForPixiPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir, gd::String additionalSpec)
|
||||
{
|
||||
fs.MkDir(exportDir);
|
||||
fs.ClearDir(exportDir);
|
||||
std::vector<gd::String> includesFiles;
|
||||
|
||||
gd::Project exportedProject = project;
|
||||
|
||||
//Export resources (*before* generating events as some resources filenames may be updated)
|
||||
ExportResources(fs, exportedProject, exportDir);
|
||||
//Generate events code
|
||||
if ( !ExportEventsCode(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
return false;
|
||||
|
||||
AddLibsInclude(true, false, includesFiles);
|
||||
|
||||
//Export source files
|
||||
if ( !ExportExternalSourceFiles(exportedProject, fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/", includesFiles) )
|
||||
{
|
||||
gd::LogError(_("Error during exporting! Unable to export source files:\n")+lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Strip the project (*after* generating events as the events may use stripped things (objects groups...))
|
||||
gd::ProjectStripper::StripProject(exportedProject);
|
||||
exportedProject.SetFirstLayout(layout.GetName());
|
||||
|
||||
//Export the project
|
||||
ExportToJSON(fs, exportedProject, fs.GetTempDir() + "/GDTemporaries/JSCodeTemp/data.js",
|
||||
"gdjs.projectData");
|
||||
includesFiles.push_back(fs.GetTempDir()+"/GDTemporaries/JSCodeTemp/data.js");
|
||||
|
||||
//Copy all the dependencies
|
||||
RemoveIncludes(false, true, includesFiles);
|
||||
ExportIncludesAndLibs(includesFiles, exportDir, false);
|
||||
|
||||
//Create the index file
|
||||
if (!ExportPixiIndexFile("./JsPlatform/Runtime/index.html", exportDir, includesFiles, additionalSpec))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
gd::String ExporterHelper::ExportToJSON(gd::AbstractFileSystem &fs, const gd::Project &project, gd::String filename,
|
||||
gd::String wrapIntoVariable)
|
||||
{
|
||||
fs.MkDir(fs.DirNameFrom(filename));
|
||||
|
||||
//Save the project to JSON
|
||||
gd::SerializerElement rootElement;
|
||||
project.SerializeTo(rootElement);
|
||||
|
||||
gd::String output = gd::Serializer::ToJSON(rootElement);
|
||||
if (!wrapIntoVariable.empty()) output = wrapIntoVariable + " = " + output + ";";
|
||||
|
||||
if (!fs.WriteToFile(filename, output))
|
||||
return "Unable to write "+filename;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool ExporterHelper::ExportPixiIndexFile(gd::String source, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec)
|
||||
{
|
||||
gd::String str = fs.ReadFile(source);
|
||||
|
||||
//Generate custom declarations for font resources
|
||||
gd::String customCss;
|
||||
gd::String customHtml;
|
||||
GenerateFontsDeclaration(fs, exportDir, customCss, customHtml);
|
||||
|
||||
//Generate the file
|
||||
if (!CompleteIndexFile(str, customCss, customHtml, exportDir, includesFiles, additionalSpec))
|
||||
return false;
|
||||
|
||||
//Write the index.html file
|
||||
if (!fs.WriteToFile(exportDir + "/index.html", str))
|
||||
{
|
||||
lastError = "Unable to write index file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExporterHelper::ExportCordovaConfigFile(const gd::Project & project, gd::String exportDir)
|
||||
{
|
||||
gd::String str = fs.ReadFile("./JsPlatform/Runtime/Cordova/config.xml")
|
||||
.FindAndReplace("GDJS_PROJECTNAME", project.GetName())
|
||||
.FindAndReplace("GDJS_PACKAGENAME", project.GetPackageName())
|
||||
.FindAndReplace("GDJS_ORIENTATION", "default");
|
||||
|
||||
if (!fs.WriteToFile(exportDir + "/config.xml", str))
|
||||
{
|
||||
lastError = "Unable to write configuration file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExporterHelper::ExportCocos2dFiles(const gd::Project & project, gd::String exportDir, const std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
if (!fs.CopyFile("./JsPlatform/Runtime/Cocos2d/main.js", exportDir + "/main.js"))
|
||||
{
|
||||
lastError = "Unable to write Cocos2d main.js file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fs.CopyFile("./JsPlatform/Runtime/Cocos2d/index.html", exportDir + "/index.html"))
|
||||
{
|
||||
lastError = "Unable to write Cocos2d index.html file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fs.CopyFile("./JsPlatform/Runtime/Cocos2d/cocos2d-js-v3.10.js", exportDir + "/cocos2d-js-v3.10.js"))
|
||||
{
|
||||
lastError = "Unable to write Cocos2d cocos2d-js-v3.10.js file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
gd::String includeFilesStr = "";
|
||||
bool first = true;
|
||||
for(auto & file : includesFiles)
|
||||
{
|
||||
if ( !fs.FileExists(exportDir + "/src/" + file) )
|
||||
{
|
||||
std::cout << "Warning: Unable to find " << exportDir + "/" + file << "." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
includeFilesStr += gd::String(first ? "" : ", ") + "\"src/" + file + "\"\n";
|
||||
first = false;
|
||||
}
|
||||
|
||||
gd::String str = fs.ReadFile("./JsPlatform/Runtime/Cocos2d/project.json")
|
||||
.FindAndReplace("// GDJS_INCLUDE_FILES", includeFilesStr);
|
||||
|
||||
if (!fs.WriteToFile(exportDir + "/project.json", str))
|
||||
{
|
||||
lastError = "Unable to write Cocos2d project.json file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExporterHelper::CompleteIndexFile(gd::String & str, gd::String customCss, gd::String customHtml, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec)
|
||||
{
|
||||
if (additionalSpec.empty()) additionalSpec = "{}";
|
||||
|
||||
gd::String codeFilesIncludes;
|
||||
for (std::vector<gd::String>::const_iterator it = includesFiles.begin(); it != includesFiles.end(); ++it)
|
||||
{
|
||||
if ( !fs.FileExists(exportDir + "/" + *it) )
|
||||
{
|
||||
std::cout << "Warning: Unable to find " << exportDir+"/"+*it << "." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
gd::String relativeFile = exportDir+"/"+*it;
|
||||
fs.MakeRelative(relativeFile, exportDir);
|
||||
codeFilesIncludes += "\t<script src=\""+relativeFile+"\"></script>\n";
|
||||
}
|
||||
|
||||
str = str.FindAndReplace("/* GDJS_CUSTOM_STYLE */", customCss)
|
||||
.FindAndReplace("<!-- GDJS_CUSTOM_HTML -->", customHtml)
|
||||
.FindAndReplace("<!-- GDJS_CODE_FILES -->", codeFilesIncludes)
|
||||
.FindAndReplace("{}/*GDJS_ADDITIONAL_SPEC*/", additionalSpec);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExporterHelper::AddLibsInclude(bool pixiRenderers, bool cocosRenderers, std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
if (pixiRenderers)
|
||||
{
|
||||
InsertUnique(includesFiles, "pixi-renderers/pixi.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/runtimegame-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/runtimescene-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/layer-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/pixi-image-manager.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/spriteruntimeobject-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "pixi-renderers/loadingscreen-pixi-renderer.js");
|
||||
InsertUnique(includesFiles, "howler-sound-manager/howler.min.js");
|
||||
InsertUnique(includesFiles, "howler-sound-manager/howler-sound-manager.js");
|
||||
}
|
||||
|
||||
if (cocosRenderers)
|
||||
{
|
||||
InsertUnique(includesFiles, "cocos-renderers/cocos-director-manager.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/cocos-image-manager.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/cocos-tools.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/layer-cocos-renderer.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/loadingscreen-cocos-renderer.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/runtimegame-cocos-renderer.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/runtimescene-cocos-renderer.js");
|
||||
InsertUnique(includesFiles, "cocos-renderers/spriteruntimeobject-cocos-renderer.js");
|
||||
InsertUnique(includesFiles, "cocos-sound-manager/cocos-sound-manager.js");
|
||||
}
|
||||
}
|
||||
|
||||
void ExporterHelper::RemoveIncludes(bool pixiRenderers, bool cocosRenderers, std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
if (pixiRenderers)
|
||||
{
|
||||
for (auto it = includesFiles.begin(); it != includesFiles.end(); )
|
||||
{
|
||||
if (it->find("pixi-renderer") != gd::String::npos)
|
||||
includesFiles.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (cocosRenderers)
|
||||
{
|
||||
for (auto it = includesFiles.begin(); it != includesFiles.end(); )
|
||||
{
|
||||
if (it->find("cocos-renderer") != gd::String::npos)
|
||||
includesFiles.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ExporterHelper::ExportEventsCode(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
fs.MkDir(outputDir);
|
||||
|
||||
//First, do not forget common includes (they must be included before events generated code files).
|
||||
InsertUnique(includesFiles, "libs/jshashtable.js");
|
||||
InsertUnique(includesFiles, "gd.js");
|
||||
InsertUnique(includesFiles, "libs/hshg.js");
|
||||
InsertUnique(includesFiles, "inputmanager.js");
|
||||
InsertUnique(includesFiles, "timemanager.js");
|
||||
InsertUnique(includesFiles, "runtimeobject.js");
|
||||
InsertUnique(includesFiles, "profiler.js");
|
||||
InsertUnique(includesFiles, "runtimescene.js");
|
||||
InsertUnique(includesFiles, "scenestack.js");
|
||||
InsertUnique(includesFiles, "polygon.js");
|
||||
InsertUnique(includesFiles, "force.js");
|
||||
InsertUnique(includesFiles, "layer.js");
|
||||
InsertUnique(includesFiles, "timer.js");
|
||||
InsertUnique(includesFiles, "runtimegame.js");
|
||||
InsertUnique(includesFiles, "variable.js");
|
||||
InsertUnique(includesFiles, "variablescontainer.js");
|
||||
InsertUnique(includesFiles, "eventscontext.js");
|
||||
InsertUnique(includesFiles, "runtimebehavior.js");
|
||||
InsertUnique(includesFiles, "spriteruntimeobject.js");
|
||||
|
||||
//Common includes for events only.
|
||||
InsertUnique(includesFiles, "events-tools/commontools.js");
|
||||
InsertUnique(includesFiles, "events-tools/runtimescenetools.js");
|
||||
InsertUnique(includesFiles, "events-tools/inputtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/objecttools.js");
|
||||
InsertUnique(includesFiles, "events-tools/cameratools.js");
|
||||
InsertUnique(includesFiles, "events-tools/soundtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/storagetools.js");
|
||||
InsertUnique(includesFiles, "events-tools/stringtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/windowtools.js");
|
||||
InsertUnique(includesFiles, "events-tools/networktools.js");
|
||||
|
||||
for (std::size_t i = 0;i<project.GetLayoutsCount();++i)
|
||||
{
|
||||
std::set<gd::String> eventsIncludes;
|
||||
gd::Layout & exportedLayout = project.GetLayout(i);
|
||||
gd::String eventsOutput = EventsCodeGenerator::GenerateSceneEventsCompleteCode(project, exportedLayout,
|
||||
exportedLayout.GetEvents(), eventsIncludes, false /*Export for edittime*/);
|
||||
gd::String filename = outputDir+"code"+gd::String::From(i)+".js";
|
||||
|
||||
//Export the code
|
||||
if (fs.WriteToFile(filename, eventsOutput))
|
||||
{
|
||||
for ( std::set<gd::String>::iterator include = eventsIncludes.begin() ; include != eventsIncludes.end(); ++include )
|
||||
InsertUnique(includesFiles, *include);
|
||||
|
||||
InsertUnique(includesFiles, filename);
|
||||
}
|
||||
else {
|
||||
lastError = _("Unable to write ") + filename;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExporterHelper::ExportExternalSourceFiles(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles)
|
||||
{
|
||||
const std::vector < std::shared_ptr<gd::SourceFile> > & allFiles = project.GetAllSourceFiles();
|
||||
for (std::size_t i = 0;i<allFiles.size();++i)
|
||||
{
|
||||
if (allFiles[i] == std::shared_ptr<gd::SourceFile>() ) continue;
|
||||
if (allFiles[i]->GetLanguage() != "Javascript" ) continue;
|
||||
|
||||
gd::SourceFile & file = *allFiles[i];
|
||||
|
||||
gd::String filename = file.GetFileName();
|
||||
fs.MakeAbsolute(filename, fs.DirNameFrom(project.GetProjectFile()));
|
||||
gd::String outFilename = "ext-code"+gd::String::From(i)+".js";
|
||||
if (!fs.CopyFile(filename, outputDir+outFilename))
|
||||
gd::LogWarning(_("Could not copy external file") + filename);
|
||||
|
||||
InsertUnique(includesFiles, outputDir+outFilename);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExporterHelper::ExportIncludesAndLibs(std::vector<gd::String> & includesFiles, gd::String exportDir, bool minify)
|
||||
{
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
//Includes files :
|
||||
if ( minify )
|
||||
{
|
||||
gd::String nodeExec = GetNodeExecutablePath();
|
||||
if ( nodeExec.empty() || !fs.FileExists(nodeExec) )
|
||||
{
|
||||
std::cout << "Node.js executable not found." << std::endl;
|
||||
gd::LogWarning(_("The exported script could not be minified: Please check that you installed Node.js on your system."));
|
||||
minify = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
gd::String jsPlatformDir = wxGetCwd()+"/JsPlatform/";
|
||||
gd::String cmd = nodeExec+" \""+jsPlatformDir+"Tools/uglify-js/bin/uglifyjs\" ";
|
||||
|
||||
gd::String allJsFiles;
|
||||
for ( std::vector<gd::String>::iterator include = includesFiles.begin() ; include != includesFiles.end(); ++include )
|
||||
{
|
||||
if ( fs.FileExists(jsPlatformDir+"Runtime/"+*include) )
|
||||
allJsFiles += "\""+jsPlatformDir+"Runtime/"+*include+"\" ";
|
||||
else if ( fs.FileExists(jsPlatformDir+"Runtime/Extensions/"+*include) )
|
||||
allJsFiles += "\""+jsPlatformDir+"Runtime/Extensions/"+*include+"\" ";
|
||||
else if ( fs.FileExists(*include) )
|
||||
allJsFiles += "\""+*include+"\" ";
|
||||
}
|
||||
|
||||
cmd += allJsFiles;
|
||||
cmd += "-o \""+exportDir+"/code.js\"";
|
||||
|
||||
wxArrayString output;
|
||||
wxArrayString errors;
|
||||
long res = wxExecute(cmd, output, errors);
|
||||
if ( res != 0 )
|
||||
{
|
||||
std::cout << "Execution of \"UglifyJS\" failed (Command line : " << cmd << ")." << std::endl;
|
||||
std::cout << "Output: ";
|
||||
for (size_t i = 0;i<output.size();++i)
|
||||
std::cout << output[i] << std::endl;
|
||||
for (size_t i = 0;i<errors.size();++i)
|
||||
std::cout << errors[i] << std::endl;
|
||||
|
||||
gd::LogWarning(_("The exported script could not be minified.\n\nMay be an extension is triggering this error: Try to contact the developer if you think it is the case."));
|
||||
minify = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
includesFiles.clear();
|
||||
InsertUnique(includesFiles, "code.js");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
minify = false;
|
||||
#endif
|
||||
|
||||
//If the closure compiler failed or was not request, simply copy all the include files.
|
||||
if ( !minify )
|
||||
{
|
||||
for ( std::vector<gd::String>::iterator include = includesFiles.begin() ; include != includesFiles.end(); ++include )
|
||||
{
|
||||
if ( fs.FileExists("./JsPlatform/Runtime/"+*include) )
|
||||
{
|
||||
gd::String path = fs.DirNameFrom(exportDir+"/"+*include);
|
||||
if ( !fs.DirExists(path) ) fs.MkDir(path);
|
||||
|
||||
fs.CopyFile("./JsPlatform/Runtime/"+*include, exportDir+"/"+*include);
|
||||
//Ok, the filename is relative to the export dir.
|
||||
}
|
||||
else if ( fs.FileExists("./JsPlatform/Runtime/Extensions/"+*include) )
|
||||
{
|
||||
gd::String path = fs.DirNameFrom(exportDir+"/Extensions/"+*include);
|
||||
if ( !fs.DirExists(path) ) fs.MkDir(path);
|
||||
|
||||
fs.CopyFile("./JsPlatform/Runtime/Extensions/"+*include, exportDir+"/Extensions/"+*include);
|
||||
*include = "Extensions/"+*include; //Ensure filename is relative to the export dir.
|
||||
}
|
||||
else if ( fs.FileExists(*include) )
|
||||
{
|
||||
fs.CopyFile(*include, exportDir+"/"+fs.FileNameFrom(*include));
|
||||
*include = fs.FileNameFrom(*include); //Ensure filename is relative to the export dir.
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Could not copy include file " << *include << " (File not found)." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExporterHelper::ExportResources(gd::AbstractFileSystem & fs, gd::Project & project, gd::String exportDir, wxProgressDialog * progressDialog)
|
||||
{
|
||||
gd::ProjectResourcesCopier::CopyAllResourcesTo(project, fs, exportDir, true, progressDialog, false, false);
|
||||
}
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
gd::String ExporterHelper::GetNodeExecutablePath()
|
||||
{
|
||||
std::vector<gd::String> guessPaths;
|
||||
wxString userPath;
|
||||
if ( wxConfigBase::Get()->Read("Paths/Node" , &userPath) && !userPath.empty() )
|
||||
guessPaths.push_back(userPath);
|
||||
else
|
||||
{
|
||||
//Try some common paths.
|
||||
#if defined(WINDOWS)
|
||||
guessPaths.push_back("C:/Program Files/nodejs/node.exe");
|
||||
guessPaths.push_back("C:/Program Files (x86)/nodejs/node.exe");
|
||||
#elif defined(LINUX) || defined(MACOS)
|
||||
guessPaths.push_back("/usr/bin/env/nodejs");
|
||||
guessPaths.push_back("/usr/bin/nodejs");
|
||||
guessPaths.push_back("/usr/local/bin/nodejs");
|
||||
guessPaths.push_back("/usr/bin/env/node");
|
||||
guessPaths.push_back("/usr/bin/node");
|
||||
guessPaths.push_back("/usr/local/bin/node");
|
||||
#else
|
||||
#warning Please complete this so as to return a path to the Node executable.
|
||||
#endif
|
||||
}
|
||||
|
||||
for (size_t i = 0;i<guessPaths.size();++i)
|
||||
{
|
||||
if ( wxFileExists(guessPaths[i]) )
|
||||
return guessPaths[i];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
171
GDJS/GDJS/IDE/ExporterHelper.h
Normal file
171
GDJS/GDJS/IDE/ExporterHelper.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* GDevelop JS Platform
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
|
||||
* This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef EXPORTER_HELPER_H
|
||||
#define EXPORTER_HELPER_H
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "GDCore/IDE/ProjectExporter.h"
|
||||
namespace gd { class Project; }
|
||||
namespace gd { class Layout; }
|
||||
namespace gd { class ExternalLayout; }
|
||||
namespace gd { class AbstractFileSystem; }
|
||||
class wxProgressDialog;
|
||||
|
||||
namespace gdjs
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief Export a project or a layout to a playable HTML5/Javascript based game.
|
||||
*/
|
||||
class ExporterHelper
|
||||
{
|
||||
public:
|
||||
ExporterHelper(gd::AbstractFileSystem & fileSystem) : fs(fileSystem) {};
|
||||
virtual ~ExporterHelper() {};
|
||||
|
||||
/**
|
||||
* \brief Return the error that occurred during the last export.
|
||||
*/
|
||||
const gd::String & GetLastError() const { return lastError; };
|
||||
|
||||
#if !defined(GD_NO_WX_GUI)
|
||||
/**
|
||||
* \brief Try to locate the Node.js executable. (Node must be installed in a standard folder).
|
||||
* \return An empty string if not found, a full path to the node executable otherwise.
|
||||
*/
|
||||
static gd::String GetNodeExecutablePath();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Export a project to JSON
|
||||
*
|
||||
* \param fs The abstract file system to use to write the file
|
||||
* \param project The project to be exported.
|
||||
* \param filename The filename where export the project
|
||||
* \param wrapIntoVariable If not empty, the resulting json will be wrapped in this javascript
|
||||
* variable allowing to use it as a classical javascript object.
|
||||
* \return Empty string if everthing is ok, description of the error otherwise.
|
||||
*/
|
||||
static gd::String ExportToJSON(gd::AbstractFileSystem &fs, const gd::Project &project, gd::String filename,
|
||||
gd::String wrapIntoVariable);
|
||||
|
||||
/**
|
||||
* \brief Copy all the resources of the project to to the export directory, updating the resources filenames.
|
||||
*
|
||||
* \param fs The abstract file system to use
|
||||
* \param project The project with resources to be exported.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param progressDlg Optional wxProgressDialog which will be updated with the progress.
|
||||
*/
|
||||
static void ExportResources(gd::AbstractFileSystem & fs, gd::Project & project, gd::String exportDir,
|
||||
wxProgressDialog * progressDlg = NULL);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add libraries files from Pixi.js or Cocos2d to the list of includes.
|
||||
*/
|
||||
void AddLibsInclude(bool pixiRenderers, bool cocosRenderers, std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Remove include files that are Pixi or Cocos2d renderers.
|
||||
*/
|
||||
void RemoveIncludes(bool pixiRenderers, bool cocosRenderers, std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Copy all the includes files and the standard libraries files to the export directory.
|
||||
*
|
||||
* The includes files are also modified so as to be relative to the export directory
|
||||
* ( Files with absolute filenames are copied into the export directory and their path are stripped ).
|
||||
*
|
||||
* \param includesFiles A vector with filenames to be copied.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param minify If true, the includes files must be merged into one file using Google Closure Compiler.
|
||||
* ( includesFiles parameter will be updated with the new filename )
|
||||
*/
|
||||
bool ExportIncludesAndLibs(std::vector<gd::String> & includesFiles, gd::String exportDir, bool minify);
|
||||
|
||||
/**
|
||||
* \brief Generate the events JS code, and save them to the export directory.
|
||||
*
|
||||
* Files are named "codeX.js", X being the number of the layout in the project.
|
||||
* \param project The project with resources to be exported.
|
||||
* \param outputDir The directory where the events code must be generated.
|
||||
* \param includesFiles A reference to a vector that will be filled with JS files to be exported along with the project.
|
||||
* ( including "codeX.js" files ).
|
||||
*/
|
||||
bool ExportEventsCode(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Copy the external source files used by the game into the export directory, and add them into files
|
||||
* to be included.
|
||||
*
|
||||
* Files are named "ext-codeX.js", X being the index of the external source file in the project.
|
||||
* \param project The project with resources to be exported.
|
||||
* \param outputDir The directory where the events code must be generated.
|
||||
* \param includesFiles A reference to a vector that will be filled with JS files to be exported along with the project.
|
||||
* (including "ext-codeX.js" files).
|
||||
*/
|
||||
bool ExportExternalSourceFiles(gd::Project & project, gd::String outputDir, std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Generate the standard index file and save it to the export directory.
|
||||
*
|
||||
* The includes files must be relative to the export directory.
|
||||
*
|
||||
* \param project The project with layouts to be exported.
|
||||
* \param source The file to be used as a template for the final file.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param includesFiles The JS files to be included in the HTML file. Order is important.
|
||||
* \param additionalSpec JSON string that will be passed to the gdjs.RuntimeGame object.
|
||||
*/
|
||||
bool ExportPixiIndexFile(gd::String source, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec = "");
|
||||
|
||||
/**
|
||||
* \brief Replace the annotations in a index.html file by the specified content.
|
||||
*
|
||||
* \param indexFileContent The source of the index.html file.
|
||||
* \param customCss "<!-- GDJS_CUSTOM_STYLE -->" will be replaced by the content of the string.
|
||||
* \param customHtml "<!-- GDJS_CUSTOM_HTML -->" will be replaced by the content of the string.
|
||||
* \param exportDir The directory where the project must be generated.
|
||||
* \param codeFilesIncludes "<!-- GDJS_CODE_FILES -->" will be replaced by HTML tags to include the filenames contained inside the vector.
|
||||
* \param additionalSpec The string "GDJS_ADDITIONAL_SPEC" surrounded by comments marks will be replaced by the content of the string.
|
||||
*/
|
||||
bool CompleteIndexFile(gd::String & indexFileContent, gd::String customCss, gd::String customHtml, gd::String exportDir, const std::vector<gd::String> & includesFiles, gd::String additionalSpec);
|
||||
|
||||
/**
|
||||
* \brief Generate the Cordova configuration file and save it to the export directory.
|
||||
*
|
||||
* \param project The project to be used to generate the configuration file.
|
||||
* \param exportDir The directory where the config.xml must be created.
|
||||
*/
|
||||
bool ExportCordovaConfigFile(const gd::Project & project, gd::String exportDir);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Generate the base Cocos2d files.
|
||||
*
|
||||
* \param project The project to be used to generate the configuration file.
|
||||
* \param exportDir The directory where the config.xml must be created.
|
||||
*/
|
||||
bool ExportCocos2dFiles(const gd::Project & project, gd::String exportDir, const std::vector<gd::String> & includesFiles);
|
||||
|
||||
/**
|
||||
* \brief Launch all export methods to generate a complete, stand-alone game for previewing.
|
||||
*
|
||||
* \param layout The layout to be previewed.
|
||||
* \param exportDir The directory where the preview must be created.
|
||||
* \param additionalSpec Any additional parameters to be passed to the gdjs.RuntimeGame.
|
||||
* \return true if export was successful.
|
||||
*/
|
||||
bool ExportLayoutForPixiPreview(gd::Project & project, gd::Layout & layout, gd::String exportDir, gd::String additionalSpec);
|
||||
|
||||
gd::AbstractFileSystem & fs; ///< The abstract file system to be used for exportation.
|
||||
gd::String lastError; ///< The last error that occurred.
|
||||
};
|
||||
|
||||
}
|
||||
#endif // EXPORTER_HELPER_H
|
36
GDJS/Runtime/Cocos2d/cocos2d-js-v3.10.js
Normal file
36
GDJS/Runtime/Cocos2d/cocos2d-js-v3.10.js
Normal file
File diff suppressed because one or more lines are too long
30
GDJS/Runtime/Cocos2d/index.html
Normal file
30
GDJS/Runtime/Cocos2d/index.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
<link rel="icon" type="image/GIF" href="res/favicon.ico"/>
|
||||
<meta name="viewport" content="width=480, initial-scale=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes"/>
|
||||
<meta name="full-screen" content="yes"/>
|
||||
<meta name="screen-orientation" content="portrait"/>
|
||||
<meta name="x5-fullscreen" content="true"/>
|
||||
<meta name="360-fullscreen" content="true"/>
|
||||
<style>
|
||||
body, canvas, div {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="padding:0; margin: 0; background: #000;">
|
||||
<script src="res/loading.js"></script>
|
||||
<canvas id="gameCanvas" width="480" height="720"></canvas>
|
||||
|
||||
<script src="cocos2d-js-v3.10.js"></script>
|
||||
<script cocos src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
26
GDJS/Runtime/Cocos2d/main.js
Normal file
26
GDJS/Runtime/Cocos2d/main.js
Normal file
@@ -0,0 +1,26 @@
|
||||
cc.game.onStart = function(){
|
||||
if(!cc.sys.isNative && document.getElementById("cocosLoading")) //If referenced loading.js, please remove it
|
||||
document.body.removeChild(document.getElementById("cocosLoading"));
|
||||
|
||||
gdjs.registerObjects();
|
||||
gdjs.registerBehaviors();
|
||||
gdjs.registerGlobalCallbacks();
|
||||
|
||||
var game = new gdjs.RuntimeGame(gdjs.projectData, {});
|
||||
|
||||
// Pass true to enable retina display, disabled by default to improve performance
|
||||
cc.view.enableRetina(false);
|
||||
// Adjust viewport meta
|
||||
cc.view.adjustViewPort(true);
|
||||
// Setup the resolution policy and design resolution size
|
||||
cc.view.setDesignResolutionSize(game.getDefaultWidth(), game.getDefaultHeight(), cc.ResolutionPolicy.SHOW_ALL);
|
||||
// The game will be resized when browser size change
|
||||
cc.view.resizeWithBrowserSize(true);
|
||||
|
||||
//Load all assets and start the game
|
||||
game.loadAllAssets(function() {
|
||||
game.startGameLoop();
|
||||
});
|
||||
};
|
||||
|
||||
cc.game.run();
|
16
GDJS/Runtime/Cocos2d/project.json
Normal file
16
GDJS/Runtime/Cocos2d/project.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"project_type": "javascript",
|
||||
|
||||
"debugMode" : 1,
|
||||
"showFPS" : true,
|
||||
"frameRate" : 60,
|
||||
"id" : "gameCanvas",
|
||||
"renderMode" : 0,
|
||||
"engineDir":"frameworks/cocos2d-html5",
|
||||
|
||||
"modules" : ["cocos2d"],
|
||||
|
||||
"jsList" : [
|
||||
// GDJS_INCLUDE_FILES
|
||||
]
|
||||
}
|
@@ -25,8 +25,7 @@ gdjs.CocosImageManager.prototype.getTexture = function(imageName) {
|
||||
file = this.getInvalidTexture();
|
||||
}
|
||||
|
||||
//TODO: path
|
||||
var texture = cc.textureCache.addImage('src/JSPreview/' + file);
|
||||
var texture = cc.textureCache.addImage('res/' + file);
|
||||
return texture;
|
||||
};
|
||||
|
||||
@@ -44,7 +43,7 @@ gdjs.CocosImageManager.prototype.isPowerOf2 = function(texture) {
|
||||
gdjs.CocosImageManager.prototype.loadTextures = function(onProgress, onComplete) {
|
||||
var that = this;
|
||||
var files = Object.keys(this._resources).map(function(name) {
|
||||
return 'src/JSPreview/' + that._resources[name].file;
|
||||
return 'res/' + that._resources[name].file;
|
||||
});
|
||||
|
||||
cc.LoaderScene.preload(files, function () {
|
||||
|
@@ -60,7 +60,7 @@ gdjs.RuntimeGameCocosRenderer.prototype.getWindowTitle = function() {
|
||||
|
||||
gdjs.RuntimeGameCocosRenderer.prototype.startGameLoop = function(fn) {
|
||||
this._gameLoopFn = fn;
|
||||
this._gameLoopFn(); //TODO
|
||||
this._gameLoopFn();
|
||||
}
|
||||
|
||||
gdjs.RuntimeGameCocosRenderer.prototype.getDirectorManager = function() {
|
||||
|
@@ -51,7 +51,7 @@ gdjs.RuntimeSceneCocosRenderer.prototype.render = function() {
|
||||
var b = intColor & 255;
|
||||
|
||||
this._cocosBgLayer.setColor(cc.color(r, g, b));
|
||||
this._renderProfileText();
|
||||
//this._renderProfileText(); //Uncomment to display profiling times
|
||||
};
|
||||
|
||||
gdjs.RuntimeSceneCocosRenderer.prototype._renderProfileText = function() {
|
||||
|
@@ -77,10 +77,10 @@ gdjs.SoundManager = gdjs.CocosSoundManager; //Register the class to let the engi
|
||||
gdjs.CocosSoundManager.prototype._getFileFromSoundName = function(soundName) {
|
||||
if (this._availableResources.hasOwnProperty(soundName) &&
|
||||
this._availableResources[soundName].file) {
|
||||
return 'src/JSPreview/' + this._availableResources[soundName].file;
|
||||
return 'res/' + this._availableResources[soundName].file;
|
||||
}
|
||||
|
||||
return 'src/JSPreview/' + soundName;
|
||||
return 'res/' + soundName;
|
||||
}
|
||||
|
||||
gdjs.CocosSoundManager.prototype.playSound = function(soundName, loop, volume, pitch) {
|
||||
|
@@ -20,7 +20,7 @@ gdjs.RuntimeScenePixiRenderer.prototype.onCanvasResized = function() {
|
||||
gdjs.RuntimeScenePixiRenderer.prototype.render = function() {
|
||||
if (!this._pixiRenderer) return;
|
||||
|
||||
this._renderProfileText();
|
||||
//this._renderProfileText(); //Uncomment to display profiling times
|
||||
|
||||
// render the PIXI container of the scene
|
||||
this._pixiRenderer.backgroundColor = this._runtimeScene.getBackgroundColor();
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user