/** GDevelop - Video Object Extension Copyright (c) 2010-2014 Florian Rival (Florian.Rival@gmail.com) This project is released under the MIT License. */ #if defined(GD_IDE_ONLY) #include //Must be placed first, otherwise we get errors relative to "cannot convert 'const TCHAR*'..." in wx/msw/winundef.h #endif #include #include "GDCpp/Object.h" #include "GDCpp/ImageManager.h" #include "GDCpp/Serialization/SerializerElement.h" #include "GDCpp/FontManager.h" #include "GDCpp/Position.h" #include "GDCpp/Polygon2d.h" #include "GDCpp/CommonTools.h" #include "VideoObject.h" #if defined(GD_IDE_ONLY) #include "GDCore/IDE/ArbitraryResourceWorker.h" #include "GDCore/IDE/Dialogs/MainFrameWrapper.h" #include "VideoObjectEditor.h" #endif VideoObject::VideoObject(std::string name_) : Object(name_), looping(true), paused(false), opacity( 255 ), colorR( 255 ), colorG( 255 ), colorB( 255 ), angle(0) { } VideoObject::~VideoObject() { } void VideoObject::DoUnserializeFrom(gd::Project & project, const gd::SerializerElement & element) { SetVideoFile(element.GetStringAttribute("videoFile")); looping = element.GetBoolAttribute("looping"); opacity = element.GetFloatAttribute("opacity"); SetColor( element.GetIntAttribute("colorR", 255), element.GetIntAttribute("colorG", 255), element.GetIntAttribute("colorB", 255)); SetVolume(element.GetIntAttribute("volume", 100)); } #if defined(GD_IDE_ONLY) void VideoObject::DoSerializeTo(gd::SerializerElement & element) const { element.SetAttribute("videoFile", videoFile); element.SetAttribute("looping", looping); element.SetAttribute("opacity", opacity); element.SetAttribute("colorR", colorR); element.SetAttribute("colorG", colorG); element.SetAttribute("colorB", colorB); element.SetAttribute("volume", static_cast(GetVolume())); } #endif bool VideoObject::LoadRuntimeResources(const RuntimeScene & scene, const gd::ImageManager & imageMgr ) { ReloadVideo(); return true; } void VideObject::SetVideoFile(std::string file) { videoFile = file; #if defined(GD_IDE_ONLY) videoFile = gd::AbstractFileSystem::NormalizeSeparator(videoFile); #endif } void VideoObject::ReloadVideo() { video.Load(videoFile); video.SetLooping(looping); video.SetPause(paused); video.GetRenderSprite().setTexture(video.GetNextFrameImage(), true); video.GetRenderSprite().setOrigin(video.GetRenderSprite().getLocalBounds().width/2, video.GetRenderSprite().getLocalBounds().height/2); } bool VideoObject::SetAngle(float newAngle) { angle = newAngle; video.GetRenderSprite().setRotation(angle); return true; }; double VideoObject::GetTimePosition() const { return video.GetTimePosition(); } double VideoObject::GetDuration() const { return video.GetDuration(); } /** * Load a new video */ void VideoObject::LoadAndPlayVideo( const std::string & videoFile ) { SetVideoFile(videoFile); ReloadVideo(); video.SetPause(false); } void VideoObject::Seek( double position ) { video.Seek(position); } void VideoObject::SetColor(const std::string & colorStr) { vector < string > colors = SplitString(colorStr, ';'); if ( colors.size() < 3 ) return; //La couleur est incorrecte SetColor( ToInt(colors[0]), ToInt(colors[1]), ToInt(colors[2]) ); } unsigned int VideoObject::GetVolume() { return video.GetVolume(); } void VideoObject::SetVolume(unsigned int vol) { if(vol < 0) video.SetVolume(vol); } /** * Update animation and direction from the inital position */ bool VideoObject::InitializeFromInitialInstance(const gd::InitialInstance & position) { return true; } /** * Render object at runtime */ bool VideoObject::Draw( sf::RenderTarget& renderTarget ) { //Don't draw anything if hidden if ( hidden ) return true; video.GetRenderSprite().setTexture(video.GetNextFrameImage(), true); renderTarget.draw( video.GetRenderSprite() ); return true; } #if defined(GD_IDE_ONLY) /** * Render object at edittime */ bool VideoObject::DrawEdittime(sf::RenderTarget& renderTarget) { if ( !video.IsValid() ) { static bool badImageLoaded = false; static sf::Texture badVideoIcon; if ( !badImageLoaded ) { badVideoIcon.loadFromFile("CppPlatform/Extensions/badVideo.png"); badImageLoaded = true; } video.GetRenderSprite().setTexture(badVideoIcon, true); } else { sf::RectangleShape rectangle(sf::Vector2f(video.GetRenderSprite().getLocalBounds().width, video.GetRenderSprite().getLocalBounds().height)); rectangle.setFillColor(sf::Color(0,0,0)); rectangle.setOrigin(video.GetRenderSprite().getLocalBounds().width/2, video.GetRenderSprite().getLocalBounds().height/2); rectangle.setPosition(GetX(), GetY()); rectangle.setRotation(video.GetRenderSprite().getRotation()); renderTarget.draw(rectangle); //Display first frame video.Seek(0.1); video.GetRenderSprite().setTexture(video.GetNextFrameImage(), true); } renderTarget.draw( video.GetRenderSprite() ); return true; } void VideoObject::ExposeResources(gd::ArbitraryResourceWorker & worker) { worker.ExposeFile(videoFile); } bool VideoObject::GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail) const { thumbnail = wxBitmap("CppPlatform/Extensions/videoicon24.png", wxBITMAP_TYPE_ANY); return true; } void VideoObject::EditObject( wxWindow* parent, gd::Project & game, gd::MainFrameWrapper & mainFrameWrapper ) { VideoObjectEditor dialog(parent, game, *this, mainFrameWrapper); dialog.ShowModal(); } void VideoObject::GetPropertyForDebugger(unsigned int propertyNb, string & name, string & value) const { if ( propertyNb == 0 ) {name = _("File"); value = GetVideoFile();} else if ( propertyNb == 1 ) {name = _("Automatic restart"); value = looping ? _("Yes") : _("No");} else if ( propertyNb == 2 ) {name = _("Position in video"); value = ToString(video.GetTimePosition())+"s";} else if ( propertyNb == 3 ) {name = _("Paused"); value = paused ? _("Yes") : _("No");} else if ( propertyNb == 4 ) {name = _("Length"); value = ToString(video.GetDuration())+"s";} else if ( propertyNb == 5 ) {name = _("Color"); value = ToString(colorR)+";"+ToString(colorG)+";"+ToString(colorB);} else if ( propertyNb == 6 ) {name = _("Opacity"); value = ToString(GetOpacity());} } bool VideoObject::ChangeProperty(unsigned int propertyNb, string newValue) { if ( propertyNb == 0 ) { SetVideoFile(newValue); ReloadVideo(); } else if ( propertyNb == 1 ) { looping = (newValue == _T("Oui")); video.SetLooping(looping); } else if ( propertyNb == 2 ) { video.Seek(ToFloat(newValue)); } else if ( propertyNb == 3 ) { paused = (newValue == _T("Oui")); video.SetPause(paused); } else if ( propertyNb == 4 ) { return false; } else if ( propertyNb == 5 ) { string r, gb, g, b; { size_t separationPos = newValue.find(";"); if ( separationPos > newValue.length()) return false; r = newValue.substr(0, separationPos); gb = newValue.substr(separationPos+1, newValue.length()); } { size_t separationPos = gb.find(";"); if ( separationPos > gb.length()) return false; g = gb.substr(0, separationPos); b = gb.substr(separationPos+1, gb.length()); } SetColor(ToInt(r), ToInt(g), ToInt(b)); } else if ( propertyNb == 6 ) { SetOpacity(ToFloat(newValue)); } return true; } unsigned int VideoObject::GetNumberOfProperties() const { return 7; } #endif void VideoObject::OnPositionChanged() { video.GetRenderSprite().setPosition( GetX(), GetY() ); } /** * VideoObject provides a basic bounding box. */ std::vector VideoObject::GetHitBoxes() const { std::vector mask; Polygon2d rectangle = Polygon2d::CreateRectangle(GetWidth(), GetHeight()); rectangle.Rotate(GetAngle()/180*3.14159); rectangle.Move(GetX()+GetCenterX(), GetY()+GetCenterY()); mask.push_back(rectangle); return mask; } /** * Get the real X position of the sprite */ float VideoObject::GetDrawableX() const { return video.GetRenderSprite().getPosition().x-video.GetRenderSprite().getOrigin().x; } /** * Get the real Y position of the text */ float VideoObject::GetDrawableY() const { return video.GetRenderSprite().getPosition().y-video.GetRenderSprite().getOrigin().y; } /** * Width is the width of the current sprite. */ float VideoObject::GetWidth() const { return video.GetRenderSprite().getLocalBounds().width; } /** * Height is the height of the current sprite. */ float VideoObject::GetHeight() const { return video.GetRenderSprite().getLocalBounds().height; } /** * X center is computed with text rectangle */ float VideoObject::GetCenterX() const { return video.GetRenderSprite().getLocalBounds().width/2; } /** * Y center is computed with text rectangle */ float VideoObject::GetCenterY() const { return video.GetRenderSprite().getLocalBounds().height/2; } /** * Nothing to do when updating time */ void VideoObject::UpdateTime(float time_increase) { video.UpdateTime(time_increase); } /** * Change the color filter of the sprite object */ void VideoObject::SetColor( unsigned int r, unsigned int g, unsigned int b ) { colorR = r; colorG = g; colorB = b; video.GetRenderSprite().setColor(sf::Color(colorR, colorG, colorB, opacity)); } void VideoObject::SetOpacity(float val) { if ( val > 255 ) val = 255; else if ( val < 0 ) val = 0; opacity = val; video.GetRenderSprite().setColor(sf::Color(colorR, colorG, colorB, opacity)); } void DestroyRuntimeVideoObject(RuntimeObject * object) { delete object; } RuntimeObject * CreateRuntimeVideoObject(RuntimeScene & scene, const gd::Object & object) { return new RuntimeVideoObject(scene, object); } /** * Function destroying an extension Object. * GDevelop does not delete directly extension object * to avoid overloaded new/delete conflicts. */ void DestroyVideoObject(gd::Object * object) { delete object; } /** * Function creating an extension Object. * GDevelop can not directly create an extension object */ gd::Object * CreateVideoObject(std::string name) { return new VideoObject(name); }