Merge pull request #216 from 4ian/feature/audio-resources

Support for audio resources
This commit is contained in:
Florian Rival
2015-11-28 16:58:59 +01:00
44 changed files with 804 additions and 458 deletions

View File

@@ -489,29 +489,29 @@
<debugger />
<wxsmith version="1">
<resources>
<wxDialog wxs="wxsmith/ChooseVariableDialog.wxs" src="GDCore\IDE\Dialogs\ChooseVariableDialog.cpp" hdr="GDCore\IDE\Dialogs\ChooseVariableDialog.h" fwddecl="0" i18n="1" name="ChooseVariableDialog" language="CPP" />
<wxDialog wxs="wxsmith/ResourceLibraryDialog.wxs" src="GDCore\IDE\Dialogs\ResourceLibraryDialog.cpp" hdr="GDCore\IDE\Dialogs\ResourceLibraryDialog.h" fwddecl="0" i18n="1" name="ResourceLibraryDialog" language="CPP" />
<wxDialog wxs="wxsmith/ProjectExtensionsDialog.wxs" src="GDCore\IDE\Dialogs\ProjectExtensionsDialog.cpp" hdr="GDCore\IDE\Dialogs\ProjectExtensionsDialog.h" fwddecl="0" i18n="1" name="ProjectExtensionsDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseObjectDialog.wxs" src="GDCore\IDE\Dialogs\ChooseObjectDialog.cpp" hdr="GDCore\IDE\Dialogs\ChooseObjectDialog.h" fwddecl="0" i18n="1" name="ChooseObjectDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseBehaviorDialog.wxs" src="GDCore\IDE\Dialogs\ChooseBehaviorDialog.cpp" hdr="GDCore\IDE\Dialogs\ChooseBehaviorDialog.h" fwddecl="0" i18n="1" name="ChooseBehaviorDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseLayerDialog.wxs" src="GDCore\IDE\Dialogs\ChooseLayerDialog.cpp" hdr="GDCore\IDE\Dialogs\ChooseLayerDialog.h" fwddecl="0" i18n="1" name="ChooseLayerDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditExpressionDialog.wxs" src="GDCore\IDE\Dialogs\EditExpressionDialog.cpp" hdr="GDCore\IDE\Dialogs\EditExpressionDialog.h" fwddecl="0" i18n="1" name="EditExpressionDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditStrExpressionDialog.wxs" src="GDCore\IDE\Dialogs\EditStrExpressionDialog.cpp" hdr="GDCore\IDE\Dialogs\EditStrExpressionDialog.h" fwddecl="0" i18n="1" name="EditStrExpressionDialog" language="CPP" />
<wxDialog wxs="wxsmith/AdvancedEntryDialog.wxs" src="GDCore\IDE\Dialogs\AdvancedEntryDialog.cpp" hdr="GDCore\IDE\Dialogs\AdvancedEntryDialog.h" fwddecl="0" i18n="1" name="AdvancedEntryDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseObjectTypeDialog.wxs" src="GDCore\IDE\Dialogs\ChooseObjectTypeDialog.cpp" hdr="GDCore\IDE\Dialogs\ChooseObjectTypeDialog.h" fwddecl="0" i18n="1" name="ChooseObjectTypeDialog" language="CPP" />
<wxPanel wxs="wxsmith/LayoutEditorCanvas.wxs" src="GDCore\IDE\Dialogs\LayoutEditorCanvas.cpp" hdr="GDCore\IDE\Dialogs\LayoutEditorCanvas.h" fwddecl="0" i18n="1" name="LayoutEditorCanvas" language="CPP" />
<wxDialog wxs="wxsmith/GridSetupDialog.wxs" src="GDCore\IDE\Dialogs\GridSetupDialog.cpp" hdr="GDCore\IDE\Dialogs\GridSetupDialog.h" fwddecl="0" i18n="1" name="GridSetupDialog" language="CPP" />
<wxPanel wxs="wxsmith/LayersEditorPanel.wxs" src="GDCore\IDE\Dialogs\LayersEditorPanel.cpp" hdr="GDCore\IDE\Dialogs\LayersEditorPanel.h" fwddecl="0" i18n="1" name="LayersEditorPanel" language="CPP" />
<wxDialog wxs="wxsmith/InstancesAdvancedPasteDialog.wxs" src="GDCore\IDE\Dialogs\InstancesAdvancedPasteDialog.cpp" hdr="GDCore\IDE\Dialogs\InstancesAdvancedPasteDialog.h" fwddecl="0" i18n="1" name="InstancesAdvancedPasteDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseBehaviorTypeDialog.wxs" src="GDCore\IDE\Dialogs\ChooseBehaviorTypeDialog.cpp" hdr="GDCore\IDE\Dialogs\ChooseBehaviorTypeDialog.h" fwddecl="0" i18n="1" name="ChooseBehaviorTypeDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditLayerDialog.wxs" src="GDCore\IDE\Dialogs\EditLayerDialog.cpp" hdr="GDCore\IDE\Dialogs\EditLayerDialog.h" fwddecl="0" i18n="1" name="EditLayerDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditLink.wxs" src="GDCore\IDE\Dialogs\EditLink.cpp" hdr="GDCore\IDE\Dialogs\EditLink.h" fwddecl="0" i18n="1" name="EditLink" language="CPP" />
<wxDialog wxs="wxsmith/EditComment.wxs" src="GDCore\IDE\Dialogs\EditComment.cpp" hdr="GDCore\IDE\Dialogs\EditComment.h" fwddecl="0" i18n="1" name="EditComment" language="CPP" />
<wxDialog wxs="wxsmith/EditForEachEvent.wxs" src="GDCore\IDE\Dialogs\EditForEachEvent.cpp" hdr="GDCore\IDE\Dialogs\EditForEachEvent.h" fwddecl="0" i18n="1" name="EditForEachEvent" language="CPP" />
<wxDialog wxs="wxsmith/EditRepeatEvent.wxs" src="GDCore\IDE\Dialogs\EditRepeatEvent.cpp" hdr="GDCore\IDE\Dialogs\EditRepeatEvent.h" fwddecl="0" i18n="1" name="EditRepeatEvent" language="CPP" />
<wxDialog wxs="wxsmith/ProjectUpdateDialog.wxs" src="GDCore\IDE\Dialogs\ProjectUpdateDialog.cpp" hdr="GDCore\IDE\Dialogs\ProjectUpdateDialog.h" fwddecl="0" i18n="1" name="ProjectUpdateDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseVariableDialog.wxs" src="GDCore/IDE/Dialogs/ChooseVariableDialog.cpp" hdr="GDCore/IDE/Dialogs/ChooseVariableDialog.h" fwddecl="0" i18n="1" name="ChooseVariableDialog" language="CPP" />
<wxDialog wxs="wxsmith/ResourceLibraryDialog.wxs" src="GDCore/IDE/Dialogs/ResourceLibraryDialog.cpp" hdr="GDCore/IDE/Dialogs/ResourceLibraryDialog.h" fwddecl="0" i18n="1" name="ResourceLibraryDialog" language="CPP" />
<wxDialog wxs="wxsmith/ProjectExtensionsDialog.wxs" src="GDCore/IDE/Dialogs/ProjectExtensionsDialog.cpp" hdr="GDCore/IDE/Dialogs/ProjectExtensionsDialog.h" fwddecl="0" i18n="1" name="ProjectExtensionsDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseObjectDialog.wxs" src="GDCore/IDE/Dialogs/ChooseObjectDialog.cpp" hdr="GDCore/IDE/Dialogs/ChooseObjectDialog.h" fwddecl="0" i18n="1" name="ChooseObjectDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseBehaviorDialog.wxs" src="GDCore/IDE/Dialogs/ChooseBehaviorDialog.cpp" hdr="GDCore/IDE/Dialogs/ChooseBehaviorDialog.h" fwddecl="0" i18n="1" name="ChooseBehaviorDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseLayerDialog.wxs" src="GDCore/IDE/Dialogs/ChooseLayerDialog.cpp" hdr="GDCore/IDE/Dialogs/ChooseLayerDialog.h" fwddecl="0" i18n="1" name="ChooseLayerDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditExpressionDialog.wxs" src="GDCore/IDE/Dialogs/EditExpressionDialog.cpp" hdr="GDCore/IDE/Dialogs/EditExpressionDialog.h" fwddecl="0" i18n="1" name="EditExpressionDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditStrExpressionDialog.wxs" src="GDCore/IDE/Dialogs/EditStrExpressionDialog.cpp" hdr="GDCore/IDE/Dialogs/EditStrExpressionDialog.h" fwddecl="0" i18n="1" name="EditStrExpressionDialog" language="CPP" />
<wxDialog wxs="wxsmith/AdvancedEntryDialog.wxs" src="GDCore/IDE/Dialogs/AdvancedEntryDialog.cpp" hdr="GDCore/IDE/Dialogs/AdvancedEntryDialog.h" fwddecl="0" i18n="1" name="AdvancedEntryDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseObjectTypeDialog.wxs" src="GDCore/IDE/Dialogs/ChooseObjectTypeDialog.cpp" hdr="GDCore/IDE/Dialogs/ChooseObjectTypeDialog.h" fwddecl="0" i18n="1" name="ChooseObjectTypeDialog" language="CPP" />
<wxPanel wxs="wxsmith/LayoutEditorCanvas.wxs" src="GDCore/IDE/Dialogs/LayoutEditorCanvas.cpp" hdr="GDCore/IDE/Dialogs/LayoutEditorCanvas.h" fwddecl="0" i18n="1" name="LayoutEditorCanvas" language="CPP" />
<wxDialog wxs="wxsmith/GridSetupDialog.wxs" src="GDCore/IDE/Dialogs/GridSetupDialog.cpp" hdr="GDCore/IDE/Dialogs/GridSetupDialog.h" fwddecl="0" i18n="1" name="GridSetupDialog" language="CPP" />
<wxPanel wxs="wxsmith/LayersEditorPanel.wxs" src="GDCore/IDE/Dialogs/LayersEditorPanel.cpp" hdr="GDCore/IDE/Dialogs/LayersEditorPanel.h" fwddecl="0" i18n="1" name="LayersEditorPanel" language="CPP" />
<wxDialog wxs="wxsmith/InstancesAdvancedPasteDialog.wxs" src="GDCore/IDE/Dialogs/InstancesAdvancedPasteDialog.cpp" hdr="GDCore/IDE/Dialogs/InstancesAdvancedPasteDialog.h" fwddecl="0" i18n="1" name="InstancesAdvancedPasteDialog" language="CPP" />
<wxDialog wxs="wxsmith/ChooseBehaviorTypeDialog.wxs" src="GDCore/IDE/Dialogs/ChooseBehaviorTypeDialog.cpp" hdr="GDCore/IDE/Dialogs/ChooseBehaviorTypeDialog.h" fwddecl="0" i18n="1" name="ChooseBehaviorTypeDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditLayerDialog.wxs" src="GDCore/IDE/Dialogs/EditLayerDialog.cpp" hdr="GDCore/IDE/Dialogs/EditLayerDialog.h" fwddecl="0" i18n="1" name="EditLayerDialog" language="CPP" />
<wxDialog wxs="wxsmith/EditLink.wxs" src="GDCore/IDE/Dialogs/EditLink.cpp" hdr="GDCore/IDE/Dialogs/EditLink.h" fwddecl="0" i18n="1" name="EditLink" language="CPP" />
<wxDialog wxs="wxsmith/EditComment.wxs" src="GDCore/IDE/Dialogs/EditComment.cpp" hdr="GDCore/IDE/Dialogs/EditComment.h" fwddecl="0" i18n="1" name="EditComment" language="CPP" />
<wxDialog wxs="wxsmith/EditForEachEvent.wxs" src="GDCore/IDE/Dialogs/EditForEachEvent.cpp" hdr="GDCore/IDE/Dialogs/EditForEachEvent.h" fwddecl="0" i18n="1" name="EditForEachEvent" language="CPP" />
<wxDialog wxs="wxsmith/EditRepeatEvent.wxs" src="GDCore/IDE/Dialogs/EditRepeatEvent.cpp" hdr="GDCore/IDE/Dialogs/EditRepeatEvent.h" fwddecl="0" i18n="1" name="EditRepeatEvent" language="CPP" />
<wxDialog wxs="wxsmith/ProjectUpdateDialog.wxs" src="GDCore/IDE/Dialogs/ProjectUpdateDialog.cpp" hdr="GDCore/IDE/Dialogs/ProjectUpdateDialog.h" fwddecl="0" i18n="1" name="ProjectUpdateDialog" language="CPP" />
<wxDialog wxs="wxsmith/SpriteObjectEditor.wxs" src="GDCore\Extensions\BuiltinExtensions\SpriteExtension\Dialogs\SpriteObjectEditor.cpp" hdr="GDCore\Extensions\BuiltinExtensions\SpriteExtension\Dialogs\SpriteObjectEditor.h" fwddecl="0" i18n="1" name="SpriteObjectEditor" language="CPP" />
<wxPanel wxs="wxsmith/ResourcesEditor.wxs" src="GDCore\IDE\Dialogs\ResourcesEditor.cpp" hdr="GDCore\IDE\Dialogs\ResourcesEditor.h" fwddecl="0" i18n="1" name="ResourcesEditor" language="CPP" />
<wxPanel wxs="wxsmith/ResourcesEditor.wxs" src="GDCore/IDE/Dialogs/ResourcesEditor.cpp" hdr="GDCore/IDE/Dialogs/ResourcesEditor.h" fwddecl="0" i18n="1" name="ResourcesEditor" language="CPP" />
</resources>
</wxsmith>
</Extensions>

View File

@@ -27,7 +27,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(gd::Plat
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("soundfile", _("Audio file"))
.AddParameter("soundfile", _("Audio file (or audio resource name)"))
.AddParameter("expression", _("Channel identifier"))
.AddParameter("yesorno", _("Repeat the sound"), "",true).SetDefaultValue("no")
.AddParameter("expression", _("Volume (from 0 to 100, 100 by default)"), "",true).SetDefaultValue("100")
@@ -75,7 +75,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(gd::Plat
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("musicfile", _("Audio file"))
.AddParameter("musicfile", _("Audio file (or audio resource name)"))
.AddParameter("expression", _("Channel identifier"))
.AddParameter("yesorno", _("Repeat the sound"), "",true).SetDefaultValue("no")
.AddParameter("expression", _("Volume (from 0 to 100, 100 by default)"), "",true).SetDefaultValue("100")
@@ -220,7 +220,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(gd::Plat
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("soundfile", _("Audio file"))
.AddParameter("soundfile", _("Audio file (or audio resource name)"))
.AddParameter("yesorno", _("Repeat the sound"), "",true).SetDefaultValue("no")
.AddParameter("expression", _("Volume (from 0 to 100, 100 by default)"), "",true).SetDefaultValue("100")
.AddParameter("expression", _("Pitch (speed) (1 by default)"), "",true).SetDefaultValue("1")
@@ -234,7 +234,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(gd::Plat
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("musicfile", _("Audio file"))
.AddParameter("musicfile", _("Audio file (or audio resource name)"))
.AddParameter("yesorno", _("Repeat the sound"), "",true).SetDefaultValue("no")
.AddParameter("expression", _("Volume (from 0 to 100, 100 by default)"), "",true).SetDefaultValue("100")
.AddParameter("expression", _("Pitch (speed) (1 by default)"), "",true).SetDefaultValue("1")

View File

@@ -1029,7 +1029,7 @@ bool DndTextSpriteObjectEditor::OnDropText(wxCoord x, wxCoord y, const wxString&
//Add ressources dragged from the library dialog to the project.
std::vector<gd::String> files;
for (std::size_t i = 2;i<command.size();++i) files.push_back(command[i]);
std::vector<gd::String> names = editor.resourcesEditorPnl->CopyAndAddResources(files, command[1]);
std::vector<gd::String> names = editor.resourcesEditorPnl->CopyAndAddResources(files, command[1], "image");
//And add them as usual to the animation.
for (std::size_t i = 0;i<names.size();++i)

View File

@@ -30,7 +30,7 @@ bool DndTextResourcesEditor::OnDropText(wxCoord x, wxCoord y, const wxString& te
for (std::size_t i = 2;i<command.size();++i)
files.push_back(command[i]);
editor.CopyAndAddResources(files, command[1]);
editor.CopyAndAddResources(files, command[1], "image");
}
else
std::cout << "Drop was triggered but the command was not understood" << std::endl;

View File

@@ -12,6 +12,7 @@
#include "GDCore/Tools/Localization.h"
//(*InternalHeaders(ResourcesEditor)
#include <wx/bitmap.h>
#include <wx/intl.h>
#include <wx/image.h>
#include <wx/string.h>
//*)
@@ -69,15 +70,18 @@ const long ResourcesEditor::ID_PROPGRID = wxNewId();
const long ResourcesEditor::ID_PANEL2 = wxNewId();
const long ResourcesEditor::idMenuMod = wxNewId();
const long ResourcesEditor::idMenuAjouter = wxNewId();
const long ResourcesEditor::idMenuAddAudio = wxNewId();
const long ResourcesEditor::idMenuDel = wxNewId();
const long ResourcesEditor::ID_MENUITEM9 = wxNewId();
const long ResourcesEditor::idMoveUp = wxNewId();
const long ResourcesEditor::idMoveDown = wxNewId();
const long ResourcesEditor::ID_MENUITEM1 = wxNewId();
const long ResourcesEditor::ID_MENUITEM10 = wxNewId();
const long ResourcesEditor::ID_MENUITEM2 = wxNewId();
const long ResourcesEditor::ID_MENUITEM3 = wxNewId();
const long ResourcesEditor::ID_MENUITEM5 = wxNewId();
const long ResourcesEditor::ID_MENUITEM6 = wxNewId();
const long ResourcesEditor::ID_MENUITEM11 = wxNewId();
const long ResourcesEditor::ID_MENUITEM5 = wxNewId();
const long ResourcesEditor::ID_MENUITEM4 = wxNewId();
const long ResourcesEditor::ID_MENUITEM7 = wxNewId();
const long ResourcesEditor::ID_MENUITEM8 = wxNewId();
@@ -143,9 +147,9 @@ resourceLibraryDialog(new gd::ResourceLibraryDialog(this))
corePanel->SetSizer(FlexGridSizer3);
FlexGridSizer3->Fit(corePanel);
FlexGridSizer3->SetSizeHints(corePanel);
AuiManager1->AddPane(corePanel, wxAuiPaneInfo().Name(_T("corePane")).Caption(_("Pane caption")).CaptionVisible(false).CloseButton(false).Center());
AuiManager1->AddPane(corePanel, wxAuiPaneInfo().Name(_T("corePane")).DefaultPane().Caption(_("Pane caption")).CaptionVisible(false).CloseButton(false).Center());
previewPanel = new wxPanel(this, ID_PANEL3, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL, _T("ID_PANEL3"));
AuiManager1->AddPane(previewPanel, wxAuiPaneInfo().Name(_T("previewPane")).Caption(_("Preview")).CaptionVisible().Right());
AuiManager1->AddPane(previewPanel, wxAuiPaneInfo().Name(_T("previewPane")).DefaultPane().Caption(_("Preview")).CaptionVisible().Right());
propertiesPanel = new wxPanel(this, ID_PANEL2, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL2"));
FlexGridSizer1 = new wxFlexGridSizer(0, 3, 0, 0);
FlexGridSizer1->AddGrowableCol(0);
@@ -155,7 +159,7 @@ resourceLibraryDialog(new gd::ResourceLibraryDialog(this))
propertiesPanel->SetSizer(FlexGridSizer1);
FlexGridSizer1->Fit(propertiesPanel);
FlexGridSizer1->SetSizeHints(propertiesPanel);
AuiManager1->AddPane(propertiesPanel, wxAuiPaneInfo().Name(_T("propertiesPane")).Caption(_("Properties")).CaptionVisible().Position(1).Right());
AuiManager1->AddPane(propertiesPanel, wxAuiPaneInfo().Name(_T("propertiesPane")).DefaultPane().Caption(_("Properties")).CaptionVisible().Position(1).Right());
AuiManager1->Update();
MenuItem3 = new wxMenuItem((&ContextMenu), idMenuMod, _("Rename\tF2"), wxEmptyString, wxITEM_NORMAL);
MenuItem3->SetBitmap(gd::SkinHelper::GetIcon("rename", 16));
@@ -164,7 +168,10 @@ resourceLibraryDialog(new gd::ResourceLibraryDialog(this))
MenuItem1 = new wxMenuItem((&ContextMenu), idMenuAjouter, _("Add an image"), wxEmptyString, wxITEM_NORMAL);
MenuItem1->SetBitmap(gd::SkinHelper::GetIcon("add", 16));
ContextMenu.Append(MenuItem1);
deleteImageItem = new wxMenuItem((&ContextMenu), idMenuDel, _("Delete the image\tDEL"), wxEmptyString, wxITEM_NORMAL);
MenuItem4 = new wxMenuItem((&ContextMenu), idMenuAddAudio, _("Add a sound/music"), wxEmptyString, wxITEM_NORMAL);
ContextMenu.Append(MenuItem4);
ContextMenu.AppendSeparator();
deleteImageItem = new wxMenuItem((&ContextMenu), idMenuDel, _("Delete\tDEL"), wxEmptyString, wxITEM_NORMAL);
deleteImageItem->SetBitmap(gd::SkinHelper::GetIcon("delete", 16));
ContextMenu.Append(deleteImageItem);
MenuItem14 = new wxMenuItem((&ContextMenu), ID_MENUITEM9, _("Remove from folder only"), wxEmptyString, wxITEM_NORMAL);
@@ -179,6 +186,8 @@ resourceLibraryDialog(new gd::ResourceLibraryDialog(this))
MenuItem2 = new wxMenuItem((&emptyMenu), ID_MENUITEM1, _("Add an image"), wxEmptyString, wxITEM_NORMAL);
MenuItem2->SetBitmap(gd::SkinHelper::GetIcon("add", 16));
emptyMenu.Append(MenuItem2);
MenuItem15 = new wxMenuItem((&emptyMenu), ID_MENUITEM10, _("Add a sound/music"), wxEmptyString, wxITEM_NORMAL);
emptyMenu.Append(MenuItem15);
emptyMenu.AppendSeparator();
MenuItem6 = new wxMenuItem((&emptyMenu), ID_MENUITEM2, _("Add a folder"), wxEmptyString, wxITEM_NORMAL);
MenuItem6->SetBitmap(wxBitmap(wxImage(_T("res/foldericon.png"))));
@@ -186,13 +195,16 @@ resourceLibraryDialog(new gd::ResourceLibraryDialog(this))
MenuItem9 = new wxMenuItem((&folderMenu), ID_MENUITEM3, _("Rename\tF2"), wxEmptyString, wxITEM_NORMAL);
MenuItem9->SetBitmap(gd::SkinHelper::GetIcon("rename", 16));
folderMenu.Append(MenuItem9);
MenuItem13 = new wxMenuItem((&folderMenu), ID_MENUITEM5, _("Delete\tDEL"), wxEmptyString, wxITEM_NORMAL);
MenuItem13->SetBitmap(gd::SkinHelper::GetIcon("delete", 16));
folderMenu.Append(MenuItem13);
folderMenu.AppendSeparator();
MenuItem10 = new wxMenuItem((&folderMenu), ID_MENUITEM6, _("Add an image"), wxEmptyString, wxITEM_NORMAL);
MenuItem10->SetBitmap(gd::SkinHelper::GetIcon("add", 16));
folderMenu.Append(MenuItem10);
MenuItem16 = new wxMenuItem((&folderMenu), ID_MENUITEM11, _("Add a sound/music"), wxEmptyString, wxITEM_NORMAL);
folderMenu.Append(MenuItem16);
folderMenu.AppendSeparator();
MenuItem13 = new wxMenuItem((&folderMenu), ID_MENUITEM5, _("Delete\tDEL"), wxEmptyString, wxITEM_NORMAL);
MenuItem13->SetBitmap(gd::SkinHelper::GetIcon("delete", 16));
folderMenu.Append(MenuItem13);
folderMenu.AppendSeparator();
MenuItem5 = new wxMenuItem((&folderMenu), ID_MENUITEM4, _("Add a folder"), wxEmptyString, wxITEM_NORMAL);
MenuItem5->SetBitmap(wxBitmap(wxImage(_T("res/foldericon.png"))));
@@ -219,15 +231,18 @@ resourceLibraryDialog(new gd::ResourceLibraryDialog(this))
previewPanel->Connect(wxEVT_SIZE,(wxObjectEventFunction)&ResourcesEditor::OnpreviewPanelResize,0,this);
Connect(idMenuMod,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnModNameImageBtClick);
Connect(idMenuAjouter,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddImageBtClick);
Connect(idMenuAddAudio,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddAudioSelected);
Connect(idMenuDel,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnDelImageBtClick);
Connect(ID_MENUITEM9,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnremoveFolderOnlySelected);
Connect(idMoveUp,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnMoveUpSelected);
Connect(idMoveDown,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnMoveDownSelected);
Connect(ID_MENUITEM1,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddImageBtClick);
Connect(ID_MENUITEM10,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddAudioSelected);
Connect(ID_MENUITEM2,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddFolderSelected);
Connect(ID_MENUITEM3,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnModNameImageBtClick);
Connect(ID_MENUITEM5,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnDelImageBtClick);
Connect(ID_MENUITEM6,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddImageBtClick);
Connect(ID_MENUITEM11,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddAudioSelected);
Connect(ID_MENUITEM5,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnDelImageBtClick);
Connect(ID_MENUITEM4,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnAddFolderSelected);
Connect(ID_MENUITEM7,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnMoveUpSelected);
Connect(ID_MENUITEM8,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&ResourcesEditor::OnMoveDownSelected);
@@ -348,29 +363,45 @@ wxTreeItemId ResourcesEditor::GetSelectedFolderItem()
*/
void ResourcesEditor::OnAddImageBtClick( wxCommandEvent& event )
{
wxFileDialog FileDialog( this, _("Choose one or more images to add"), "", "", _("Supported image files|*.jpg;*.png|All files|*.*"), wxFD_MULTIPLE|wxFD_PREVIEW );
wxFileDialog fileDialog( this, _("Choose one or more images to add"), "", "", _("Supported image files|*.jpg;*.png|All files|*.*"), wxFD_MULTIPLE|wxFD_PREVIEW );
if ( fileDialog.ShowModal() != wxID_OK ) return;
if ( FileDialog.ShowModal() == wxID_OK )
{
gd::LogStatus( _( "Adding images" ) );
gd::LogStatus( _( "Adding images" ) );
wxArrayString files;
FileDialog.GetPaths( files );
gd::String imageNonAjoutees;
wxArrayString files;
fileDialog.GetPaths( files );
gd::String imageNonAjoutees;
//Add each image to images list and to folder if any
std::vector < gd::String > filenames;
for ( std::size_t i = 0; i < files.GetCount();++i )
filenames.push_back(files[i]);
AddResources(filenames);
gd::LogStatus( _( "Resources successfully added" ) );
}
std::vector < gd::String > filenames;
for ( std::size_t i = 0; i < files.GetCount();++i )
filenames.push_back(files[i]);
AddResources(filenames, "image");
gd::LogStatus( _( "Resources successfully added" ) );
}
std::vector<gd::String> ResourcesEditor::CopyAndAddResources(std::vector<gd::String> filenames, const gd::String & destinationDirStr)
void ResourcesEditor::OnAddAudioSelected(wxCommandEvent& event)
{
wxFileDialog fileDialog( this, _("Choose one or more audio files to add"), "", "", _("Supported audio files|*.ogg;*.mp3;*.wav|All files|*.*"), wxFD_MULTIPLE|wxFD_PREVIEW );
if ( fileDialog.ShowModal() != wxID_OK ) return;
gd::LogStatus( _( "Adding audio files" ) );
wxArrayString files;
fileDialog.GetPaths( files );
gd::String imageNonAjoutees;
std::vector < gd::String > filenames;
for ( std::size_t i = 0; i < files.GetCount();++i )
filenames.push_back(files[i]);
AddResources(filenames, "audio");
gd::LogStatus( _( "Resources successfully added" ) );
}
std::vector<gd::String> ResourcesEditor::CopyAndAddResources(std::vector<gd::String> filenames,
const gd::String & destinationDirStr, const gd::String & kind)
{
if ( !project.GetProjectFile().empty() ) //If game is not saved, we keep absolute filenames and do not copy resources.
{
@@ -392,10 +423,10 @@ std::vector<gd::String> ResourcesEditor::CopyAndAddResources(std::vector<gd::Str
}
}
return AddResources(filenames);
return AddResources(filenames, kind);
}
std::vector<gd::String> ResourcesEditor::AddResources(const std::vector<gd::String> & filenames)
std::vector<gd::String> ResourcesEditor::AddResources(const std::vector<gd::String> & filenames, const gd::String & kind)
{
std::vector<gd::String> resourceNames;
gd::String alreadyExistingResources;
@@ -423,7 +454,7 @@ std::vector<gd::String> ResourcesEditor::AddResources(const std::vector<gd::Stri
gd::LogStatus( _( "Adding " ) + name );
//Add to all images
if ( project.GetResourcesManager().AddResource(name, file.GetFullPath()) )
if ( project.GetResourcesManager().AddResource(name, file.GetFullPath(), kind) )
{
for ( std::size_t j = 0; j < project.GetUsedPlatforms().size();++j)
project.GetUsedPlatforms()[j]->GetChangesNotifier().OnResourceModified(project, name);
@@ -945,7 +976,7 @@ void ResourcesEditor::Refresh()
void ResourcesEditor::OnDeleteUnusedFiles( wxCommandEvent& event )
{
std::vector<gd::String> unusedImages =
gd::ProjectResourcesAdder::GetAllUselessResources(project);
gd::ProjectResourcesAdder::GetAllUselessImages(project);
//Construct corresponding wxArrayString with unused images
wxArrayString imagesNotUsed;

View File

@@ -44,7 +44,7 @@ public:
* Ask the resources editor to add the resources contained into \a filenames.
* \return A vector containing the name of the added resources.
*/
std::vector<gd::String> AddResources(const std::vector<gd::String> & filenames);
std::vector<gd::String> AddResources(const std::vector<gd::String> & filenames, const gd::String & kind);
/**
* Ask the resources editor to add the resources contained into \a filenames.
@@ -52,7 +52,7 @@ public:
* (which is relative to the project directory) before being added to the project.
* \return A vector containing the name of the added resources.
*/
std::vector<gd::String> CopyAndAddResources(std::vector<gd::String> filenames, const gd::String & destinationDir);
std::vector<gd::String> CopyAndAddResources(std::vector<gd::String> filenames, const gd::String & destinationDir, const gd::String & kind);
/**
* \brief Called by DndTextResourcesEditor when one or more resources from the editor has been dropped
@@ -76,8 +76,10 @@ public:
wxMenuItem* MenuItem5;
wxMenuItem* MenuItem2;
wxTreeCtrl* resourcesTree;
wxMenuItem* MenuItem4;
wxMenuItem* MenuItem14;
wxMenuItem* MenuItem11;
wxMenuItem* MenuItem15;
wxMenuItem* MenuItem13;
wxMenu ContextMenu;
wxMenuItem* MenuItem10;
@@ -86,6 +88,7 @@ public:
wxMenuItem* MenuItem6;
wxPanel* previewPanel;
wxPanel* propertiesPanel;
wxMenuItem* MenuItem16;
wxMenuItem* MenuItem9;
wxMenu folderMenu;
//*)
@@ -126,15 +129,18 @@ protected:
static const long ID_PANEL2;
static const long idMenuMod;
static const long idMenuAjouter;
static const long idMenuAddAudio;
static const long idMenuDel;
static const long ID_MENUITEM9;
static const long idMoveUp;
static const long idMoveDown;
static const long ID_MENUITEM1;
static const long ID_MENUITEM10;
static const long ID_MENUITEM2;
static const long ID_MENUITEM3;
static const long ID_MENUITEM5;
static const long ID_MENUITEM6;
static const long ID_MENUITEM11;
static const long ID_MENUITEM5;
static const long ID_MENUITEM4;
static const long ID_MENUITEM7;
static const long ID_MENUITEM8;
@@ -193,6 +199,7 @@ private:
void OnresourcesTreeKeyDown(wxTreeEvent& event);
void OnresourcesTreeEndDrag(wxTreeEvent& event);
void OnAddFromLibraryToolbarBtClick(wxCommandEvent& event);
void OnAddAudioSelected(wxCommandEvent& event);
//*)
void OnMoreOptions( wxCommandEvent& event );
void OnAddFromLibraryBtClick(wxCommandEvent& event);

View File

@@ -21,6 +21,44 @@ using namespace std;
namespace gd
{
void ArbitraryResourceWorker::ExposeImage(gd::String & imageName)
{
//Nothing to do, the image is a referece to a resource that
//is already exposed.
};
void ArbitraryResourceWorker::ExposeAudio(gd::String & audioName)
{
for(auto resources : GetResources())
{
if (!resources) continue;
if (resources->HasResource(audioName) &&
resources->GetResource(audioName).GetKind() == "audio")
{
//Nothing to do, the audio is a reference to a resource that
//is already exposed.
return;
}
}
ExposeFile(audioName);
};
void ArbitraryResourceWorker::ExposeResources(gd::ResourcesManager * resourcesManager)
{
if (!resourcesManager) return;
resourcesManagers.push_back(resourcesManager);
std::vector<gd::String> resources = resourcesManager->GetAllResourcesList();
for ( std::size_t i = 0;i < resources.size() ;i++ )
{
if ( resourcesManager->GetResource(resources[i]).UseFile() )
ExposeResource(resourcesManager->GetResource(resources[i]));
}
}
void ArbitraryResourceWorker::ExposeResource(gd::Resource & resource)
{
if (!resource.UseFile()) return;

View File

@@ -15,6 +15,7 @@ namespace gd {class BaseEvent;}
namespace gd {class Project;}
namespace gd {class EventsList;}
namespace gd {class Resource;}
namespace gd {class ResourcesManager;}
namespace gd
{
@@ -33,14 +34,50 @@ namespace gd
class GD_CORE_API ArbitraryResourceWorker
{
public:
ArbitraryResourceWorker() {};
virtual ~ArbitraryResourceWorker();
virtual void ExposeImage(gd::String & imageName) = 0;
virtual void ExposeShader(gd::String & shaderName) = 0;
/**
* \brief Expose a set of resources.
* \note When launching an ArbitraryResourceWorker, this should be called first
* to ensure that resources are known so that images, shaders & audio can make reference
* to them.
*/
void ExposeResources(gd::ResourcesManager * resourcesManager);
/**
* \brief Expose an image, which is always a reference to a "image" resource.
*/
virtual void ExposeImage(gd::String & imageName);
/**
* \brief Expose an audio, which is either a reference to an "audio" resource,
* or a filename if no resource with this name exists.
*/
virtual void ExposeAudio(gd::String & audioName);
/**
* \brief Expose a shader.
* \warn Currently unsupported.
*/
virtual void ExposeShader(gd::String & shaderName) {};
/**
* \brief Expose a raw filename.
*/
virtual void ExposeFile(gd::String & resourceFileName) = 0;
void ExposeResource(gd::Resource & resource);
protected:
const std::vector<gd::ResourcesManager *> & GetResources() { return resourcesManagers; };
private:
/**
* \brief Expose a resource: resources that have a file are
* exposed as file (see ExposeFile).
*/
void ExposeResource(gd::Resource & resource);
std::vector<gd::ResourcesManager *> resourcesManagers;
};
/**

View File

@@ -38,9 +38,8 @@ public:
std::set<gd::String> & GetAllUsedImages() { return allUsedImages; };
virtual void ExposeFile(gd::String & resource) {};
virtual void ExposeFile(gd::String & resource) { /*Don't care, we just list images*/ };
virtual void ExposeImage(gd::String & imageName) {allUsedImages.insert(imageName);};
virtual void ExposeShader(gd::String & shaderName) {};
protected:
std::set<gd::String> allUsedImages;

View File

@@ -27,14 +27,14 @@ bool ProjectResourcesAdder::AddAllMissingImages(gd::Project & project)
if (!resourcesManager.HasResource(*it))
{
std::cout << "Adding missing resource \""<<*it<<"\"to the project.";
resourcesManager.AddResource(*it, /*filename=*/*it); //Note that AddResource add a image resource by default.
resourcesManager.AddResource(*it, /*filename=*/*it, "image");
}
}
return true;
}
std::vector<gd::String> ProjectResourcesAdder::GetAllUselessResources(gd::Project & project)
std::vector<gd::String> ProjectResourcesAdder::GetAllUselessImages(gd::Project & project)
{
std::vector<gd::String> unusedResources;
@@ -58,9 +58,9 @@ std::vector<gd::String> ProjectResourcesAdder::GetAllUselessResources(gd::Projec
return unusedResources;
}
void ProjectResourcesAdder::RemoveAllUselessResources(gd::Project & project)
void ProjectResourcesAdder::RemoveAllUselessImages(gd::Project & project)
{
std::vector<gd::String> unusedResources = GetAllUselessResources(project);
std::vector<gd::String> unusedResources = GetAllUselessImages(project);
for(std::size_t i = 0;i < unusedResources.size();++i) {
project.GetResourcesManager().RemoveResource(unusedResources[i]);

View File

@@ -41,7 +41,7 @@ public:
*
* \return A vector containing the name of all unused resources
*/
static std::vector<gd::String> GetAllUselessResources(gd::Project & project);
static std::vector<gd::String> GetAllUselessImages(gd::Project & project);
/**
* \brief Remove all resources that are not used
@@ -52,7 +52,7 @@ public:
*
* \param project The project to be crawled.
*/
static void RemoveAllUselessResources(gd::Project & project);
static void RemoveAllUselessImages(gd::Project & project);
};
}

View File

@@ -36,9 +36,6 @@ public:
*/
virtual void ExposeFile(gd::String & resource);
virtual void ExposeImage(gd::String & imageName) {};
virtual void ExposeShader(gd::String & shaderName) {};
private:
bool hasAbsoluteFilenames;
AbstractFileSystem & fs;

View File

@@ -58,9 +58,6 @@ public:
*/
virtual void ExposeFile(gd::String & resource);
virtual void ExposeImage(gd::String & imageName) {};
virtual void ExposeShader(gd::String & shaderName) {};
protected:
void SetNewFilename(gd::String oldFilename, gd::String newFilename);

View File

@@ -4,7 +4,7 @@
* This project is released under the MIT License.
*/
#include "GDCore/Project/ImageManager.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/ResourcesManager.h"
#include "GDCore/Project/ResourcesLoader.h"
#include "GDCore/Tools/InvalidImage.h"
#include "GDCore/Project/ResourcesManager.h"
@@ -14,7 +14,7 @@ namespace gd
{
ImageManager::ImageManager() :
game(NULL)
resourcesManager(NULL)
{
#if !defined(EMSCRIPTEN)
badTexture = std::shared_ptr<SFMLTextureWrapper>(new SFMLTextureWrapper);
@@ -26,9 +26,9 @@ ImageManager::ImageManager() :
std::shared_ptr<SFMLTextureWrapper> ImageManager::GetSFMLTexture(const gd::String & name) const
{
if ( !game )
if ( !resourcesManager )
{
std::cout << "Image manager has no game associated with.";
std::cout << "ImageManager has no ResourcesManager associated with.";
return badTexture;
}
@@ -40,7 +40,7 @@ std::shared_ptr<SFMLTextureWrapper> ImageManager::GetSFMLTexture(const gd::Strin
//Load only an image when necessary
try
{
ImageResource & image = dynamic_cast<ImageResource&>(game->GetResourcesManager().GetResource(name));
ImageResource & image = dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
std::shared_ptr<SFMLTextureWrapper> texture(new SFMLTextureWrapper(ResourcesLoader::Get()->LoadSFMLTexture( image.GetFile() )));
texture->texture.setSmooth(image.smooth);
@@ -80,9 +80,9 @@ void ImageManager::SetSFMLTextureAsPermanentlyLoaded(const gd::String & name, st
void ImageManager::ReloadImage(const gd::String & name) const
{
if ( !game )
if ( !resourcesManager )
{
std::cout << "Image manager has no game associated with.";
std::cout << "ImageManager has no ResourcesManager associated with.";
return;
}
@@ -94,7 +94,7 @@ void ImageManager::ReloadImage(const gd::String & name) const
try
{
ImageResource & image = dynamic_cast<ImageResource&>(game->GetResourcesManager().GetResource(name));
ImageResource & image = dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
std::cout << "ImageManager: Reload " << name << std::endl;
@@ -113,12 +113,6 @@ void ImageManager::ReloadImage(const gd::String & name) const
std::shared_ptr<OpenGLTextureWrapper> ImageManager::GetOpenGLTexture(const gd::String & name) const
{
if ( !game )
{
std::cout << "Image manager has no game associated with.";
return badOpenGLTexture;
}
if ( alreadyLoadedOpenGLTextures.find(name) != alreadyLoadedOpenGLTextures.end() && !alreadyLoadedOpenGLTextures.find(name)->second.expired() )
return alreadyLoadedOpenGLTextures.find(name)->second.lock();
@@ -131,9 +125,9 @@ std::shared_ptr<OpenGLTextureWrapper> ImageManager::GetOpenGLTexture(const gd::S
void ImageManager::LoadPermanentImages()
{
if ( !game )
if ( !resourcesManager )
{
std::cout << "Image manager has no game associated with.";
std::cout << "ImageManager has no ResourcesManager associated with.";
return;
}
@@ -141,12 +135,12 @@ void ImageManager::LoadPermanentImages()
//so as not to unload images that could be still present.
std::map < gd::String, std::shared_ptr<SFMLTextureWrapper> > newPermanentlyLoadedImages;
std::vector<gd::String> resources = game->GetResourcesManager().GetAllResourcesList();
std::vector<gd::String> resources = resourcesManager->GetAllResourcesList();
for ( std::size_t i = 0;i <resources.size();i++ )
{
try
{
ImageResource & image = dynamic_cast<ImageResource&>(game->GetResourcesManager().GetResource(resources[i]));
ImageResource & image = dynamic_cast<ImageResource&>(resourcesManager->GetResource(resources[i]));
if ( image.alwaysLoaded )
newPermanentlyLoadedImages[image.GetName()] = GetSFMLTexture(image.GetName());
@@ -171,7 +165,7 @@ void ImageManager::PreventImagesUnloading()
void ImageManager::EnableImagesUnloading()
{
preventUnloading = false;
unloadingPreventer.clear(); //Images which are not used anymore will thus be destroyed ( As no shared pointer will be pointing to them ).
unloadingPreventer.clear(); //Images which are not used anymore will thus be destroyed (As no shared pointer will be pointing to them).
}
#endif

View File

@@ -15,7 +15,7 @@
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
namespace gd { class Project; }
namespace gd { class ResourcesManager; }
class OpenGLTextureWrapper;
class SFMLTextureWrapper;
#undef LoadImage //thx windows.h
@@ -26,7 +26,8 @@ namespace gd
/**
* \brief Manage images for the IDE as well as at runtime for GD C++ Platform, providing an easy way to get SFML images or OpenGL textures.
*
* Image manager is used by objects to obtain their images from the image name.<br>
* Image manager is used by objects to obtain their images from the image name.
*
* Images are loaded dynamically when necessary, and are unloaded if there is no
* more shared_ptr pointing on an image.
*
@@ -57,9 +58,9 @@ public:
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture(const gd::String & name) const;
/**
* \brief Set the project associated with the image manager.
* \brief Set the gd::ResourcesManager used by the ImageManager.
*/
void SetGame(gd::Project * game_) { game = game_; }
void SetResourcesManager(gd::ResourcesManager * resourcesManager_) { resourcesManager = resourcesManager_; }
/**
* \brief Load all images of the project which are flagged as alwaysLoaded.
@@ -119,7 +120,7 @@ private:
mutable std::shared_ptr<SFMLTextureWrapper> badTexture;
mutable std::shared_ptr<OpenGLTextureWrapper> badOpenGLTexture;
gd::Project * game;
gd::ResourcesManager * resourcesManager;
};
}
@@ -132,7 +133,7 @@ private:
*/
class GD_CORE_API SFMLTextureWrapper
{
public :
public:
SFMLTextureWrapper(const sf::Texture & texture);
SFMLTextureWrapper();
~SFMLTextureWrapper();
@@ -149,13 +150,13 @@ public :
*/
class GD_CORE_API OpenGLTextureWrapper
{
public :
public:
OpenGLTextureWrapper(std::shared_ptr<SFMLTextureWrapper> sfmlTexture_);
OpenGLTextureWrapper() : texture(0) {};
~OpenGLTextureWrapper();
inline GLuint GetOpenGLTexture() const { return texture; }
private :
private:
std::shared_ptr<SFMLTextureWrapper> sfmlTexture;
GLuint texture;
};

View File

@@ -75,7 +75,7 @@ Project::Project() :
dirty(false)
#endif
{
imageManager->SetGame(this);
imageManager->SetResourcesManager(&resourcesManager);
#if defined(GD_IDE_ONLY)
//Game use builtin extensions by default
extensionsUsed.push_back("BuiltinObject");
@@ -810,12 +810,7 @@ gd::String Project::GetBadObjectNameWarning()
void Project::ExposeResources(gd::ArbitraryResourceWorker & worker)
{
//Add project resources
std::vector<gd::String> resources = GetResourcesManager().GetAllResourcesList();
for ( std::size_t i = 0;i < resources.size() ;i++ )
{
if ( GetResourcesManager().GetResource(resources[i]).UseFile() )
worker.ExposeResource(GetResourcesManager().GetResource(resources[i]));
}
worker.ExposeResources(&GetResourcesManager());
#if !defined(GD_NO_WX_GUI)
gd::SafeYield::Do();
#endif
@@ -1037,7 +1032,7 @@ void Project::Init(const gd::Project & game)
//Resources
resourcesManager = game.resourcesManager;
imageManager = std::shared_ptr<ImageManager>(new ImageManager(*game.imageManager));
imageManager->SetGame(this);
imageManager->SetResourcesManager(&resourcesManager);
GetObjects().clear();
for (std::size_t i =0;i<game.GetObjects().size();++i)

View File

@@ -86,11 +86,11 @@ const Resource & ResourcesManager::GetResource(const gd::String & name) const
std::shared_ptr<Resource> ResourcesManager::CreateResource(const gd::String & kind)
{
if (kind == "image")
{
return std::shared_ptr<Resource>(new ImageResource);
}
else if (kind == "audio")
return std::shared_ptr<Resource>(new AudioResource);
std::cout << "Bad resource created ( type: " << kind << ")" << std::endl;
std::cout << "Bad resource created (type: " << kind << ")" << std::endl;
return std::shared_ptr<Resource>(new Resource);
}
@@ -133,15 +133,15 @@ bool ResourcesManager::AddResource(const gd::Resource & resource)
return true;
}
bool ResourcesManager::AddResource(const gd::String & name, const gd::String & filename)
bool ResourcesManager::AddResource(const gd::String & name, const gd::String & filename, const gd::String & kind)
{
if ( HasResource(name) ) return false;
std::shared_ptr<ImageResource> image(new ImageResource);
image->SetFile(filename);
image->SetName(name);
std::shared_ptr<Resource> res = CreateResource(kind);
res->SetFile(filename);
res->SetName(name);
resources.push_back(image);
resources.push_back(res);
return true;
}
@@ -618,6 +618,29 @@ void ImageResource::SerializeTo(SerializerElement & element) const
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile()); //Keep the resource path in the current locale (but save it in UTF8 for compatibility on other OSes)
}
#endif
void AudioResource::SetFile(const gd::String & newFile)
{
file = newFile;
//Convert all backslash to slashs.
while (file.find('\\') != gd::String::npos)
file.replace(file.find('\\'), 1, "/");
}
void AudioResource::UnserializeFrom(const SerializerElement & element)
{
SetUserAdded( element.GetBoolAttribute("userAdded") );
SetFile(element.GetStringAttribute("file"));
}
#if defined(GD_IDE_ONLY)
void AudioResource::SerializeTo(SerializerElement & element) const
{
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile()); //Keep the resource path in the current locale (but save it in UTF8 for compatibility on other OSes)
}
ResourceFolder::ResourceFolder(const ResourceFolder & other)

View File

@@ -220,6 +220,34 @@ private:
gd::String file;
};
/**
* \brief Describe an audio file used by a project.
*
* \see Resource
* \ingroup ResourcesManagement
*/
class GD_CORE_API AudioResource : public Resource
{
public:
AudioResource() : Resource() { SetKind("audio"); };
virtual ~AudioResource() {};
virtual AudioResource* Clone() const { return new AudioResource(*this);}
virtual const gd::String & GetFile() const {return file;};
virtual void SetFile(const gd::String & newFile);
#if defined(GD_IDE_ONLY)
virtual bool UseFile() { return true; }
void SerializeTo(SerializerElement & element) const;
#endif
void UnserializeFrom(const SerializerElement & element);
private:
gd::String file;
};
/**
* \brief Inventory all resources used by a project
*
@@ -273,7 +301,8 @@ public:
/**
* \brief Add a resource created from a file.
*/
bool AddResource(const gd::String & name, const gd::String & filename);
bool AddResource(const gd::String & name, const gd::String & filename,
const gd::String & kind);
/**
* \brief Remove a resource

View File

@@ -22,7 +22,6 @@ class ArbitraryResourceWorkerTest : public gd::ArbitraryResourceWorker
public:
virtual void ExposeFile(gd::String & file) { files.push_back(file); };
virtual void ExposeImage(gd::String & imageName) {images.push_back(imageName); };
virtual void ExposeShader(gd::String & shaderName) {}
std::vector<gd::String> files;
std::vector<gd::String> images;
@@ -48,14 +47,16 @@ TEST_CASE( "Resources", "[common][resources]" ) {
}
SECTION("ArbitraryResourceWorker") {
gd::Project project;
project.GetResourcesManager().AddResource("res1", "path/to/file1.png");
project.GetResourcesManager().AddResource("res2", "path/to/file2.png");
project.GetResourcesManager().AddResource("res3", "path/to/file3.png");
project.GetResourcesManager().AddResource("res1", "path/to/file1.png", "image");
project.GetResourcesManager().AddResource("res2", "path/to/file2.png", "image");
project.GetResourcesManager().AddResource("res3", "path/to/file3.png", "image");
project.GetResourcesManager().AddResource("res4", "path/to/file4.png", "audio");
ArbitraryResourceWorkerTest worker;
project.ExposeResources(worker);
REQUIRE(worker.files.size() == 3);
REQUIRE(worker.files.size() == 4);
REQUIRE(std::find(worker.files.begin(), worker.files.end(), "path/to/file2.png") != worker.files.end());
REQUIRE(std::find(worker.files.begin(), worker.files.end(), "path/to/file4.png") != worker.files.end());
SECTION("Object using a resource") {
gd::SpriteObject obj("myObject");
@@ -71,21 +72,22 @@ TEST_CASE( "Resources", "[common][resources]" ) {
worker.files.clear();
worker.images.clear();
project.ExposeResources(worker);
REQUIRE(worker.files.size() == 3);
REQUIRE(worker.files.size() == 4);
REQUIRE(worker.images.size() == 1);
REQUIRE(worker.images[0] == "res1");
SECTION("ProjectResourcesAdder") {
std::vector<gd::String> uselessResources =
gd::ProjectResourcesAdder::GetAllUselessResources(project);
gd::ProjectResourcesAdder::GetAllUselessImages(project);
REQUIRE(uselessResources.size() == 2);
gd::ProjectResourcesAdder::RemoveAllUselessResources(project);
gd::ProjectResourcesAdder::RemoveAllUselessImages(project);
std::vector<gd::String> remainingResources =
project.GetResourcesManager().GetAllResourcesList();
REQUIRE(remainingResources.size() == 1);
REQUIRE(remainingResources.size() == 2);
REQUIRE(remainingResources[0] == "res1");
REQUIRE(remainingResources[1] == "res4");
}
}
}

View File

@@ -51,14 +51,16 @@ TEST_CASE( "ResourcesMergingHelper", "[common]" ) {
resourcesMerger.SetBaseDirectory("/game/base/folder/");
gd::Project project;
project.GetResourcesManager().AddResource("Image1", "/image1.png");
project.GetResourcesManager().AddResource("Image2", "image2.png");
project.GetResourcesManager().AddResource("Image3", "subfolder/image3.png");
project.GetResourcesManager().AddResource("Image1", "/image1.png", "image");
project.GetResourcesManager().AddResource("Image2", "image2.png", "image");
project.GetResourcesManager().AddResource("Audio1", "audio1.png", "audio");
project.GetResourcesManager().AddResource("Image3", "subfolder/image3.png", "image");
project.ExposeResources(resourcesMerger);
auto resourcesFilenames = resourcesMerger.GetAllResourcesOldAndNewFilename();
REQUIRE(resourcesFilenames["MakeAbsolute(/image1.png)"] == "FileNameFrom(MakeAbsolute(/image1.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(audio1.png)"] == "FileNameFrom(MakeAbsolute(audio1.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(image2.png)"] == "FileNameFrom(MakeAbsolute(image2.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(subfolder/image3.png)"] == "FileNameFrom(MakeAbsolute(subfolder/image3.png))");
}
@@ -69,15 +71,17 @@ TEST_CASE( "ResourcesMergingHelper", "[common]" ) {
resourcesMerger.PreserveDirectoriesStructure(true);
gd::Project project;
project.GetResourcesManager().AddResource("Image1", "/image1.png");
project.GetResourcesManager().AddResource("Image2", "image2.png");
project.GetResourcesManager().AddResource("Image3", "subfolder/image3.png");
project.GetResourcesManager().AddResource("Image1", "/image1.png", "image");
project.GetResourcesManager().AddResource("Image2", "image2.png", "image");
project.GetResourcesManager().AddResource("Audio1", "audio1.png", "audio");
project.GetResourcesManager().AddResource("Image3", "subfolder/image3.png", "image");
project.ExposeResources(resourcesMerger);
auto resourcesFilenames = resourcesMerger.GetAllResourcesOldAndNewFilename();
REQUIRE(resourcesFilenames["MakeAbsolute(/image1.png)"] == "MakeRelative(MakeAbsolute(/image1.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(image2.png)"] == "MakeRelative(MakeAbsolute(image2.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(audio1.png)"] == "MakeRelative(MakeAbsolute(audio1.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(subfolder/image3.png)"] == "MakeRelative(MakeAbsolute(subfolder/image3.png))");
}
}

View File

@@ -168,8 +168,13 @@
<bitmap code='gd::SkinHelper::GetIcon(&quot;add&quot;, 16)' />
<handler function="OnAddImageBtClick" entry="EVT_MENU" />
</object>
<object class="wxMenuItem" name="idMenuAddAudio" variable="MenuItem4" member="yes">
<label>Add a sound/music</label>
<handler function="OnAddAudioSelected" entry="EVT_MENU" />
</object>
<object class="separator" />
<object class="wxMenuItem" name="idMenuDel" variable="deleteImageItem" member="no">
<label>Delete the image</label>
<label>Delete</label>
<accel>DEL</accel>
<bitmap code='gd::SkinHelper::GetIcon(&quot;delete&quot;, 16)' />
<handler function="OnDelImageBtClick" entry="EVT_MENU" />
@@ -200,6 +205,10 @@
<bitmap code='gd::SkinHelper::GetIcon(&quot;add&quot;, 16)' />
<handler function="OnAddImageBtClick" entry="EVT_MENU" />
</object>
<object class="wxMenuItem" name="ID_MENUITEM10" variable="MenuItem15" member="yes">
<label>Add a sound/music</label>
<handler function="OnAddAudioSelected" entry="EVT_MENU" />
</object>
<object class="separator" />
<object class="wxMenuItem" name="ID_MENUITEM2" variable="MenuItem6" member="yes">
<label>Add a folder</label>
@@ -214,18 +223,23 @@
<bitmap code='gd::SkinHelper::GetIcon(&quot;rename&quot;, 16)' />
<handler function="OnModNameImageBtClick" entry="EVT_MENU" />
</object>
<object class="wxMenuItem" name="ID_MENUITEM5" variable="MenuItem13" member="yes">
<label>Delete</label>
<accel>DEL</accel>
<bitmap code='gd::SkinHelper::GetIcon(&quot;delete&quot;, 16)' />
<handler function="OnDelImageBtClick" entry="EVT_MENU" />
</object>
<object class="separator" />
<object class="wxMenuItem" name="ID_MENUITEM6" variable="MenuItem10" member="yes">
<label>Add an image</label>
<bitmap code='gd::SkinHelper::GetIcon(&quot;add&quot;, 16)' />
<handler function="OnAddImageBtClick" entry="EVT_MENU" />
</object>
<object class="wxMenuItem" name="ID_MENUITEM11" variable="MenuItem16" member="yes">
<label>Add a sound/music</label>
<handler function="OnAddAudioSelected" entry="EVT_MENU" />
</object>
<object class="separator" />
<object class="wxMenuItem" name="ID_MENUITEM5" variable="MenuItem13" member="yes">
<label>Delete</label>
<accel>DEL</accel>
<bitmap code='gd::SkinHelper::GetIcon(&quot;delete&quot;, 16)' />
<handler function="OnDelImageBtClick" entry="EVT_MENU" />
</object>
<object class="separator" />
<object class="wxMenuItem" name="ID_MENUITEM4" variable="MenuItem5" member="yes">
<label>Add a folder</label>

View File

@@ -121,7 +121,7 @@ void TileSet::LoadResources(RuntimeGame &game)
void TileSet::LoadResources(gd::Project &game)
{
if(game.GetResourcesManager().HasResource(textureName))
try
{
gd::ImageResource & image = dynamic_cast<gd::ImageResource&>(game.GetResourcesManager().GetResource(textureName));
//Load the resource into a wxBitmap (IDE only) and also get its SFMLTextureWrapper
@@ -144,7 +144,7 @@ void TileSet::LoadResources(gd::Project &game)
//Readjust the m_collidable std::vector according to the number of tiles
m_collidable.resize(GetTilesCount(), true);
}
else
catch(...)
{
m_tilesetTexture = std::shared_ptr<SFMLTextureWrapper>();
}

View File

@@ -7,6 +7,8 @@
#include <iostream>
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCpp/Extensions/Builtin/AudioExtension.h"
#include "GDCpp/RuntimeScene.h"
#include "GDCpp/RuntimeGame.h"
#include "GDCpp/SoundManager.h"
#include "GDCpp/CommonTools.h"
#if defined(GD_IDE_ONLY)
@@ -70,26 +72,28 @@ void AudioExtension::ExposeActionsResources(gd::Instruction & action, gd::Arbitr
if ( action.GetType() == "PlaySound" || action.GetType() == "PlaySoundCanal" || action.GetType() == "PlayMusic" || action.GetType() == "PlayMusicCanal" )
{
gd::String parameter = action.GetParameter(1).GetPlainString();
worker.ExposeFile(parameter);
worker.ExposeAudio(parameter);
action.SetParameter(1, parameter);
}
}
void AudioExtension::GetPropertyForDebugger(RuntimeScene & scene, std::size_t propertyNb, gd::String & name, gd::String & value) const
{
SoundManager & manager = scene.game->GetSoundManager();
if ( propertyNb == 0 )
{
name = _("Global volume:");
value = gd::String::From(SoundManager::Get()->GetGlobalVolume());
value = gd::String::From(manager.GetGlobalVolume());
}
else if ( propertyNb < 1+SoundManager::Get()->sounds.size()*3 )
else if ( propertyNb < 1+manager.sounds.size()*3 )
{
std::size_t soundNb = ((propertyNb-1)-(propertyNb-1)%3)/3;
if (soundNb >= SoundManager::Get()->sounds.size()) return;
if (soundNb >= manager.sounds.size()) return;
if ( propertyNb % 3 == 1)
{
sf::Sound::Status soundStatus = SoundManager::Get()->sounds[soundNb]->GetStatus();
sf::Sound::Status soundStatus = manager.sounds[soundNb]->GetStatus();
if ( soundStatus == sf::Sound::Playing)
name = _("Sound played:");
@@ -98,29 +102,29 @@ void AudioExtension::GetPropertyForDebugger(RuntimeScene & scene, std::size_t pr
else if ( soundStatus == sf::Sound::Paused)
name = _("Paused sound:");
value = SoundManager::Get()->sounds[soundNb]->file;
value = manager.sounds[soundNb]->file;
}
else if ( propertyNb % 3 == 2)
{
name = _(" -Volume/Pitch:");
value = gd::String::From(SoundManager::Get()->sounds[soundNb]->GetVolume())
+"/"+gd::String::From(SoundManager::Get()->sounds[soundNb]->GetPitch());
value = gd::String::From(manager.sounds[soundNb]->GetVolume())
+"/"+gd::String::From(manager.sounds[soundNb]->GetPitch());
}
else
{
name = _(" -Progress (seconds) :");
value = gd::String::From(SoundManager::Get()->sounds[soundNb]->GetPlayingOffset());
value = gd::String::From(manager.sounds[soundNb]->GetPlayingOffset());
}
}
else if ( propertyNb < 1+SoundManager::Get()->sounds.size()*3+SoundManager::Get()->musics.size()*3 )
else if ( propertyNb < 1+manager.sounds.size()*3+manager.musics.size()*3 )
{
std::size_t musicNb = ((propertyNb-1-SoundManager::Get()->sounds.size()*3)-(propertyNb-1-SoundManager::Get()->sounds.size()*3)%3)/3;
if (musicNb >= SoundManager::Get()->musics.size()) return;
std::size_t musicNb = ((propertyNb-1-manager.sounds.size()*3)-(propertyNb-1-manager.sounds.size()*3)%3)/3;
if (musicNb >= manager.musics.size()) return;
if ( propertyNb % 3 == 1)
{
sf::Sound::Status soundStatus = SoundManager::Get()->musics[musicNb]->GetStatus();
sf::Sound::Status soundStatus = manager.musics[musicNb]->GetStatus();
if ( soundStatus == sf::Sound::Playing)
name = _("Played music:");
@@ -129,33 +133,35 @@ void AudioExtension::GetPropertyForDebugger(RuntimeScene & scene, std::size_t pr
else if ( soundStatus == sf::Sound::Paused)
name = _("Paused music:");
value = SoundManager::Get()->musics[musicNb]->file;
value = manager.musics[musicNb]->file;
}
else if ( propertyNb % 3 == 2)
{
name = _(" -Volume/Pitch:");
value = gd::String::From(SoundManager::Get()->musics[musicNb]->GetVolume())
+"/"+gd::String::From(SoundManager::Get()->musics[musicNb]->GetPitch());
value = gd::String::From(manager.musics[musicNb]->GetVolume())
+"/"+gd::String::From(manager.musics[musicNb]->GetPitch());
}
else
{
name = _(" -Progress (seconds) :");
value = gd::String::From(SoundManager::Get()->musics[musicNb]->GetPlayingOffset());
value = gd::String::From(manager.musics[musicNb]->GetPlayingOffset());
}
}
}
bool AudioExtension::ChangeProperty(RuntimeScene & scene, std::size_t propertyNb, gd::String newValue)
{
SoundManager & manager = scene.game->GetSoundManager();
if ( propertyNb == 0 )
{
SoundManager::Get()->SetGlobalVolume(newValue.To<float>());
manager.SetGlobalVolume(newValue.To<float>());
return true;
}
else if ( propertyNb < 1+SoundManager::Get()->sounds.size()*3 )
else if ( propertyNb < 1+manager.sounds.size()*3 )
{
std::size_t soundNb = ((propertyNb-1)-(propertyNb-1)%3)/3;
if (soundNb >= SoundManager::Get()->sounds.size()) return false;
if (soundNb >= manager.sounds.size()) return false;
if ( propertyNb % 3 == 1)
{
@@ -166,21 +172,21 @@ bool AudioExtension::ChangeProperty(RuntimeScene & scene, std::size_t propertyNb
std::vector<gd::String> values = newValue.Split(U'/');
if ( values.size() < 2 ) return false;
SoundManager::Get()->sounds[soundNb]->SetVolume(values[0].To<int>());
SoundManager::Get()->sounds[soundNb]->SetPitch(values[1].To<float>());
manager.sounds[soundNb]->SetVolume(values[0].To<float>(), manager.GetGlobalVolume());
manager.sounds[soundNb]->SetPitch(values[1].To<float>());
return true;
}
else
{
SoundManager::Get()->sounds[soundNb]->SetPlayingOffset(newValue.To<float>());
manager.sounds[soundNb]->SetPlayingOffset(newValue.To<float>());
return true;
}
}
else if ( propertyNb < 1+SoundManager::Get()->sounds.size()*3+SoundManager::Get()->musics.size()*3 )
else if ( propertyNb < 1+manager.sounds.size()*3+manager.musics.size()*3 )
{
std::size_t musicNb = ((propertyNb-1-SoundManager::Get()->sounds.size()*3)-(propertyNb-1-SoundManager::Get()->sounds.size()*3)%3)/3;
if (musicNb >= SoundManager::Get()->musics.size()) return false;
std::size_t musicNb = ((propertyNb-1-manager.sounds.size()*3)-(propertyNb-1-manager.sounds.size()*3)%3)/3;
if (musicNb >= manager.musics.size()) return false;
if ( propertyNb % 3 == 1)
{
@@ -191,13 +197,13 @@ bool AudioExtension::ChangeProperty(RuntimeScene & scene, std::size_t propertyNb
std::vector<gd::String> values = newValue.Split(U'/');
if ( values.size() < 2 ) return false;
SoundManager::Get()->musics[musicNb]->SetVolume(values[0].To<float>());
SoundManager::Get()->musics[musicNb]->SetPitch(values[1].To<float>());
manager.musics[musicNb]->SetVolume(values[0].To<float>(), manager.GetGlobalVolume());
manager.musics[musicNb]->SetPitch(values[1].To<float>());
return true;
}
else
{
SoundManager::Get()->musics[musicNb]->SetPlayingOffset(newValue.To<float>());
manager.musics[musicNb]->SetPlayingOffset(newValue.To<float>());
return true;
}
}
@@ -208,7 +214,9 @@ bool AudioExtension::ChangeProperty(RuntimeScene & scene, std::size_t propertyNb
std::size_t AudioExtension::GetNumberOfProperties(RuntimeScene & scene) const
{
return 1+SoundManager::Get()->musics.size()*3+SoundManager::Get()->sounds.size()*3;
SoundManager & manager = scene.game->GetSoundManager();
return 1+manager.musics.size()*3+manager.sounds.size()*3;
}
#endif

View File

@@ -5,19 +5,19 @@
*/
#include "AudioTools.h"
#include <string>
#include "GDCpp/RuntimeGame.h"
#include "GDCpp/RuntimeScene.h"
#include "GDCpp/SoundManager.h"
#include "GDCpp/ResourcesLoader.h"
#undef PlaySound //Gniark!
#undef PlaySound //Avoid a nasty macro from polluting everything
/**
* Test if a music is played
*/
bool GD_API MusicPlaying( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return false;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return false;
return (SoundManager::Get()->GetMusicOnChannel(channel)->GetStatus() == sf::Music::Playing);
return (scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetStatus() == sf::Music::Playing);
}
/**
@@ -25,9 +25,9 @@ bool GD_API MusicPlaying( RuntimeScene & scene, unsigned int channel )
*/
bool GD_API MusicPaused( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return false;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return false;
return (SoundManager::Get()->GetMusicOnChannel(channel)->GetStatus() == sf::Music::Paused);
return (scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetStatus() == sf::Music::Paused);
}
/**
@@ -35,9 +35,9 @@ bool GD_API MusicPaused( RuntimeScene & scene, unsigned int channel )
*/
bool GD_API MusicStopped( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return false;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return false;
return (SoundManager::Get()->GetMusicOnChannel(channel)->GetStatus() == sf::Music::Stopped);
return (scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetStatus() == sf::Music::Stopped);
}
@@ -46,9 +46,9 @@ bool GD_API MusicStopped( RuntimeScene & scene, unsigned int channel )
*/
bool GD_API SoundPlaying( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return false;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return false;
return (SoundManager::Get()->GetSoundOnChannel(channel)->GetStatus() == sf::Sound::Playing);
return (scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetStatus() == sf::Sound::Playing);
}
/**
@@ -56,9 +56,9 @@ bool GD_API SoundPlaying( RuntimeScene & scene, unsigned int channel )
*/
bool GD_API SoundPaused( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return false;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return false;
return (SoundManager::Get()->GetSoundOnChannel(channel)->GetStatus() == sf::Sound::Paused);
return (scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetStatus() == sf::Sound::Paused);
}
/**
@@ -66,26 +66,16 @@ bool GD_API SoundPaused( RuntimeScene & scene, unsigned int channel )
*/
bool GD_API SoundStopped( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return false;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return false;
return (SoundManager::Get()->GetSoundOnChannel(channel)->GetStatus() == sf::Sound::Stopped);
return (scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetStatus() == sf::Sound::Stopped);
}
void GD_API PlaySoundOnChannel( RuntimeScene & scene, const gd::String & file, unsigned int channel, bool repeat, float volume, float pitch )
{
sf::Clock latency;
//Chargement
SoundManager * soundManager = SoundManager::Get();
//Son à jouer
std::shared_ptr<Sound> sound = std::shared_ptr<Sound>(new Sound(file));
sound->sound.play();
soundManager->SetSoundOnChannel(channel, sound);
soundManager->GetSoundOnChannel(channel)->sound.setLoop(repeat);
soundManager->GetSoundOnChannel(channel)->SetVolume(volume);
soundManager->GetSoundOnChannel(channel)->SetPitch(pitch);
scene.game->GetSoundManager().PlaySoundOnChannel(file, channel, repeat, volume, pitch);
scene.GetTimeManager().NotifyPauseWasMade(latency.getElapsedTime().asMicroseconds());
}
@@ -94,202 +84,153 @@ void GD_API PlaySound( RuntimeScene & scene, const gd::String & file, bool repea
{
sf::Clock latency;
SoundManager * soundManager = SoundManager::Get();
soundManager->sounds.push_back(std::shared_ptr<Sound>(new Sound(file)));
soundManager->sounds.back()->sound.play();
soundManager->sounds.back()->sound.setLoop(repeat);
soundManager->sounds.back()->SetVolume(volume);
soundManager->sounds.back()->SetPitch(pitch);
scene.game->GetSoundManager().PlaySound(file, repeat, volume, pitch);
scene.GetTimeManager().NotifyPauseWasMade(latency.getElapsedTime().asMicroseconds());
}
void GD_API StopSoundOnChannel( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
SoundManager::Get()->GetSoundOnChannel(channel)->sound.stop();
scene.game->GetSoundManager().GetSoundOnChannel(channel)->sound.stop();
}
void GD_API PauseSoundOnChannel( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
SoundManager::Get()->GetSoundOnChannel(channel)->sound.pause();
scene.game->GetSoundManager().GetSoundOnChannel(channel)->sound.pause();
}
void GD_API RePlaySoundOnChannel( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
SoundManager::Get()->GetSoundOnChannel(channel)->sound.play();
scene.game->GetSoundManager().GetSoundOnChannel(channel)->sound.play();
}
void GD_API PlayMusic( RuntimeScene & scene, const gd::String & file, bool repeat, float volume, float pitch )
{
SoundManager * soundManager = SoundManager::Get();
std::shared_ptr<Music> music(new Music);
#if !defined(GD_IDE_ONLY)
gd::ResourcesLoader * ressourcesLoader = gd::ResourcesLoader::Get();
if(ressourcesLoader->HasFile(file))
{
std::size_t size = ressourcesLoader->GetBinaryFileSize(file);
music->SetBuffer(ressourcesLoader->LoadBinaryFile(file), size);
music->OpenFromMemory(size);
}
else
#endif
{
music->OpenFromFile(file);
}
soundManager->musics.push_back(music); //Ajout aux soundManager qui prend en charge la musique
soundManager->musics.back()->Play();
music->SetLoop(repeat);
music->SetVolume(volume);
music->SetPitch(pitch);
scene.game->GetSoundManager().PlayMusic(file, repeat, volume, pitch);
}
void GD_API PlayMusicOnChannel( RuntimeScene & scene, const gd::String & file, unsigned int channel , bool repeat, float volume, float pitch )
{
SoundManager * soundManager = SoundManager::Get();
std::shared_ptr<Music> music(new Music);
#if !defined(GD_IDE_ONLY)
gd::ResourcesLoader * ressourcesLoader = gd::ResourcesLoader::Get();
if(ressourcesLoader->HasFile(file))
{
std::size_t size = ressourcesLoader->GetBinaryFileSize(file);
music->SetBuffer(ressourcesLoader->LoadBinaryFile(file), size);
music->OpenFromMemory(size);
}
else
#endif
{
music->OpenFromFile(file);
}
music->Play();
soundManager->SetMusicOnChannel(channel, music); //Ajout au soundManager qui prend en charge la music
music->SetLoop(repeat);
music->SetVolume(volume);
music->SetPitch(pitch);
scene.game->GetSoundManager().PlayMusicOnChannel(file, channel, repeat, volume, pitch);
}
void GD_API StopMusicOnChannel( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
SoundManager::Get()->GetMusicOnChannel(channel)->Stop();
scene.game->GetSoundManager().GetMusicOnChannel(channel)->Stop();
}
void GD_API PauseMusicOnChannel( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
SoundManager::Get()->GetMusicOnChannel(channel)->Pause();
scene.game->GetSoundManager().GetMusicOnChannel(channel)->Pause();
}
void GD_API RePlayMusicOnChannel( RuntimeScene & scene, unsigned int channel )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
SoundManager::Get()->GetMusicOnChannel(channel)->Play();
scene.game->GetSoundManager().GetMusicOnChannel(channel)->Play();
}
void GD_API SetSoundVolumeOnChannel( RuntimeScene & scene, unsigned int channel, float volume )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
SoundManager::Get()->GetSoundOnChannel(channel)->SetVolume(volume);
scene.game->GetSoundManager().GetSoundOnChannel(channel)->SetVolume(volume, scene.game->GetSoundManager().GetGlobalVolume());
}
void GD_API SetMusicVolumeOnChannel( RuntimeScene & scene, unsigned int channel, float volume )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
SoundManager::Get()->GetMusicOnChannel(channel)->SetVolume(volume);
scene.game->GetSoundManager().GetMusicOnChannel(channel)->SetVolume(volume, scene.game->GetSoundManager().GetGlobalVolume());
}
double GD_API GetSoundVolumeOnChannel( RuntimeScene & scene, unsigned int channel)
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return 0;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return 0;
return SoundManager::Get()->GetSoundOnChannel(channel)->GetVolume();
return scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetVolume();
}
double GD_API GetMusicVolumeOnChannel( RuntimeScene & scene, unsigned int channel)
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return 0;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return 0;
return SoundManager::Get()->GetMusicOnChannel(channel)->GetVolume();
return scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetVolume();
}
void GD_API SetGlobalVolume( RuntimeScene & scene, float volume )
{
SoundManager::Get()->SetGlobalVolume(volume);
scene.game->GetSoundManager().SetGlobalVolume(volume);
}
double GD_API GetGlobalVolume( RuntimeScene & scene )
{
return SoundManager::Get()->GetGlobalVolume();
return scene.game->GetSoundManager().GetGlobalVolume();
}
void GD_API SetSoundPitchOnChannel( RuntimeScene & scene, unsigned int channel, float pitch )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
SoundManager::Get()->GetSoundOnChannel(channel)->SetPitch(pitch);
scene.game->GetSoundManager().GetSoundOnChannel(channel)->SetPitch(pitch);
}
void GD_API SetMusicPitchOnChannel( RuntimeScene & scene, unsigned int channel, float pitch )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
SoundManager::Get()->GetMusicOnChannel(channel)->SetPitch(pitch);
scene.game->GetSoundManager().GetMusicOnChannel(channel)->SetPitch(pitch);
}
double GD_API GetSoundPitchOnChannel( RuntimeScene & scene, unsigned int channel)
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return 0;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return 0;
return SoundManager::Get()->GetSoundOnChannel(channel)->GetPitch();
return scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetPitch();
}
double GD_API GetMusicPitchOnChannel( RuntimeScene & scene, unsigned int channel)
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return 0;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return 0;
return SoundManager::Get()->GetMusicOnChannel(channel)->GetPitch();
return scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetPitch();
}
void GD_API SetSoundPlayingOffsetOnChannel( RuntimeScene & scene, unsigned int channel, float playingOffset )
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return;
SoundManager::Get()->GetSoundOnChannel(channel)->SetPlayingOffset(playingOffset);
scene.game->GetSoundManager().GetSoundOnChannel(channel)->SetPlayingOffset(playingOffset);
}
void GD_API SetMusicPlayingOffsetOnChannel( RuntimeScene & scene, unsigned int channel, float playingOffset )
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return;
SoundManager::Get()->GetMusicOnChannel(channel)->SetPlayingOffset(playingOffset);
scene.game->GetSoundManager().GetMusicOnChannel(channel)->SetPlayingOffset(playingOffset);
}
double GD_API GetSoundPlayingOffsetOnChannel( RuntimeScene & scene, unsigned int channel)
{
if ( SoundManager::Get()->GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return 0;
if ( scene.game->GetSoundManager().GetSoundOnChannel(channel) == std::shared_ptr<Sound>() ) return 0;
return static_cast<double>(SoundManager::Get()->GetSoundOnChannel(channel)->GetPlayingOffset());
return static_cast<double>(scene.game->GetSoundManager().GetSoundOnChannel(channel)->GetPlayingOffset());
}
double GD_API GetMusicPlayingOffsetOnChannel( RuntimeScene & scene, unsigned int channel)
{
if ( SoundManager::Get()->GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return 0;
if ( scene.game->GetSoundManager().GetMusicOnChannel(channel) == std::shared_ptr<Music>() ) return 0;
return static_cast<double>(SoundManager::Get()->GetMusicOnChannel(channel)->GetPlayingOffset());
return static_cast<double>(scene.game->GetSoundManager().GetMusicOnChannel(channel)->GetPlayingOffset());
}

View File

@@ -169,7 +169,6 @@ void CppPlatform::OnIDEClosed()
CodeCompiler::Get()->ClearOutputDirectory();
#endif
SoundManager::Get()->DestroySingleton();
FontManager::Get()->DestroySingleton();
}
#endif

View File

@@ -135,7 +135,7 @@ void CppLayoutPreviewer::StopPreview()
if ( profiler ) previewScene.SetProfiler(profiler.get());
if ( profiler ) editor.GetLayout().SetProfiler(profiler.get());
if ( debugger ) debugger->Pause();
SoundManager::Get()->ClearAllSoundsAndMusics();
previewGame.GetSoundManager().ClearAllSoundsAndMusics();
}
void CppLayoutPreviewer::OnUpdate()
@@ -181,7 +181,7 @@ void CppLayoutPreviewer::RefreshFromLayout()
cout << "Scene Editor canvas reloading... (step 1/2)" << endl;
isReloading = true;
SoundManager::Get()->ClearAllSoundsAndMusics();
previewGame.GetSoundManager().ClearAllSoundsAndMusics();
if ( editor.GetProject().GetImageManager() ) editor.GetProject().GetImageManager()->PreventImagesUnloading(); //Images are normally unloaded and loaded again when reloading the scene. We can prevent this to happen as it is time wasting.
//Reset game

View File

@@ -167,7 +167,7 @@ void FullProjectCompiler::LaunchProjectCompilation()
wxLogNull noLogPlease;
wxString tempDir = GetTempDir();
ClearDirectory(tempDir); //Pr<50>paration du r<>pertoire
ClearDirectory(tempDir);
//Wait current compilations to end
if ( CodeCompiler::Get()->CompilationInProcess() )
@@ -191,32 +191,8 @@ void FullProjectCompiler::LaunchProjectCompilation()
//Prepare resources to copy
diagnosticManager.OnMessage( _("Preparing resources...") );
//Add images
std::vector<gd::String> allResources = game.GetResourcesManager().GetAllResourcesList();
for ( unsigned int i = 0;i < allResources.size() ;i++ )
{
diagnosticManager.OnMessage( _("Preparing resources..."), allResources[i] );
if ( game.GetResourcesManager().GetResource(allResources[i]).UseFile() )
resourcesMergingHelper.ExposeResource(game.GetResourcesManager().GetResource(allResources[i]));
}
//Add scenes resources
for ( unsigned int i = 0;i < game.GetLayoutsCount();i++ )
{
for (unsigned int j = 0;j<game.GetLayout(i).GetObjects().size();++j) //Add objects resources
game.GetLayout(i).GetObjects()[j]->ExposeResources(resourcesMergingHelper);
LaunchResourceWorkerOnEvents(game, game.GetLayout(i).GetEvents(), resourcesMergingHelper);
}
//Add external events resources
for ( unsigned int i = 0;i < game.GetExternalEventsCount();i++ )
{
LaunchResourceWorkerOnEvents(game, game.GetExternalEvents(i).GetEvents(), resourcesMergingHelper);
}
//Add global objects resources
for (unsigned int j = 0;j<game.GetObjects().size();++j) //Add global objects resources
game.GetObjects()[j]->ExposeResources(resourcesMergingHelper);
//Add resources
game.ExposeResources(resourcesMergingHelper);
//Compile all scene events to object files
for (unsigned int i = 0;i<game.GetLayoutsCount();++i)

View File

@@ -8,20 +8,14 @@
using namespace std;
Music::Music() :
buffer(NULL),
volume(100)
buffer(NULL),
volume(100)
{
//ctor
}
Music::~Music()
{
//dtor
}
bool Music::OpenFromFile(const gd::String & filename)
{
#if defined(GDE)
#if defined(GD_IDE_ONLY)
file = filename;
#endif
return music.openFromFile(filename.ToLocale());
@@ -69,16 +63,16 @@ void Music::SetLoop(bool loop)
music.setLoop(loop);
}
void Music::SetVolume(float volume_)
void Music::SetVolume(float volume_, float globalVolume)
{
volume = volume_;
if ( volume < 0 ) volume = 0;
if ( volume > 100 ) volume = 100;
UpdateVolume(); //Mise <20> jour du volume r<>el
UpdateVolume(globalVolume);
}
void Music::UpdateVolume()
void Music::UpdateVolume(float globalVolume)
{
music.setVolume(volume * SoundManager::Get()->GetGlobalVolume()/100.f);
music.setVolume(volume * globalVolume / 100.f);
}

View File

@@ -19,7 +19,7 @@ class GD_API Music
{
public:
Music();
virtual ~Music();
virtual ~Music() {};
/**
* \brief Open the music from a file.
@@ -80,7 +80,7 @@ public:
* \brief Change the music volume.
* \param volume The new volume, between 0 and 100.
*/
void SetVolume(float volume_);
void SetVolume(float volume_, float globalVolume);
/**
* \brief Get the music volume.
@@ -113,7 +113,7 @@ public:
*
* Called by the sound manager when the global volume is updated.
*/
void UpdateVolume();
void UpdateVolume(float globalVolume);
#if defined(GD_IDE_ONLY)
gd::String file; ///< Only useful for GD debugger

View File

@@ -13,6 +13,7 @@
RuntimeGame::RuntimeGame()
{
soundManager.SetResourcesManager(&GetResourcesManager());
}
void RuntimeGame::LoadFromProject(const gd::Project & project)
@@ -20,6 +21,6 @@ void RuntimeGame::LoadFromProject(const gd::Project & project)
//Copy inherited project
gd::Project::operator=(project);
//Initialize variables
variables.Merge(project.GetVariables());
soundManager.SetResourcesManager(&GetResourcesManager());
}

View File

@@ -7,18 +7,19 @@
#define RUNTIMEGAME_H
#include "GDCpp/Project/Project.h"
#include "GDCpp/SoundManager.h"
#include "GDCpp/RuntimeVariablesContainer.h"
#include <vector>
#include <string>
#include <map>
#include <memory>
class SoundManager;
/**
* \brief Represents a game being played.
*
* A RuntimeGame is used when a game is played.<be>
* It contains everything a project provide, but also specific
* functions and members for runtime ( variables... )
* It contains everything a project provides, but also specific
* functions and members for runtime (variables...)
*
* \ingroup GameEngine
*/
@@ -30,11 +31,19 @@ public:
/**
* \brief Set up the RuntimeGame using a gd::Project.
*
* Typically called automatically by the IDE or by the game executable.
*/
void LoadFromProject( const gd::Project & project );
/**
* Return the sound manager of the game.
*/
SoundManager & GetSoundManager() { return soundManager; };
/**
* Return the sound manager of the game.
*/
const SoundManager & GetSoundManager() const { return soundManager; };
/**
* \brief Provide access to the global variables container
*/
@@ -47,6 +56,7 @@ public:
private:
RuntimeVariablesContainer variables; ///<List of the global variables
SoundManager soundManager;
};
#endif // RUNTIMEGAME_H

View File

@@ -120,7 +120,7 @@ bool RuntimeScene::RenderAndStep()
ManageRenderTargetEvents();
timeManager.Update(clock.restart().asMicroseconds(), game->GetMinimumFPS());
ManageObjectsBeforeEvents();
SoundManager::Get()->ManageGarbage();
if (game) game->GetSoundManager().ManageGarbage();
#if defined(GD_IDE_ONLY)
if( GetProfiler() )
@@ -442,7 +442,7 @@ bool RuntimeScene::LoadFromSceneAndCustomInstances( const gd::Layout & scene, co
}
std::cout << ".";
if ( StopSoundsOnStartup() ) {SoundManager::Get()->ClearAllSoundsAndMusics(); }
if ( StopSoundsOnStartup() ) {game->GetSoundManager().ClearAllSoundsAndMusics(); }
if ( renderWindow ) renderWindow->setTitle(GetWindowDefaultTitle());
std::cout << " Done." << std::endl;

View File

@@ -6,10 +6,8 @@
using namespace std;
ShaderManager::ShaderManager() :
game(NULL)
ShaderManager::ShaderManager()
{
//ctor
}
std::shared_ptr<sf::Shader> ShaderManager::GetSFMLShader(const std::vector<gd::String> & shaders)

View File

@@ -26,14 +26,11 @@ class ShaderManager
public:
ShaderManager();
virtual ~ShaderManager() {};
void SetGame(gd::Project * game_) { game = game_; }
std::shared_ptr<sf::Shader> GetSFMLShader(const std::vector<gd::String> & shaders);
private:
mutable std::map < std::vector<gd::String>, std::weak_ptr<sf::Shader> > alreadyLoadedShader;
gd::Project * game;
};
#endif // SHADERMANAGER_H

View File

@@ -27,10 +27,6 @@ volume(100)
sound.setBuffer(buffer);
}
Sound::~Sound()
{
}
Sound::Sound(const Sound & copy) :
file(copy.file)
{
@@ -38,18 +34,16 @@ Sound::Sound(const Sound & copy) :
sound.setBuffer(buffer);
}
void Sound::SetVolume(float volume_)
void Sound::SetVolume(float volume_, float globalVolume)
{
volume = volume_;
if ( volume < 0 ) volume = 0;
if ( volume > 100 ) volume = 100;
UpdateVolume();
UpdateVolume(globalVolume);
}
void Sound::UpdateVolume()
void Sound::UpdateVolume(float globalVolume)
{
SoundManager * soundManager = SoundManager::Get();
sound.setVolume(volume*soundManager->GetGlobalVolume()/100.f);
sound.setVolume(volume * globalVolume / 100.f);
}

View File

@@ -20,7 +20,7 @@ public:
Sound();
Sound(gd::String file);
Sound(const Sound & copy);
virtual ~Sound();
virtual ~Sound() {};
/**
* \brief Get the sound status
@@ -32,7 +32,7 @@ public:
* \brief Change the music volume.
* \param volume The new volume, between 0 and 100.
*/
void SetVolume(float volume_);
void SetVolume(float volume_, float globalVolume);
/**
* \brief Get the sound volume.
@@ -71,7 +71,7 @@ public:
*
* Called by the sound manager when the global volume is updated.
*/
void UpdateVolume();
void UpdateVolume(float globalVolume);
private:
float volume; ///< Volume is not directly stored in the sf::Sound as GD allows to change global volume.

View File

@@ -4,23 +4,100 @@
* This project is released under the MIT License.
*/
#include "GDCpp/SoundManager.h"
#include "GDCpp/ResourcesLoader.h"
#include "GDCpp/Project/ResourcesManager.h"
#include "GDCpp/Music.h"
#include "GDCpp/Sound.h"
#include "GDCpp/String.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
SoundManager *SoundManager::_singleton = NULL;
SoundManager::SoundManager() :
globalVolume(100)
globalVolume(100),
resourcesManager(nullptr)
{
}
SoundManager::~SoundManager()
const gd::String & SoundManager::GetFileFromSoundName(const gd::String & name) const
{
if (!resourcesManager || !resourcesManager->HasResource(name))
return name;
return resourcesManager->GetResource(name).GetFile();
}
void SoundManager::PlaySoundOnChannel(const gd::String & name, unsigned int channel, bool repeat, float volume, float pitch)
{
std::shared_ptr<Sound> sound = std::shared_ptr<Sound>(new Sound(GetFileFromSoundName(name)));
sound->sound.play();
SetSoundOnChannel(channel, sound);
GetSoundOnChannel(channel)->sound.setLoop(repeat);
GetSoundOnChannel(channel)->SetVolume(volume, globalVolume);
GetSoundOnChannel(channel)->SetPitch(pitch);
}
void SoundManager::PlaySound(const gd::String & name, bool repeat, float volume, float pitch)
{
sounds.push_back(std::shared_ptr<Sound>(new Sound(GetFileFromSoundName(name))));
sounds.back()->sound.play();
sounds.back()->sound.setLoop(repeat);
sounds.back()->SetVolume(volume, globalVolume);
sounds.back()->SetPitch(pitch);
}
void SoundManager::PlayMusic(const gd::String & name, bool repeat, float volume, float pitch)
{
const gd::String & file = GetFileFromSoundName(name);
std::shared_ptr<Music> music(new Music);
#if !defined(GD_IDE_ONLY)
gd::ResourcesLoader * ressourcesLoader = gd::ResourcesLoader::Get();
if(ressourcesLoader->HasFile(file))
{
std::size_t size = ressourcesLoader->GetBinaryFileSize(file);
music->SetBuffer(ressourcesLoader->LoadBinaryFile(file), size);
music->OpenFromMemory(size);
}
else
#endif
{
music->OpenFromFile(file);
}
musics.push_back(music);
musics.back()->Play();
music->SetLoop(repeat);
music->SetVolume(volume, globalVolume);
music->SetPitch(pitch);
}
void SoundManager::PlayMusicOnChannel(const gd::String & name, unsigned int channel , bool repeat, float volume, float pitch)
{
const gd::String & file = GetFileFromSoundName(name);
std::shared_ptr<Music> music(new Music);
#if !defined(GD_IDE_ONLY)
gd::ResourcesLoader * ressourcesLoader = gd::ResourcesLoader::Get();
if(ressourcesLoader->HasFile(file))
{
std::size_t size = ressourcesLoader->GetBinaryFileSize(file);
music->SetBuffer(ressourcesLoader->LoadBinaryFile(file), size);
music->OpenFromMemory(size);
}
else
#endif
{
music->OpenFromFile(file);
}
SetMusicOnChannel(channel, music);
music->Play();
music->SetLoop(repeat);
music->SetVolume(volume, globalVolume);
music->SetPitch(pitch);
}
void SoundManager::ManageGarbage()
@@ -69,21 +146,20 @@ void SoundManager::SetGlobalVolume(float volume)
if ( globalVolume > 100.0 )
globalVolume = 100.0;
//Mise <20> jour des volumes des sons
for (std::map<std::size_t, std::shared_ptr<Sound> >::iterator it = soundsChannel.begin();it != soundsChannel.end();++it)
{
if ( it->second != std::shared_ptr<Sound>() ) (it->second)->UpdateVolume();
if ( it->second != std::shared_ptr<Sound>() ) (it->second)->UpdateVolume(globalVolume);
}
for (std::map<std::size_t, std::shared_ptr<Music> >::iterator it = musicsChannel.begin();it != musicsChannel.end();++it)
{
if ( it->second != std::shared_ptr<Music>() ) it->second->UpdateVolume();
if ( it->second != std::shared_ptr<Music>() ) it->second->UpdateVolume(globalVolume);
}
for (std::size_t i =0;i<sounds.size();++i)
{
if ( sounds[i] != std::shared_ptr<Sound>() ) sounds[i]->UpdateVolume();
if ( sounds[i] != std::shared_ptr<Sound>() ) sounds[i]->UpdateVolume(globalVolume);
}
for (std::size_t i =0;i<musics.size();++i)
{
if ( musics[i] != std::shared_ptr<Music>() ) musics[i]->UpdateVolume();
if ( musics[i] != std::shared_ptr<Music>() ) musics[i]->UpdateVolume(globalVolume);
}
}

View File

@@ -13,6 +13,8 @@
#include <string>
#include <vector>
#include <map>
namespace gd { class ResourcesManager; }
#undef PlaySound //Avoid a nasty macro from polluting everything
using namespace std;
@@ -27,9 +29,55 @@ using namespace std;
class GD_API SoundManager
{
public:
SoundManager();
~SoundManager() {};
/**
* \brief Set the gd::ResourcesManager used by the SoundManager.
*/
void SetResourcesManager(gd::ResourcesManager * resourcesManager_) { resourcesManager = resourcesManager_; }
vector < std::shared_ptr<Music> > musics;
vector < std::shared_ptr<Sound> > sounds;
/**
* \brief Play a sound (wav files).
* \param file The resource name, or filename to load.
* \param repeat true to loop the sound
* \param volume The volume, between 0 and 100.
* \param pitch The pithc, 1 by default
*/
void PlaySound(const gd::String & name, bool repeat, float volume, float pitch);
/**
* \brief Play a music (ogg files).
* \param file The resource name, or filename to load.
* \param repeat true to loop the music
* \param volume The volume, between 0 and 100.
* \param pitch The pithc, 1 by default
*/
void PlayMusic(const gd::String & name, bool repeat, float volume, float pitch);
/**
* \brief Play a sound (wav files) on a channel.
* \param file The resource name, or filename to load.
* \param channel The channel to use. The previous sound, if any, will be stopped.
* \param repeat true to loop the sound
* \param volume The volume, between 0 and 100.
* \param pitch The pithc, 1 by default
*/
void PlaySoundOnChannel(const gd::String & name, unsigned int channel, bool repeat, float volume, float pitch);
/**
* \brief Play a music (wav files) on a channel.
* \param file The resource name, or filename to load.
* \param channel The channel to use. The previous music, if any, will be stopped.
* \param repeat true to loop the music
* \param volume The volume, between 0 and 100.
* \param pitch The pithc, 1 by default
*/
void PlayMusicOnChannel(const gd::String & name, unsigned int channel, bool repeat, float volume, float pitch);
/**
* Return pointer to a music on a channel
*/
@@ -54,17 +102,13 @@ public:
* Get global game sound volume.
* Example :
* \code
* float currentVolume = SoundManager::Get()->GetGlobalVolume();
* float currentVolume = game.GetSoundManager().GetGlobalVolume();
* \endcode
*/
inline float GetGlobalVolume() const { return globalVolume; }
/**
* Change global game sound volume.
* Example :
* \code
* SoundManager::Get()->SetGlobalVolume(50);
* \endcode
*/
void SetGlobalVolume(float volume);
@@ -84,35 +128,14 @@ public:
*/
void ManageGarbage();
static SoundManager *Get()
{
if ( NULL == _singleton )
{
_singleton = new SoundManager;
}
return ( static_cast<SoundManager*>( _singleton ) );
}
static void DestroySingleton()
{
if ( NULL != _singleton )
{
delete _singleton;
_singleton = NULL;
}
}
private:
const gd::String & GetFileFromSoundName(const gd::String & name) const;
std::map<std::size_t, std::shared_ptr<Sound> > soundsChannel;
std::map<std::size_t, std::shared_ptr<Music> > musicsChannel;
float globalVolume;
SoundManager();
~SoundManager();
static SoundManager *_singleton;
gd::ResourcesManager * resourcesManager;
};

View File

@@ -193,7 +193,7 @@ int main( int argc, char *p_argv[] )
while (sceneStack.Step() && !abort)
;
SoundManager::Get()->DestroySingleton();
runtimeGame.GetSoundManager().ClearAllSoundsAndMusics();
FontManager::Get()->DestroySingleton();
gd::CloseLibrary(codeLibrary);

View File

@@ -74,7 +74,7 @@ void AudioExtension::ExposeActionsResources(gd::Instruction & action, gd::Arbitr
if ( action.GetType() == "PlaySound" || action.GetType() == "PlaySoundCanal" || action.GetType() == "PlayMusic" || action.GetType() == "PlayMusicCanal" )
{
gd::String parameter = action.GetParameter(1).GetPlainString();
worker.ExposeFile(parameter);
worker.ExposeAudio(parameter);
action.SetParameter(1, parameter);
}
}

View File

@@ -5,18 +5,17 @@
*/
/**
* The imageManager stores textures that can be used by the objects
* ImageManager loads and stores textures that can be used by the objects.
*
* @class ImageManager
* @namespace gdjs
* @param runtimeGame The runtimeGame to be imageManager belongs to.
*/
gdjs.ImageManager = function(runtimeGame)
gdjs.ImageManager = function(resources)
{
this._game = runtimeGame;
this._resources = resources;
this._invalidTexture = PIXI.Texture.fromImage("bunny.png"); //TODO
this._loadedTextures = new Hashtable();
this._loadedPow2ConvertedTextures = new Hashtable();
};
/**
@@ -33,10 +32,10 @@ gdjs.ImageManager.prototype.getPIXITexture = function(name) {
return this._invalidTexture;
}
var resources = this._game.getGameData().resources.resources;
if ( resources ) {
//Texture is not loaded, load it now from the resources list.
if ( this._resources ) {
var texture = null;
gdjs.iterateOverArray(resources, function(res) {
gdjs.iterateOverArray(this._resources, function(res) {
if ( res.name === name &&
res.kind === "image" ) {
@@ -46,7 +45,7 @@ gdjs.ImageManager.prototype.getPIXITexture = function(name) {
});
if ( texture !== null ) {
//console.log("Loaded texture \""+name+"\".");
console.log("Loaded texture \""+name+"\".");
this._loadedTextures.put(name, texture);
return texture;
}
@@ -65,3 +64,65 @@ gdjs.ImageManager.prototype.getInvalidPIXITexture = function() {
return this._invalidTexture;
};
/**
* Load the specified resources, so that textures are loaded and can then be
* used by calling `getPIXITexture`.
* @param onProgress Callback called each time a new file is loaded.
* @param onComplete Callback called when loading is done.
* @param resources The resources to be loaded. If not specified, will load the resources
* specified in the ImageManager constructor.
* @method loadTextures
*/
gdjs.ImageManager.prototype.loadTextures = function(onProgress, onComplete, resources) {
resources = resources || this._resources;
//Construct the list of files to be loaded.
//For one loaded file, it can have one or more resources
//that use it.
var that = this;
var files = {};
gdjs.iterateOverArray(resources, function(res) {
if ( res.file && res.kind === "image" ) {
if (that._loadedTextures.containsKey(res.name)) {
console.log("Texture \"" + res.name + "\" is already loaded.");
return true;
}
files[res.file] = files[res.file] ? files[res.file].concat(res) : [res];
}
});
var totalCount = Object.keys(files).length;
if (totalCount === 0)
return onComplete(); //Nothing to load.
var loadingCount = 0;
var loader = PIXI.loader;
loader.once('complete', function(loader, loadedFiles) {
//Store the loaded textures so that they are ready to use.
for (var file in loadedFiles) {
if (loadedFiles.hasOwnProperty(file)) {
if (!files.hasOwnProperty(file)) continue;
files[file].forEach(function(res) {
that._loadedTextures.put(res.name, loadedFiles[file].texture);
});
}
}
onComplete();
});
loader.on('progress', function() {
loadingCount++;
onProgress(loadingCount, totalCount);
});
for (var file in files) {
if (files.hasOwnProperty(file)) {
loader.add(file, file);
}
}
loader.load();
}

View File

@@ -29,7 +29,8 @@ gdjs.RuntimeGame = function(data, spec)
this._variables = new gdjs.VariablesContainer(data.variables);
this._data = data;
this._imageManager = new gdjs.ImageManager(this);
this._imageManager = new gdjs.ImageManager(data.resources ? data.resources.resources : undefined);
this._soundManager = new gdjs.SoundManager(data.resources ? data.resources.resources : undefined);
this._minFPS = data ? parseInt(data.properties.minFPS, 10) : 15;
//Rendering (see createStandardCanvas method)
@@ -63,7 +64,7 @@ gdjs.RuntimeGame = function(data, spec)
};
/**
* Get the variables of the runtimeGame.
* Get the variables of the RuntimeGame.
* @method getVariables
* @return a variablesContainer object.
*/
@@ -71,6 +72,20 @@ gdjs.RuntimeGame.prototype.getVariables = function() {
return this._variables;
};
/**
* Get the gdjs.SoundManager of the RuntimeGame.
* @method getSoundManager
* @return {gdjs.SoundManager} The sound manager.
*/
gdjs.RuntimeGame.prototype.getSoundManager = function() {
return this._soundManager;
};
/**
* Get the gdjs.ImageManager of the RuntimeGame.
* @method getImageManager
* @return {gdjs.ImageManager} The image manager.
*/
gdjs.RuntimeGame.prototype.getImageManager = function() {
return this._imageManager;
};
@@ -392,48 +407,31 @@ gdjs.RuntimeGame.prototype._resizeCanvas = function() {
/**
* Load all assets, displaying progress in renderer.
* TODO: This should be moved to ImageManager and take advantage of the load callback
* to store resources, and use it to load textures instead of fromImage.
* @method loadAllAssets
*/
gdjs.RuntimeGame.prototype.loadAllAssets = function(callback) {
//Prepare the progress text
var loadingScreen = new PIXI.Container();
var text = new PIXI.Text(" ", {font: "bold 60px Arial", fill: "#FFFFFF", align: "center"});
loadingScreen.addChild(text);
text.position.x = this._renderer.width/2-50;
text.position.y = this._renderer.height/2;
var loadingCount = 0;
//Load all assets
var assets = [];
gdjs.iterateOverArray(gdjs.projectData.resources.resources, function(res) {
if ( res.file && assets.indexOf(res.file) === -1 )
assets.push(res.file);
var allAssetsTotal = this._data.resources.resources.length;
var that = this;
this._imageManager.loadTextures(function (count, total) {
text.text = Math.floor(count / allAssetsTotal * 100) + "%";
text.position.x = that._renderer.width/2-text.width/2;
that._renderer.render(loadingScreen);
}, function() {
that._soundManager.preloadAudio(function (count, total) {
text.text = Math.floor((allAssetsTotal - total + count) / allAssetsTotal * 100) + "%";
text.position.x = that._renderer.width/2-text.width/2;
that._renderer.render(loadingScreen);
}, function() {
callback();
});
});
var game = this;
if ( assets.length !== 0 ) {
var loader = PIXI.loader;
loader.once('complete', callback);
loader.on('progress', onAssetsLoadingProgress);
for(var i = 0;i < assets.length; ++i) {
loader.add(assets[i], assets[i]);
}
loader.load();
}
else {
callback();
}
function onAssetsLoadingProgress() {
game._renderer.render(loadingScreen);
loadingCount++;
text.text = Math.floor(loadingCount/assets.length*100) + "%";
}
};
/**

View File

@@ -8,7 +8,8 @@
* The runtimeScene object represents a scene being played and rendered in the browser in a canvas.
*
* @class RuntimeScene
* @param PixiRenderer The PIXI.Renderer to be used
* @param {gdjs.RuntimeGame} runtimeGame The game associated to this scene.
* @param {PIXI.WebGLRenderer|PIXI.CanvasRenderer} pixiRenderer The renderer to be used
*/
gdjs.RuntimeScene = function(runtimeGame, pixiRenderer)
{
@@ -26,7 +27,6 @@ gdjs.RuntimeScene = function(runtimeGame, pixiRenderer)
this._lastId = 0;
this._name = "";
this._timeManager = new gdjs.TimeManager();
this._soundManager = new gdjs.SoundManager();
this._gameStopRequested = false;
this._requestedScene = "";
this._isLoaded = false; // True if loadFromScene was called and the scene is being played.
@@ -130,6 +130,9 @@ gdjs.RuntimeScene.prototype.loadFromScene = function(sceneData) {
gdjs.callbacksRuntimeSceneLoaded[i](this);
}
if (sceneData.stopSoundsOnStartup && this._runtimeGame)
this._runtimeGame.getSoundManager().clearAll();
this._isLoaded = true;
this._timeManager.reset();
};
@@ -571,11 +574,11 @@ gdjs.RuntimeScene.prototype.getTimeManager = function() {
};
/**
* Get the SoundManager of the scene.
* @return The gdjs.SoundManager of the scene.
* Shortcut to get the SoundManager of the game.
* @return The gdjs.SoundManager of the game.
*/
gdjs.RuntimeScene.prototype.getSoundManager = function() {
return this._soundManager;
return this._runtimeGame.getSoundManager();
};
//The flags to describe the change request by a scene:

View File

@@ -70,8 +70,11 @@ gdjs.Sound.prototype.rate = function() {
* @class SoundManager
* @constructor
*/
gdjs.SoundManager = function()
gdjs.SoundManager = function(resources)
{
this._resources = resources;
this._availableResources = {}; //Map storing "audio" resources for faster access.
this._sounds = {};
this._musics = {};
this._freeSounds = []; //Sounds without an assigned channel.
@@ -90,6 +93,25 @@ gdjs.SoundManager.clampRate = function(rate) {
return rate;
};
/**
* Return the file associated to the given sound name.
*
* Names and files are loaded from resources when preloadAudio is called. If no
* file is associated to the given name, then the name will be considered as a
* filename and will be returned.
* @method _getFileFromSoundName
* @private
* @return The associated filename
*/
gdjs.SoundManager.prototype._getFileFromSoundName = function(soundName) {
if (this._availableResources.hasOwnProperty(soundName) &&
this._availableResources[soundName].file) {
return this._availableResources[soundName].file;
}
return soundName;
}
/**
* Store the sound in the specified array, put it at the first index that
* is free, or add it at the end if no element is free
@@ -115,7 +137,9 @@ gdjs.SoundManager.prototype._storeSoundInArray = function(arr, sound) {
return sound;
};
gdjs.SoundManager.prototype.playSound = function(soundFile, loop, volume, pitch) {
gdjs.SoundManager.prototype.playSound = function(soundName, loop, volume, pitch) {
var soundFile = this._getFileFromSoundName(soundName);
var sound = new gdjs.Sound({
src: [soundFile], //TODO: ogg, mp3...
loop: loop,
@@ -126,12 +150,14 @@ gdjs.SoundManager.prototype.playSound = function(soundFile, loop, volume, pitch)
this._storeSoundInArray(this._freeSounds, sound).play();
};
gdjs.SoundManager.prototype.playSoundOnChannel = function(soundFile, channel, loop, volume, pitch) {
gdjs.SoundManager.prototype.playSoundOnChannel = function(soundName, channel, loop, volume, pitch) {
var oldSound = this._sounds[channel];
if (oldSound) {
oldSound.stop();
}
var soundFile = this._getFileFromSoundName(soundName);
var sound = new gdjs.Sound({
src: [soundFile], //TODO: ogg, mp3...
loop: loop,
@@ -147,10 +173,13 @@ gdjs.SoundManager.prototype.getSoundOnChannel = function(channel) {
return this._sounds[channel];
};
gdjs.SoundManager.prototype.playMusic = function(soundFile, loop, volume, pitch) {
gdjs.SoundManager.prototype.playMusic = function(soundName, loop, volume, pitch) {
var soundFile = this._getFileFromSoundName(soundName);
var sound = new gdjs.Sound({
src: [soundFile], //TODO: ogg, mp3...
loop: loop,
html5: true, //Force HTML5 audio so we don't wait for the full file to be loaded on Android.
volume: volume/100,
rate: gdjs.SoundManager.clampRate(pitch)
});
@@ -158,15 +187,18 @@ gdjs.SoundManager.prototype.playMusic = function(soundFile, loop, volume, pitch)
this._storeSoundInArray(this._freeMusics, sound).play();
};
gdjs.SoundManager.prototype.playMusicOnChannel = function(soundFile, channel, loop, volume, pitch) {
gdjs.SoundManager.prototype.playMusicOnChannel = function(soundName, channel, loop, volume, pitch) {
var oldMusic = this._musics[channel];
if (oldMusic) {
oldMusic.stop();
}
var soundFile = this._getFileFromSoundName(soundName);
var music = new gdjs.Sound({
src: [soundFile], //TODO: ogg, mp3...
loop: loop,
html5: true, //Force HTML5 audio so we don't wait for the full file to be loaded on Android.
volume: volume/100,
rate: gdjs.SoundManager.clampRate(pitch)
});
@@ -186,3 +218,70 @@ gdjs.SoundManager.prototype.setGlobalVolume = function(volume) {
gdjs.SoundManager.prototype.getGlobalVolume = function() {
return Howler.volume()*100;
};
gdjs.SoundManager.prototype.clearAll = function() {
for (var i = 0;i<this._freeSounds.length;++i) {
if (this._freeSounds[i]) this._freeSounds[i].stop();
}
for (var i = 0;i<this._freeMusics.length;++i) {
if (this._freeMusics[i]) this._freeMusics[i].stop();
}
this._freeSounds.length = 0;
this._freeMusics.length = 0;
for (var p in this._sounds) {
if (this._sounds.hasOwnProperty(p) && this._sounds[p]) {
this._sounds[p].stop();
delete this._sounds[p];
}
}
for (var p in this._musics) {
if (this._musics.hasOwnProperty(p) && this._musics[p]) {
this._musics[p].stop();
delete this._musics[p];
}
}
}
gdjs.SoundManager.prototype.preloadAudio = function(onProgress, onComplete, resources) {
resources = resources || this._resources;
var files = [];
var that = this;
gdjs.iterateOverArray(resources, function(res) {
if ( res.file && res.kind === "audio" ) {
that._availableResources[res.name] = res;
if (files.indexOf(res.file) === -1) {
files.push(res.file);
}
}
});
if (files.length === 0) return onComplete();
var loaded = 0;
function onLoad(audioFile) {
console.log("loaded", audioFile);
loaded++;
if (loaded === files.length) {
console.log("All audio loaded");
return onComplete();
}
onProgress(loaded, files.length);
}
for(var i = 0;i<files.length;++i) {
(function(audioFile) {
console.log("Loading", audioFile)
var sound = new Howl({
src: [audioFile], //TODO: ogg, mp3...
preload: true,
onload: onLoad.bind(that, audioFile),
onloaderror: onLoad.bind(that, audioFile)
});
})(files[i]);
}
}