diff --git a/.travis.yml b/.travis.yml index da0a4f3408..51b3ca0797 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,24 +9,25 @@ notifications: irc: "chat.freenode.net#stepmania-devs" before_script: - - sudo apt-get install nasm - - sudo apt-get install libmad0-dev - - sudo apt-get install libgtk2.0-dev - - sudo apt-get install binutils-dev - - sudo apt-get install libasound-dev - - sudo apt-get install libpulse-dev - - sudo apt-get install libjack-dev - - sudo apt-get install libc6-dev - - sudo apt-get install libogg-dev - - sudo apt-get install libvorbis-dev - - sudo apt-get install libbz2-dev - - sudo apt-get install zlib1g-dev - - sudo apt-get install libjpeg8-dev - - sudo apt-get install libpng12-dev - - sudo apt-get install libxtst-dev libxrandr-dev - - sudo apt-get install libglu1-mesa-dev - - sudo apt-get install mesa-common-dev - - sudo apt-get install libglew-dev + - sudo apt-get update -qq + - sudo apt-get install -y nasm + - sudo apt-get install -y libmad0-dev + - sudo apt-get install -y libgtk2.0-dev + - sudo apt-get install -y binutils-dev + - sudo apt-get install -y libasound-dev + - sudo apt-get install -y libpulse-dev + - sudo apt-get install -y libjack-dev + - sudo apt-get install -y libc6-dev + - sudo apt-get install -y libogg-dev + - sudo apt-get install -y libvorbis-dev + - sudo apt-get install -y libbz2-dev + - sudo apt-get install -y zlib1g-dev + - sudo apt-get install -y libjpeg8-dev + - sudo apt-get install -y libpng12-dev + - sudo apt-get install -y libxtst-dev libxrandr-dev + - sudo apt-get install -y libglu1-mesa-dev + - sudo apt-get install -y mesa-common-dev + - sudo apt-get install -y libglew-dev script: - ./autogen.sh diff --git a/BackgroundEffects/Centered.lua b/BackgroundEffects/Centered.lua index 5ee918a626..2e8c7d3d1d 100644 --- a/BackgroundEffects/Centered.lua +++ b/BackgroundEffects/Centered.lua @@ -2,7 +2,13 @@ local Color1 = color(Var "Color1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;diffuse,Color1;effectclock,"music"); + OnCommand= function(self) + self:xy(_screen.cx, _screen.cy):diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/Checkerboard1File2x2.lua b/BackgroundEffects/Checkerboard1File2x2.lua index 6ecca9e692..0352305d10 100644 --- a/BackgroundEffects/Checkerboard1File2x2.lua +++ b/BackgroundEffects/Checkerboard1File2x2.lua @@ -1,16 +1,32 @@ local Color1 = color(Var "Color1"); local a = LoadActor(Var "File1") .. { - OnCommand=cmd(cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color1;effectclock,"music"); + OnCommand= function(self) + self:cropto(_screen.w/2, _screen.h/2):diffuse(Color1) + :effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; local t = Def.ActorFrame { a .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; + a .. { OnCommand=function(self) + self:x(scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; + a .. { OnCommand=function(self) + self:x(scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; + a .. { OnCommand=function(self) + self:x(scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; }; return t; diff --git a/BackgroundEffects/Checkerboard2File2x2.lua b/BackgroundEffects/Checkerboard2File2x2.lua index 515341cc49..eadb73f18b 100644 --- a/BackgroundEffects/Checkerboard2File2x2.lua +++ b/BackgroundEffects/Checkerboard2File2x2.lua @@ -2,12 +2,25 @@ local Color1 = color(Var "Color1"); local Color2 = color(Var "Color2"); local a1 = LoadActor(Var "File1") .. { - OnCommand=cmd(cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color1;effectclock,"music"); + OnCommand= function(self) + self:cropto(SCREEN_WIDTH/2,SCREEN_HEIGHT/2):diffuse(Color1) + :effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; local a2 = LoadActor(Var "File2") .. { - OnCommand=cmd(cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color2;effectclock,"music"); + OnCommand= function(self) + self:cropto(SCREEN_WIDTH/2,SCREEN_HEIGHT/2):diffuse(Color2):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; @@ -15,8 +28,14 @@ local a2 = LoadActor(Var "File2") .. { local t = Def.ActorFrame { a1 .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; a2 .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a2 .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a1 .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; + a2 .. { OnCommand=function(self) + self:x(scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; + a1 .. { OnCommand=function(self) + self:x(scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; }; return t; diff --git a/BackgroundEffects/Checkerboard2x2.lua b/BackgroundEffects/Checkerboard2x2.lua index 4183d12762..399ea05548 100644 --- a/BackgroundEffects/Checkerboard2x2.lua +++ b/BackgroundEffects/Checkerboard2x2.lua @@ -3,10 +3,18 @@ local Color2 = color(Var "Color2"); -- Alternating files being played back at once local t = Def.ActorFrame { - LoadActor(Var "File1") .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM);cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color1;rate,0.25) }; - LoadActor(Var "File2") .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM);cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color2;rate,0.25) }; - LoadActor(Var "File2") .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM);cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color1;rate,0.25) }; - LoadActor(Var "File1") .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM);cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color2;rate,0.25) }; + LoadActor(Var "File1") .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM);cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color1) }; + LoadActor(Var "File2") .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM);cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color2) }; + LoadActor(Var "File2") .. { + OnCommand=function(self) + self:x(scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)):cropto(SCREEN_WIDTH/2,SCREEN_HEIGHT/2):diffuse(Color1) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; + LoadActor(Var "File1") .. { + OnCommand=function(self) + self:x(scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)):cropto(SCREEN_WIDTH/2,SCREEN_HEIGHT/2):diffuse(Color2) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; }; return t diff --git a/BackgroundEffects/File2Flash.lua b/BackgroundEffects/File2Flash.lua index dd98d708ff..e2b649fc20 100644 --- a/BackgroundEffects/File2Flash.lua +++ b/BackgroundEffects/File2Flash.lua @@ -4,14 +4,26 @@ local Color2 = color(Var "Color2"); local t = Def.ActorFrame {}; t[#t+1] = LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; if Var("File2") ~= nil then t[#t+1] = LoadActor(Var("File2")) .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color2;effectclock,"music";linear,1;diffusealpha,0); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color2):effectclock("music"):linear(1):diffusealpha(0) + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/File2Normal.lua b/BackgroundEffects/File2Normal.lua index 85fd768f48..5125fda9c0 100644 --- a/BackgroundEffects/File2Normal.lua +++ b/BackgroundEffects/File2Normal.lua @@ -4,14 +4,26 @@ local Color2 = color(Var "Color2"); local t = Def.ActorFrame {}; t[#t+1] = LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) +self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; if Var("File2") ~= nil then t[#t+1] = LoadActor(Var("File2")) .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/Kaleidoscope2x2.lua b/BackgroundEffects/Kaleidoscope2x2.lua index 834dd4f7a4..a2994bfe52 100644 --- a/BackgroundEffects/Kaleidoscope2x2.lua +++ b/BackgroundEffects/Kaleidoscope2x2.lua @@ -1,16 +1,31 @@ local Color1 = color(Var "Color1"); local a = LoadActor(Var "File1") .. { - OnCommand=cmd(cropto,SCREEN_WIDTH/2,SCREEN_HEIGHT/2;diffuse,Color1;zoomx,self:GetZoomX()*-1;zoomy,self:GetZoomY()*-1;effectclock,"music"); + OnCommand= function(self) + self:cropto(SCREEN_WIDTH/2,SCREEN_HEIGHT/2):diffuse(Color1):zoomx(self:GetZoomX()*-1):zoomy(self:GetZoomY()*-1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; local t = Def.ActorFrame { a .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a .. { OnCommand=cmd(x,scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; - a .. { OnCommand=cmd(x,scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT);y,scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)); }; + a .. { OnCommand=function(self) + self:x(scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(1,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; + a .. { OnCommand=function(self) + self:x(scale(1,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; + a .. { OnCommand=function(self) + self:x(scale(3,0,4,SCREEN_LEFT,SCREEN_RIGHT)):y(scale(3,0,4,SCREEN_TOP,SCREEN_BOTTOM)) + if self.SetDecodeMovie then self:SetDecodeMovie(false) end + end }; }; return t; diff --git a/BackgroundEffects/SongBgWithMovieViz.lua b/BackgroundEffects/SongBgWithMovieViz.lua index 7ae5d6d02f..800f5c8460 100644 --- a/BackgroundEffects/SongBgWithMovieViz.lua +++ b/BackgroundEffects/SongBgWithMovieViz.lua @@ -9,11 +9,21 @@ local t = Def.ActorFrame { self:scale_or_crop_background(); self:diffuse(Color1) self:effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end end; }; LoadActor(Var "File1") .. { - OnCommand=cmd(blend,"BlendMode_Add";x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color2;effectclock,"music"); + OnCommand=function(self) + self:blend("BlendMode_Add"):x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color2):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end; GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchNoLoop.lua b/BackgroundEffects/StretchNoLoop.lua index 0051588fea..84e630326d 100644 --- a/BackgroundEffects/StretchNoLoop.lua +++ b/BackgroundEffects/StretchNoLoop.lua @@ -6,7 +6,14 @@ local t = Def.ActorFrame { self:xy(SCREEN_CENTER_X,SCREEN_CENTER_Y) self:scale_or_crop_background() self:diffuse(Color1) - if self.loop ~= nil then + -- The playback rate in the simfile is used to set the update rate + -- on the ActorFrame, but effectclock("music") causes the sprite to + -- ignore the passed in delta time and use the music time instead. + -- So this passes the update rate in to the texture. -Kyz + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + if self.loop then self:loop(false) -- make videos start at beginning to prevent sticking on last frame self:position(0) diff --git a/BackgroundEffects/StretchNormal.lua b/BackgroundEffects/StretchNormal.lua index c814a02284..4fc137bb90 100644 --- a/BackgroundEffects/StretchNormal.lua +++ b/BackgroundEffects/StretchNormal.lua @@ -7,6 +7,10 @@ local t = Def.ActorFrame { self:scale_or_crop_background(); self:diffuse(Color1) self:effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end end; GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); diff --git a/BackgroundEffects/StretchNormalAlignLeft.lua b/BackgroundEffects/StretchNormalAlignLeft.lua index b145ef69d2..3ea7362832 100644 --- a/BackgroundEffects/StretchNormalAlignLeft.lua +++ b/BackgroundEffects/StretchNormalAlignLeft.lua @@ -3,7 +3,13 @@ local Color1 = color(Var "Color1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchNormalBlue.lua b/BackgroundEffects/StretchNormalBlue.lua index b5b7c629fb..2deae2baff 100644 --- a/BackgroundEffects/StretchNormalBlue.lua +++ b/BackgroundEffects/StretchNormalBlue.lua @@ -3,7 +3,13 @@ local Color1 = color("0,0,1,1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchNormalGreen.lua b/BackgroundEffects/StretchNormalGreen.lua index f90436b90f..225f6ac936 100644 --- a/BackgroundEffects/StretchNormalGreen.lua +++ b/BackgroundEffects/StretchNormalGreen.lua @@ -3,7 +3,13 @@ local Color1 = color("0,1,0,1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchNormalRed.lua b/BackgroundEffects/StretchNormalRed.lua index caa8ccbfa9..56b7de63f5 100644 --- a/BackgroundEffects/StretchNormalRed.lua +++ b/BackgroundEffects/StretchNormalRed.lua @@ -3,7 +3,13 @@ local Color1 = color("1,0,0,1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchPaused.lua b/BackgroundEffects/StretchPaused.lua index 41c81bdd52..46a534f398 100644 --- a/BackgroundEffects/StretchPaused.lua +++ b/BackgroundEffects/StretchPaused.lua @@ -2,7 +2,13 @@ local Color1 = color(Var "Color1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;pause;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):pause():effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchRewind.lua b/BackgroundEffects/StretchRewind.lua index 9d649131f2..4f3ccf23d2 100644 --- a/BackgroundEffects/StretchRewind.lua +++ b/BackgroundEffects/StretchRewind.lua @@ -10,6 +10,10 @@ local t = Def.ActorFrame { self:position(0) end self:effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end end; GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); diff --git a/BackgroundEffects/UpperLeft.lua b/BackgroundEffects/UpperLeft.lua index 0987f8f1c4..7e04b9992e 100644 --- a/BackgroundEffects/UpperLeft.lua +++ b/BackgroundEffects/UpperLeft.lua @@ -3,7 +3,13 @@ local Color1 = color(Var "Color1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/Visualization2File.lua b/BackgroundEffects/Visualization2File.lua index c729ed7b9d..5212c256b1 100644 --- a/BackgroundEffects/Visualization2File.lua +++ b/BackgroundEffects/Visualization2File.lua @@ -3,13 +3,25 @@ local Color2 = color(Var "Color2"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; LoadActor(Var "File2") .. { - OnCommand=cmd(blend,"BlendMode_Add";x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scaletoclipped,SCREEN_WIDTH,SCREEN_HEIGHT;diffuse,Color2;effectclock,"music"); + OnCommand=function(self) + self:blend("BlendMode_Add"):x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scaletoclipped(SCREEN_WIDTH,SCREEN_HEIGHT):diffuse(Color2):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/Visualization2FileFlash.lua b/BackgroundEffects/Visualization2FileFlash.lua index 9bc9f3e13f..d01a22a4d6 100644 --- a/BackgroundEffects/Visualization2FileFlash.lua +++ b/BackgroundEffects/Visualization2FileFlash.lua @@ -4,14 +4,26 @@ local Color2 = color(Var "Color2"); local t = Def.ActorFrame {}; t[#t+1] = LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;effectclock,"music"); - GainFocusCommand=cmd(play); - LoseFocusCommand=cmd(pause); + OnCommand=function(self) + self:x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color1):effectclock("music") + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, + GainFocusCommand=cmd(play); + LoseFocusCommand=cmd(pause); }; if Var("File2") ~= nil then t[#t+1] = LoadActor(Var("File2")) .. { - OnCommand=cmd(blend,"BlendMode_Add";x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color2;effectclock,"music";linear,1;diffusealpha,0); + OnCommand=function(self) + self:blend("BlendMode_Add"):x(SCREEN_CENTER_X):y(SCREEN_CENTER_Y):scale_or_crop_background():diffuse(Color2):effectclock("music"):linear(1):diffusealpha(0) + -- Explanation in StretchNoLoop.lua. + if self.GetTexture then + self:GetTexture():rate(self:GetParent():GetUpdateRate()) + end + end, GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 3da66d0f3f..f8390a8729 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -4,6 +4,52 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ +2015/02/04 +---------- +* [ActorFrame] GetUpdateRate added. [kyzentun] +* [Background] Using the wrong transition name no longer crashes. + Playback rate is applied to videos. + Checkerboard and other BackgroundEffects that use the same file twice no + longer play videos back at multiplied speed. [kyzentun] +* [Sprite] Get/SetDecodeMovie added. [kyzentun] + +2015/02/03 +---------- +* [MusicWheel] HideActiveSectionTitle metric added. [djpohly] + +2015/02/02 +---------- +* [ActorMultiVertex] ForceStateUpdate and Get/SetDecodeMovie added. [kyzentun] +* [RageTexture] GetWidth and Height functions added. + ( means Source, Texture, or Image) [kyzentun] +* [Scripts] find_missing_strings_in_theme_translations function added to + _fallback scripts to assist translators in finding what needs to be + translated. If you need/want to run it on your them, write a piece of lua + like this: + find_missing_strings_in_theme_translations("_fallback", "en.ini") + The first arg is the folder name of the theme to look at. + The second arg is the name of the language that is fully translated. All + other languages will be compared to it to decide what is missing or unused. + [kyzentun] +* [Song] GetBGChanges added. [kyzentun] + +2015/02/01 +---------- +* [ActorMultiVertex] Animation state system added. AMVs can now have + animated textures controlled by states written in lua. [kyzentun] + +2015/01/31 +---------- +* [EditMode] Want more lead in time before recording starts? + It's a preference. [kyzentun] + +2015/01/30 +---------- +* [Actor] Wrapper states added. This makes wrapping an Actor inside an + ActorFrame for any reason unnecessary, and makes it possible to do things + that were only possible by wrapping an Actor in an ActorFrame to Actors + that you couldn't put inside a frame before. [kyzentun] + 2015/01/20 ---------- * [ScreenSelect] ChoiceNames can be a lua command that is evaluated to get a diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index beeca21152..9fe1ca6ca5 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -212,6 +212,7 @@ + @@ -257,6 +258,7 @@ + @@ -278,6 +280,7 @@ + @@ -287,6 +290,7 @@ + @@ -301,6 +305,7 @@ + @@ -450,6 +455,7 @@ + @@ -489,22 +495,42 @@ + + + + + + + + + + + + + + + + + + + + @@ -569,6 +595,7 @@ + @@ -581,6 +608,7 @@ + @@ -1365,6 +1393,12 @@ + + + + + + @@ -1488,6 +1522,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index 23eaa72ec0..08a634a4d4 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -145,6 +145,12 @@ save yourself some time, copy this for undocumented things: [02 Utilities.lua] Old name for approach. + + This function creates files in the theme's Languages folder listing all the strings that have no translation and all the strings that are unused.
+ Strings that do not have an entry in the master language are considered unused.
+ master_lang_name is the name of the ini file that contains the language with all strings used by the theme.
+ Example: find_missing_strings_in_theme_translations("my_best_theme", "en.ini") +
[02 Utilities.lua] Return the index of a true value in list. @@ -831,6 +837,20 @@ save yourself some time, copy this for undocumented things: + + This adds a wrapper state around the Actor, which is like wrapping the Actor in an ActorFrame, except that you can use it on any actor, and add or remove wrapper states in response to things that happen while the screen is being used. (wrapping an Actor in an ActorFrame normally requires setting it up before the screen starts)
+ The ActorFrame that is returned is the wrapper state, for convenience.
+ An Actor can have any number of wrapper states. Use GetWrapperState to access wrapper states for the actor. +
+ + Returns the number of wrapper states the actor has. + + + Returns the wrapper state at index i. Think of wrapper states with a higher index as being "further out". Actor is inside Wrapper 1, Wrapper 1 is inside Wrapper 2, Wrapper 2 is inside Wrapper 3, and so on. + + + Removes the wrapper state at index i. + Returns the Actor's parent, or nil if it doesn't have one. @@ -1415,6 +1435,9 @@ save yourself some time, copy this for undocumented things: Returns the number of children in the ActorFrame. + + Gets the update function's rate. + Plays the sCommandName command on the ActorFrame's children. @@ -1517,6 +1540,72 @@ save yourself some time, copy this for undocumented things:
+ + The list of quad states is used to determine which animation state is used for each quad. The offset is added to the AMV's current state, and the resulting state is used. + + + Adds an animation state to the ActorMultiVertex. The state_data table must be like this:
+ {{left, top, right, bottom}, delay}
+ left, top, right, and bottom are pixel coordinates, starting at 0. If delay is 0 or negative, the state will last forever. +
+ + Forces the AMV to update the texture coordinates on all its quads, even if the current state has not changed. + + + Returns whether the AMV uses the animation state. + + + Sets whether the AMV uses the animation state.
+ This works best when using DrawMode_Quads.
+ AMV's can have animated textures like sprites. Each state tells the AMV what part of the texture to use, and how long the state lasts.
+ Use AddState to add a state onto the end, or SetStateProperties to set all the states at once, or SetState to set a single state.
+ Each quad has its own offset that is added to the current state. Use AddQuadState to add to the list of quad states, or SetQuadState to set an existing quad state. +
+ + Returns the number of states the AMV has. + + + Returns the number of quad states in the destination tween state for the AMV. + + + Returns the id of the current state. + + + Gets whether the AMV should call the decode function for its texture during updates. + + + Sets whether the AMV should call the decode function for its texture during updates. + + + Sets the current state. + + + Returns the offset of the requested quad state. + + + Sets the offset of the requested quad state. + + + Returns a table containing the data for the requested state. + + + Sets the requested state to the data in state_data. Similar to AddState, but SetStateData only works on states that have already been added. + + + Each element of the table must be a state_data table, and is used to construct one state. The table as a whole is the entire list of all states for the AMV. + + + Removes the requested state from the state list. + + + Removes the requested quad state from the quad state list. + + + Sets the delay for every state to delay. + + + Sets how far into its animation the AMV is. + Sets vertex number index with the properties provided. The tables of properties are each optional and can be provided in any order. @@ -3987,6 +4076,24 @@ save yourself some time, copy this for undocumented things:
+ + Returns the source width. + + + Returns the source height. + + + Returns the texture width. + + + Returns the texture height. + + + Returns the image width. + + + Returns the image height. + Returns the number of frames in this texture. @@ -4295,6 +4402,11 @@ save yourself some time, copy this for undocumented things: Returns the path to the song's banner. + + Returns a table with all the data for the song's BGCHANGES line.
+ Each element of the table is one change like this:
+ {start_beat= 1.0, rate= 1.0, transition= "example", effect= "example", file1= "example", file2= "example", color1= "#FFFFFFFF", color2= "#FFFFFFFF"} +
Returns the path to the song's CD image. @@ -4653,6 +4765,9 @@ save yourself some time, copy this for undocumented things: Returns the length of the animation in seconds. + + Gets whether the Sprite should call the decode function for its texture during updates. + Return the number of states this Sprite has. @@ -4693,6 +4808,9 @@ save yourself some time, copy this for undocumented things: Turns off the custom pos coords for the sprite. + + Sets whether the Sprite should call the decode function for its texture during updates. + Set the to mode. diff --git a/Docs/Userdocs/bgchanges_format.txt b/Docs/Userdocs/bgchanges_format.txt new file mode 100644 index 0000000000..574264e179 --- /dev/null +++ b/Docs/Userdocs/bgchanges_format.txt @@ -0,0 +1,22 @@ +The BGCHANGES line in a simfile is used to control what backgrounds are loaded by the simfile and when they appear. + +The data is between the colon and the semicolon. +Each entry is separated from the next by a comma. +Each entry is composed of 1 to 11 values separated by equals. +The meanings of the values are as follows: +1. start beat +2. file or folder name +3. play rate +4. Backward compatible transition type. CrossFade is used if this is not 0. +5. Backward compatible effect flag. StretchRewind is used if this is not 0. +6. Backward compatible effect flag. StretchNoLoop is used if this is not 0. +7. Name of the effect file to use. The BackgroundEffects folder will be searched for a match. +8. Name of the second file. +9. Name of the transition file to use. The BackgroundTransitions folder will be searched for a match. +10. Color string in either "1.0^0.5^0.75^0.25" or "#ff7fcf3f" form. The fourth channel is optional. +11. Second color string, same format. + +The file names (values 2 and 8) and the colors (values 10 and 11) are passed to the effect file as thread variables. Most effects do not use the second file. + + +The FGCHANGES line uses the same format, except only the start beat and first file are used (values 1 and 2). diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 10505b2a40..cf0de8bf02 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -397,6 +397,7 @@ Edit Courses/Mods=Edit Courses/Mods Edit Songs/Steps=Edit Songs/Steps Practice Songs/Steps=Practice Songs/Steps EditorShowBGChangesPlay=Choose whether to display song backgrounds while playing. +EditRecordModeLeadIn=Set the amount of lead-in time before recording starts. Effect=Effect EffectsReceptor=Add alternative behaviors to the receptors and notes. EffectsArrow=Add alternative behaviors to the receptors and notes. @@ -555,6 +556,38 @@ GamePrefDefaultFail=Immediate fail causes a player to die when their life bar re UserPrefScoringMode=Select the scoring mode to be used when not in a course. [OptionNames] ++0 s=+0 s ++1 s=+1 s ++2 s=+2 s ++3 s=+3 s ++4 s=+4 s ++5 s=+5 s ++6 s=+6 s ++7 s=+7 s ++8 s=+8 s ++9 s=+9 s ++10 s=+10 s ++11 s=+11 s ++12 s=+12 s ++13 s=+13 s ++14 s=+14 s ++15 s=+15 s ++16 s=+16 s ++17 s=+17 s ++18 s=+18 s ++19 s=+19 s ++20 s=+20 s ++21 s=+21 s ++22 s=+22 s ++23 s=+23 s ++24 s=+24 s ++25 s=+25 s ++26 s=+26 s ++27 s=+27 s ++28 s=+28 s ++29 s=+29 s ++30 s=+30 s ++31 s=+31 s 0ms=0ms 10ms=10ms 20ms=20ms @@ -1000,6 +1033,7 @@ Edit scrolling factor=Edit scrolling factor Edit fake=Edit fake segment Editor options=Options EditorShowBGChangesPlay=Show Backgrounds +EditRecordModeLeadIn=Record Lead In Erase step timing=Erase step timing Effect=Effect EffectsReceptor=Effects diff --git a/Themes/_fallback/Languages/pl.ini b/Themes/_fallback/Languages/pl.ini index ef9712cf90..0b20d9cb48 100644 --- a/Themes/_fallback/Languages/pl.ini +++ b/Themes/_fallback/Languages/pl.ini @@ -361,6 +361,7 @@ Edit Courses=Edycja Maratonów Edit Songs/Steps=Edycja Piosenek Practice Songs/Steps=Testowanie Piosenek EditorShowBGChangesPlay=Wyświetlanie tła piosenki podczas gry. +EditRecordModeLeadIn=Ustaw czas przejścia przed rozpoczęciem nagrywania. Effect=Efekt EffectsReceptor=Dodaje alternatywne zachowanie dla receptorów i strzałek. EffectsArrow=Dodaje alternatywne zachowanie dla receptorów i strzałek. @@ -898,6 +899,7 @@ Edit scrolling factor=Edycja parametru przesuwania Edit fake=Modyfikacja segmentu Fake Editor options=Opcje EditorShowBGChangesPlay=Pokaż tła +EditRecordModeLeadIn=Nagrywaj przejście Erase step timing=Skasuj timing Effect=Efekt EffectsReceptor=Efekty na Receptorach diff --git a/Themes/_fallback/Scripts/find_missing_lang_strings.lua b/Themes/_fallback/Scripts/find_missing_lang_strings.lua new file mode 100644 index 0000000000..3d4584558e --- /dev/null +++ b/Themes/_fallback/Scripts/find_missing_lang_strings.lua @@ -0,0 +1,64 @@ +-- All other languages are compared to the master language to determine what is +-- missing and what is unused. +-- The list of missing strings for a language is saved to lang_missing.ini, +-- where lang is the name of the language. +-- The list of unused strings is saved to lang_unused.ini. + +function find_missing_strings_in_theme_translations(theme_name, master_name) + local lang_folder= "Themes/"..theme_name.."/Languages/" + local master_language= IniFile.ReadFile(lang_folder .. master_name) + local other_languages= {} + local language_names= FILEMAN:GetDirListing(lang_folder) + -- Load all languages. + for i, name in ipairs(language_names) do + if name ~= master_name and not name:find("missing") + and not name:find("unused") then + other_languages[#other_languages+1]= { + name= name, data= IniFile.ReadFile(lang_folder .. name)} + end + end + -- Find out what is missing from each language. + local missing_list= {} + local function find_missing_in_section(section_name, section) + local function add_str_to_missing(str_name, str_value) + for i, other in ipairs(other_languages) do + if not other.data[section_name] or + not other.data[section_name][str_name] then + if not missing_list[other.name] then + missing_list[other.name]= {} + end + if not missing_list[other.name][section_name] then + missing_list[other.name][section_name]= {} + end + missing_list[other.name][section_name][str_name]= str_value + end + end + end + foreach_ordered(section, add_str_to_missing) + end + foreach_ordered(master_language, find_missing_in_section) + local function save_missing_data(lang_name, data) + IniFile.WriteFile( + lang_folder .. lang_name:sub(1, -5) .. "_missing.ini", data) + end + foreach_ordered(missing_list, save_missing_data) + -- Find out what is extra in each language. + for i, other in ipairs(other_languages) do + local unused= {} + local function find_unused_in_section(section_name, section) + local function add_str_to_unused(str_name, str_value) + if not master_language[section_name] or + not master_language[section_name][str_name] then + if not unused[section_name] then + unused[section_name]= {} + end + unused[section_name][str_name]= str_value + end + end + foreach_ordered(section, add_str_to_unused) + end + foreach_ordered(other.data, find_unused_in_section) + IniFile.WriteFile( + lang_folder .. other.name:sub(1, -5) .. "_unused.ini", unused) + end +end diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index a5686ff6c9..9d961f7f39 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -906,6 +906,7 @@ SwitchSeconds=0.10 RandomPicksLockedSongs=true UseSectionsWithPreferredGroup=false OnlyShowActiveSection=false +HideActiveSectionTitle=true RemindWheelPositions=false # RouletteSwitchSeconds=0.05 @@ -4132,7 +4133,7 @@ PlayMusic=false TimerSeconds=-1 ShowStyleIcon=false -LineNames="1,2,3,4,5,6,R1,R2,7,8,9,10,Attacks,11,12,13,14,15,16" +LineNames="1,2,3,4,5,6,R1,R2,7,8,9,10,Attacks,11,12,13,14,15,16,lead_in" # uses legacy speed line Line1="list,Speed" Line2="list,Accel" @@ -4153,6 +4154,7 @@ Line13="list,Assist" Line14="list,Rate" Line15="list,AutoAdjust" Line16="conf,EditorShowBGChangesPlay" +Linelead_in="conf,EditRecordModeLeadIn" OutCancelCommand= [StepsDisplayEdit] diff --git a/Themes/default/Languages/pl.ini b/Themes/default/Languages/pl.ini index ce8cea874c..7191c08eda 100644 --- a/Themes/default/Languages/pl.ini +++ b/Themes/default/Languages/pl.ini @@ -9,7 +9,7 @@ EventStageCounter=Piosenka %03i [ScreenTitleMenu] HelpText=&BACK; Wyjście &START; Zatwierdź &MENUUP;&MENUDOWN; Wybierz Network OK=Sieć OK -Offline=Brak poŁĄczenia +Offline=Brak połączenia Connected to %s=Podłączony do %s CurrentGametype=Tryb gry: %s LifeDifficulty=Zużycie energii: %s @@ -24,7 +24,10 @@ EventMode=Tryb Imprezy JointPremiumMain=Premia Łączona JointPremiumSecondary=Dwóch graczy może grac za jeden kredyt! DoublesPremiumMain=Podwójna Premia -DoublesPremiumSecondary=Graj w trybie Double za jeden kredyt! +DoublesPremiumSecondary=Graj w trybie Dwuosobowym za jeden kredyt! + +[ScreenCaution] +HelpText=&START; Kontynuuj [ScreenDemonstration] Demonstration=Demonstracja @@ -83,7 +86,7 @@ HelpText= HelpText= [ScreenEvaluation] -HelpText=&BACK; Wyjście &START; Dalej &MENULEFT;+&MENURIGHT; or &SELECT; Screenshot +HelpText=&BACK; Wyjście &START; Dalej &MENULEFT;+&MENURIGHT; lub &SELECT; Zrzut ekranu LifeDifficulty=Zużycie energii: %s TimingDifficulty=Ocena trafień: %s MachineRecord=Rekord Maszyny #%i! @@ -91,6 +94,9 @@ PersonalRecord=Rekord Życiowy #%i! ITG DP:=ITG DP: MIGS DP:=MIGS DP: +[ScreenContinue] +HelpText=&START; Advance Timer + [OptionTitles] AutoSetStyle=Automatycznie Ustaw Styl NotePosition=Pozycja Strzałek @@ -130,7 +136,7 @@ Appearance=Kontrola widoczności strzałek. Turn=Zmiana choreografii stepchart`a po przez modyfikacje pozycji istniejących strzałek. Insert=Zmiana choreografii stepchart`a po przez proceduralne dodanie nowych strzałek. Holds=Zmienia cześć strzałki w HOLD`y -Mines=Dodanie lub usuniecie min. +Mines=Dodanie lub usuniecie Min. PlayerAutoPlay=Program odgrywa piosenkę automatycznie ScoreDisplay=Zmiana sposobu wyświetlania punktacji. ProTiming=Zmiana sposobu wyświetlania dokładności trafienia w strzałkę. @@ -188,10 +194,10 @@ Importing Songs=Importowanie piosenek z zainstalowanych wcześniej wersji Stepma Reload Songs=Przeładowanie Piosenek Exit=Powrót do Ekranu Startowego -Explanation-WhereToFind=Uruchamia stronę www z informacja miejscach i sposobach na znalezienie piosenek. -Explanation-HowToInstall=Uruchamia stronę www z instrukcja instalacji piosenek. -Explanation-AdditionalFolders=Jeśli masz zainstalowane inne instancje Stepmanii, możesz użyć opcji AdditionalFolder z pliku ustawień by załadować je bez konieczności ich kopiowania. -Explanation-ReloadSongs=Ta czynność jest konieczna jeśli dodano/zmieniono/osunięto piosenki w trakcie pracy programu. +Explanation-WhereToFind=Uruchamia stronę www z informacją miejscach i sposobach na znalezienie piosenek. +Explanation-HowToInstall=Uruchamia stronę www z instrukcją instalacji piosenek. +Explanation-AdditionalFolders=Jeśli masz zainstalowane inne instancje Stepmanii, możesz użyć opcji Foldery Dodatkowe z pliku ustawień by załadować je bez konieczności ich kopiowania. +Explanation-ReloadSongs=Ta czynność jest konieczna jeśli dodano/zmieniono/usunięto piosenki w trakcie pracy programu. Explanation-Exit=Powrót do Ekranu Startowego. [OptionNames] @@ -209,12 +215,12 @@ HelpText=Przytrzymaj &BACK; lub &START; aby wyjść. [PaneDisplay] Taps=Kroki Jumps=Skoki -Holds=Holdy +Holds=Holds Mines=Miny -Hands=RĘce -Rolls=Rolle -Lifts=Lifty -Fakes=Fejki +Hands=Ręce +Rolls=Rolls +Lifts=Lifts +Fakes=Fakes S=S V=V A=A @@ -230,6 +236,13 @@ Play again soon!=Zagraj jeszcze raz! [ScreenHowToPlay] How To Play StepMania=Jak Grać w Stepmanię +Information=Informacja + +Feet=Twoje stopy będą wykorzystywane do gry! +Tap=Kiedy strzałki pokryją się z tym punktem,\npołóż nogę na odpowiednim panelu. +Jump=Połóż nogi na obydwu panelach jeśli pojawią się dwie\nróżne strzałki w tym samym czasie! +Miss=Jeśli wielokrotnie będziesz się mylił,\ntwój wskaźnik tańca będzie się zmniejszał\naż gra się skończy! + [Protiming] -MS=MS \ No newline at end of file +MS=MS diff --git a/Themes/default/Scripts/02 ThemePrefs.lua b/Themes/default/Scripts/02 ThemePrefs.lua index c95d3fd7d5..f13ce3130f 100644 --- a/Themes/default/Scripts/02 ThemePrefs.lua +++ b/Themes/default/Scripts/02 ThemePrefs.lua @@ -116,7 +116,7 @@ end -- screen filter function OptionRowScreenFilter() - local t = { + return { Name="ScreenFilter", LayoutType = "ShowAllInRow", SelectType = "SelectOne", @@ -147,14 +147,12 @@ function OptionRowScreenFilter() end end end, - }; - setmetatable(t, t) - return t + } end -- protiming function OptionRowProTiming() - local t = { + return { Name = "ProTiming", LayoutType = "ShowAllInRow", SelectType = "SelectOne", @@ -181,8 +179,6 @@ function OptionRowProTiming() SetUserPref("UserPrefProtiming" .. ToEnumShortString(pn), bSave) end } - setmetatable(t, t) - return t end --[[ end option rows ]] diff --git a/Themes/default/metrics.ini b/Themes/default/metrics.ini index f1a18125ff..9805deacea 100644 --- a/Themes/default/metrics.ini +++ b/Themes/default/metrics.ini @@ -2062,7 +2062,7 @@ TimerOnCommand=visible,false [ScreenPractice] [ScreenEditOptions] -LineNames="1,2,3,4,5,6,R1,R2,7,8,9,10,Attacks,11,12,13,14,15,16,SF" +LineNames="1,2,3,4,5,6,R1,R2,7,8,9,10,Attacks,11,12,13,14,15,16,SF,lead_in" Line1="lua,ArbitrarySpeedMods()" LineSF="lua,OptionRowScreenFilter()" diff --git a/Xcode/stepmania.xcodeproj/project.pbxproj b/Xcode/stepmania.xcodeproj/project.pbxproj index 64a6d1d13f..afa80d112a 100644 --- a/Xcode/stepmania.xcodeproj/project.pbxproj +++ b/Xcode/stepmania.xcodeproj/project.pbxproj @@ -8408,7 +8408,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES; - SDKROOT = macosx10.6; + SDKROOT = macosx; SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_INSTALLED_PRODUCT = NO; STRIP_STYLE = "non-global"; @@ -8789,7 +8789,7 @@ LINKER_DISPLAYS_MANGLED_NAMES = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES; - SDKROOT = macosx10.6; + SDKROOT = macosx; SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_STYLE = "non-global"; USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../extern/jsoncpp/include $(PROJECT_DIR)/../extern/vorbis"; @@ -9102,7 +9102,7 @@ LINKER_DISPLAYS_MANGLED_NAMES = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; PRESERVE_DEAD_CODE_INITS_AND_TERMS = YES; - SDKROOT = macosx10.6; + SDKROOT = macosx; SHARED_PRECOMPS_DIR = "/Library/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders/$(PRODUCT_NAME)/$(CONFIGURATION)"; STRIP_STYLE = "non-global"; USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/../extern/glew-1.5.8/include $(PROJECT_DIR)/../extern/jsoncpp/include $(PROJECT_DIR)/../extern/vorbis"; diff --git a/configure.ac b/configure.ac index e875775951..9cb0d610a2 100644 --- a/configure.ac +++ b/configure.ac @@ -388,6 +388,21 @@ AC_SUBST(RESFLAGS) dnl Add these after all tests are done as they don't exist just yet. LIBS="$LIBS $FFMPEG_LIBS" +# Selection between bundled pcre and system pcre +AC_ARG_WITH(system-pcre, AS_HELP_STRING([--with-system-pcre],[Disable building of bundled libpcre]), with_system_pcre=$withval, with_system_pcre=no) +AM_CONDITIONAL(USE_SYSTEM_PCRE, test "$with_system_pcre" == "yes") + +if test "$with_system_pcre" == "yes"; then + have_libpcre=yes + AC_CHECK_HEADER(pcre.h, , have_libpcre=no) + if test "$have_libpcre" = "no"; then + AC_MSG_ERROR([If you want to use system libpcre, please make sure that it is installed. Otherwise please configure with --without-system-pcre.]) + else + AC_DEFINE([USE_SYSTEM_PCRE], 1, [Build with system libpcre]) + LIBS="$LIBS -lpcre" + fi +fi + AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(bundle/Makefile) AC_CONFIG_FILES(src/Makefile) diff --git a/extern/jsoncpp/libjson-net2011.vcxproj b/extern/jsoncpp/libjson-net2011.vcxproj new file mode 100644 index 0000000000..8d4c2eb738 --- /dev/null +++ b/extern/jsoncpp/libjson-net2011.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0DCAA088-FC09-4422-892B-8E89F1F798CB} + libjson + libjson + + + + StaticLibrary + true + v110 + MultiByte + + + StaticLibrary + false + v110 + true + MultiByte + + + + + + + + + + + + + $(IntDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + + + $(IntDir) + $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(Configuration)\ + + + + Level3 + Disabled + true + + + ./include + + + true + + + + + Level3 + MaxSpeed + true + true + true + + + ./include + + + true + true + true + + + + + + + + + + + \ No newline at end of file diff --git a/extern/jsoncpp/libjson-net2011.vcxproj.filters b/extern/jsoncpp/libjson-net2011.vcxproj.filters new file mode 100644 index 0000000000..23fe16e111 --- /dev/null +++ b/extern/jsoncpp/libjson-net2011.vcxproj.filters @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/extern/jsoncpp/src/lib_json/json_reader.cpp b/extern/jsoncpp/src/lib_json/json_reader.cpp index 86cafcafaa..3e79ab733e 100644 --- a/extern/jsoncpp/src/lib_json/json_reader.cpp +++ b/extern/jsoncpp/src/lib_json/json_reader.cpp @@ -1,5 +1,5 @@ -#include <../extern/jsoncpp/include/json/reader.h> -#include <../extern/jsoncpp/include/json/value.h> +#include "json/reader.h" +#include "json/value.h" #include #include #include diff --git a/extern/jsoncpp/src/lib_json/json_value.cpp b/extern/jsoncpp/src/lib_json/json_value.cpp index fb480daa4a..1ecacd45d0 100644 --- a/extern/jsoncpp/src/lib_json/json_value.cpp +++ b/extern/jsoncpp/src/lib_json/json_value.cpp @@ -1,6 +1,6 @@ #include -#include <../extern/jsoncpp/include/json/value.h> -#include <../extern/jsoncpp/include/json/writer.h> +#include "json/value.h" +#include "json/writer.h" #include #include #include diff --git a/extern/jsoncpp/src/lib_json/json_writer.cpp b/extern/jsoncpp/src/lib_json/json_writer.cpp index 7868a22cbf..41373250bb 100644 --- a/extern/jsoncpp/src/lib_json/json_writer.cpp +++ b/extern/jsoncpp/src/lib_json/json_writer.cpp @@ -1,4 +1,4 @@ -#include <../extern/jsoncpp/include/json/writer.h> +#include "json/writer.h" #include #include #include diff --git a/src/Actor.cpp b/src/Actor.cpp index 9dac9f0454..1096bf1fe2 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -1,5 +1,6 @@ #include "global.h" #include "Actor.h" +#include "ActorFrame.h" #include "RageDisplay.h" #include "RageUtil.h" #include "RageMath.h" @@ -172,6 +173,11 @@ Actor::~Actor() { StopTweening(); UnsubscribeAll(); + for(size_t i= 0; i < m_WrapperStates.size(); ++i) + { + SAFE_DELETE(m_WrapperStates[i]); + } + m_WrapperStates.clear(); } Actor::Actor( const Actor &cpy ): @@ -187,6 +193,12 @@ Actor::Actor( const Actor &cpy ): CPY( m_FakeParent ); CPY( m_pLuaInstance ); + m_WrapperStates.resize(cpy.m_WrapperStates.size()); + for(size_t i= 0; i < m_WrapperStates.size(); ++i) + { + m_WrapperStates[i]= new ActorFrame(*dynamic_cast(cpy.m_WrapperStates[i])); + } + CPY( m_baseRotation ); CPY( m_baseScale ); CPY( m_fBaseAlpha ); @@ -296,7 +308,6 @@ void Actor::Draw() { return; // early abort } - bool fake_parent_partially_opaque= true; if(m_FakeParent) { if(!m_FakeParent->m_bVisible || m_FakeParent->m_fHibernateSecondsLeft > 0 @@ -305,31 +316,99 @@ void Actor::Draw() return; } m_FakeParent->PreDraw(); - fake_parent_partially_opaque= m_FakeParent->PartiallyOpaque(); - } - - this->PreDraw(); - ASSERT( m_pTempState != NULL ); - if(PartiallyOpaque() && fake_parent_partially_opaque) - { - if(m_FakeParent) + if(!m_FakeParent->PartiallyOpaque()) { - m_FakeParent->BeginDraw(); - } - // call the most-derived versions - this->BeginDraw(); - this->DrawPrimitives(); // call the most-derived version of DrawPrimitives(); - this->EndDraw(); - if(m_FakeParent) - { - m_FakeParent->EndDraw(); + m_FakeParent->PostDraw(); + return; } } - - this->PostDraw(); + if(m_FakeParent) { + m_FakeParent->BeginDraw(); + } + size_t wrapper_states_used= 0; + RageColor last_diffuse; + RageColor last_glow; + bool use_last_diffuse= false; + // dont_abort_draw exists because if one of the layers is invisible, + // there's no point in continuing. -Kyz + bool dont_abort_draw= true; + // abort_with_end_draw exists because PreDraw happens before the + // opaqueness test, so if we abort at the opaqueness test, there isn't + // a BeginDraw to match the EndDraw. -Kyz + bool abort_with_end_draw= true; + // It's more intuitive to apply the highest index wrappers first. + // On the lua side, it looks like this: + // wrapper[3] is the outermost frame. wrapper[2] is inside wrapper[3]. + // wrapper[1] is inside wrapper[2]. The actor is inside wrapper[1]. + // -Kyz + for(size_t i= m_WrapperStates.size(); i > 0 && dont_abort_draw; --i) + { + Actor* state= m_WrapperStates[i-1]; + if(!state->m_bVisible || state->m_fHibernateSecondsLeft > 0 || + state->EarlyAbortDraw()) + { + dont_abort_draw= false; + } + else + { + state->PreDraw(); + if(state->PartiallyOpaque()) + { + state->BeginDraw(); + last_diffuse= state->m_pTempState->diffuse[0]; + last_glow= state->m_pTempState->glow; + use_last_diffuse= true; + if(i > 1) + { + m_WrapperStates[i-2]->SetInternalDiffuse(last_diffuse); + m_WrapperStates[i-2]->SetInternalGlow(last_glow); + } + } + else + { + dont_abort_draw= false; + abort_with_end_draw= false; + } + ++wrapper_states_used; + } + } + // call the most-derived versions + if(dont_abort_draw) + { + if(use_last_diffuse) + { + this->SetInternalDiffuse(last_diffuse); + this->SetInternalGlow(last_glow); + } + this->PreDraw(); + ASSERT( m_pTempState != NULL ); + if(PartiallyOpaque()) + { + this->BeginDraw(); + this->DrawPrimitives(); + this->EndDraw(); + } + this->PostDraw(); + } + for(size_t i= 0; i < wrapper_states_used; ++i) + { + Actor* state= m_WrapperStates[i]; + if(abort_with_end_draw) + { + state->EndDraw(); + } + abort_with_end_draw= true; + state->PostDraw(); + state->m_pTempState= NULL; + } + + if(m_FakeParent) + { + m_FakeParent->EndDraw(); m_FakeParent->PostDraw(); + m_FakeParent->m_pTempState= NULL; } m_pTempState = NULL; } @@ -728,6 +807,10 @@ void Actor::Update( float fDeltaTime ) fDeltaTime = -m_fHibernateSecondsLeft; m_fHibernateSecondsLeft = 0; } + for(size_t i= 0; i < m_WrapperStates.size(); ++i) + { + m_WrapperStates[i]->Update(fDeltaTime); + } this->UpdateInternal( fDeltaTime ); } @@ -823,6 +906,26 @@ RString Actor::GetLineage() const return sPath; } +void Actor::AddWrapperState() +{ + ActorFrame* wrapper= new ActorFrame; + wrapper->InitState(); + m_WrapperStates.push_back(wrapper); +} + +void Actor::RemoveWrapperState(size_t i) +{ + ASSERT(i < m_WrapperStates.size()); + SAFE_DELETE(m_WrapperStates[i]); + m_WrapperStates.erase(m_WrapperStates.begin()+i); +} + +Actor* Actor::GetWrapperState(size_t i) +{ + ASSERT(i < m_WrapperStates.size()); + return m_WrapperStates[i]; +} + void Actor::BeginTweening( float time, ITween *pTween ) { ASSERT( time >= 0 ); @@ -1765,6 +1868,40 @@ public: } COMMON_RETURN_SELF; } + static int AddWrapperState(T* p, lua_State* L) + { + p->AddWrapperState(); + p->GetWrapperState(p->GetNumWrapperStates()-1)->PushSelf(L); + return 1; + } + static size_t get_state_index(T* p, lua_State* L, int stack_index) + { + // Lua is one indexed. + int i= IArg(stack_index)-1; + const size_t si= static_cast(i); + if(i < 0 || si >= p->GetNumWrapperStates()) + { + luaL_error(L, "%d is not a valid wrapper state index.", i+1); + } + return si; + } + static int RemoveWrapperState(T* p, lua_State* L) + { + size_t si= get_state_index(p, L, 1); + p->RemoveWrapperState(si); + COMMON_RETURN_SELF; + } + static int GetNumWrapperStates(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetNumWrapperStates()); + return 1; + } + static int GetWrapperState(T* p, lua_State* L) + { + size_t si= get_state_index(p, L, 1); + p->GetWrapperState(si)->PushSelf(L); + return 1; + } static int Draw( T* p, lua_State *L ) { LUA->YieldLua(); @@ -1938,6 +2075,10 @@ public: ADD_METHOD( GetParent ); ADD_METHOD( GetFakeParent ); ADD_METHOD( SetFakeParent ); + ADD_METHOD( AddWrapperState ); + ADD_METHOD( RemoveWrapperState ); + ADD_METHOD( GetNumWrapperStates ); + ADD_METHOD( GetWrapperState ); ADD_METHOD( Draw ); } diff --git a/src/Actor.h b/src/Actor.h index 7957306409..ccce22d864 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -310,6 +310,11 @@ public: void SetFakeParent(Actor* mailman) { m_FakeParent= mailman; } Actor* GetFakeParent() { return m_FakeParent; } + void AddWrapperState(); + void RemoveWrapperState(size_t i); + Actor* GetWrapperState(size_t i); + size_t GetNumWrapperStates() const { return m_WrapperStates.size(); } + /** * @brief Retrieve the Actor's x position. * @return the Actor's x position. */ @@ -604,6 +609,7 @@ public: virtual float GetAnimationLengthSeconds() const { return 0; } virtual void SetSecondsIntoAnimation( float ) {} virtual void SetUpdateRate( float ) {} + virtual float GetUpdateRate() { return 1.0f; } HiddenPtr m_pLuaInstance; @@ -616,6 +622,9 @@ protected: // state without making that actor the parent. It's like having multiple // parents. -Kyz Actor* m_FakeParent; + // WrapperStates provides a way to wrap the actor inside ActorFrames, + // applicable to any actor, not just ones the theme creates. + vector m_WrapperStates; /** @brief Some general information about the Tween. */ struct TweenInfo diff --git a/src/ActorFrame.cpp b/src/ActorFrame.cpp index 2b9bc9c6f0..26591e1eb3 100644 --- a/src/ActorFrame.cpp +++ b/src/ActorFrame.cpp @@ -251,6 +251,12 @@ void ActorFrame::DrawPrimitives() RageColor diffuse = m_pTempState->diffuse[0]; RageColor glow = m_pTempState->glow; + // Word of warning: Actor::Draw duplicates the structure of how an Actor + // is drawn inside of an ActorFrame for its wrapping feature. So if + // you're adding something new to ActorFrames that affects how Actors are + // drawn, make sure to also apply it in Actor::Draw's handling of the + // wrappers. -Kyz + // draw all sub-ActorFrames while we're in the ActorFrame's local coordinate space if( m_bDrawByZPosition ) { @@ -619,6 +625,7 @@ public: static int propagate( T* p, lua_State *L ) { p->SetPropagateCommands( BIArg(1) ); COMMON_RETURN_SELF; } static int fov( T* p, lua_State *L ) { p->SetFOV( FArg(1) ); COMMON_RETURN_SELF; } static int SetUpdateRate( T* p, lua_State *L ) { p->SetUpdateRate( FArg(1) ); COMMON_RETURN_SELF; } + DEFINE_METHOD(GetUpdateRate, GetUpdateRate()); static int SetFOV( T* p, lua_State *L ) { p->SetFOV( FArg(1) ); COMMON_RETURN_SELF; } static int vanishpoint( T* p, lua_State *L ) { p->SetVanishPoint( FArg(1), FArg(2) ); COMMON_RETURN_SELF; } static int GetChild( T* p, lua_State *L ) @@ -732,6 +739,7 @@ public: ADD_METHOD( propagate ); // deprecated ADD_METHOD( fov ); ADD_METHOD( SetUpdateRate ); + ADD_METHOD( GetUpdateRate ); ADD_METHOD( SetFOV ); ADD_METHOD( vanishpoint ); ADD_METHOD( GetChild ); diff --git a/src/ActorFrame.h b/src/ActorFrame.h index 978b9760ac..274da11ba4 100644 --- a/src/ActorFrame.h +++ b/src/ActorFrame.h @@ -76,6 +76,7 @@ public: virtual void HurryTweening( float factor ); void SetUpdateRate( float fUpdateRate ) { m_fUpdateRate = fUpdateRate; } + float GetUpdateRate() { return m_fUpdateRate; } void SetFOV( float fFOV ) { m_fFOV = fFOV; } void SetVanishPoint( float fX, float fY) { m_fVanishX = fX; m_fVanishY = fY; } diff --git a/src/ActorMultiVertex.cpp b/src/ActorMultiVertex.cpp index b3c1102311..d59b20ad33 100644 --- a/src/ActorMultiVertex.cpp +++ b/src/ActorMultiVertex.cpp @@ -15,6 +15,8 @@ #include "LuaManager.h" #include "LocalizedString.h" +const float min_state_delay= 0.0001f; + static const char *DrawModeNames[] = { "Quads", "QuadStrip", @@ -69,6 +71,11 @@ ActorMultiVertex::ActorMultiVertex() _splines[i].redimension(3); _splines[i].m_owned_by_actor= true; } + _skip_next_update= true; + _decode_movie= true; + _use_animation_state= false; + _secs_into_state= 0.0f; + _cur_state= 0; } ActorMultiVertex::~ActorMultiVertex() @@ -86,6 +93,11 @@ ActorMultiVertex::ActorMultiVertex( const ActorMultiVertex &cpy ): CPY( _EffectMode ); CPY( _TextureMode ); CPY( _splines ); + CPY(_skip_next_update); + CPY(_use_animation_state); + CPY(_secs_into_state); + CPY(_cur_state); + CPY(_states); #undef CPY if( cpy._Texture != NULL ) @@ -373,6 +385,199 @@ CubicSplineN* ActorMultiVertex::GetSpline(size_t i) return &(_splines[i]); } +void ActorMultiVertex::SetState(size_t i) +{ + ASSERT(i < _states.size()); + _cur_state= i; + _secs_into_state= 0.0f; +} + +void ActorMultiVertex::SetAllStateDelays(float delay) +{ + FOREACH(State, _states, s) + { + s->delay= delay; + } +} + +float ActorMultiVertex::GetAnimationLengthSeconds() const +{ + float tot= 0.0f; + FOREACH_CONST(State, _states, s) + { + tot+= s->delay; + } + return tot; +} + +void ActorMultiVertex::SetSecondsIntoAnimation(float seconds) +{ + SetState(0); + if(_Texture) + { + _Texture->SetPosition(seconds); + } + _secs_into_state= seconds; + UpdateAnimationState(true); +} + +void ActorMultiVertex::UpdateAnimationState(bool force_update) +{ + AMV_TweenState& dest= AMV_DestTweenState(); + vector& verts= dest.vertices; + vector& qs= dest.quad_states; + if(!_use_animation_state || _states.empty() || + dest._DrawMode == DrawMode_LineStrip || qs.empty()) + { return; } + bool state_changed= force_update; + if(_states.size() > 1) + { + while(_states[_cur_state].delay > min_state_delay && + _secs_into_state + min_state_delay > _states[_cur_state].delay) + { + _secs_into_state-= _states[_cur_state].delay; + _cur_state= (_cur_state + 1) % _states.size(); + state_changed= true; + } + } + if(state_changed) + { + size_t first= dest.FirstToDraw; + size_t last= first+dest.GetSafeNumToDraw(dest._DrawMode, dest.NumToDraw); +#define STATE_ID const size_t state_id= (_cur_state + qs[quad_id % qs.size()]) % _states.size(); + switch(AMV_DestTweenState()._DrawMode) + { + case DrawMode_Quads: + for(size_t i= first; i < last; ++i) + { + const size_t quad_id= (i-first)/4; + STATE_ID; + switch((i-first)%4) + { + case 0: + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.top; + break; + case 1: + verts[i].t.x= _states[state_id].rect.right; + verts[i].t.y= _states[state_id].rect.top; + break; + case 2: + verts[i].t.x= _states[state_id].rect.right; + verts[i].t.y= _states[state_id].rect.bottom; + break; + case 3: + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.bottom; + break; + } + } + break; + case DrawMode_QuadStrip: + for(size_t i= first; i < last; ++i) + { + const size_t quad_id= (i-first)/2; + STATE_ID; + switch((i-first)%2) + { + case 0: + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.top; + break; + case 1: + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.bottom; + break; + } + } + break; + case DrawMode_Strip: + case DrawMode_Fan: + for(size_t i= first; i < last; ++i) + { + const size_t quad_id= (i-first); + STATE_ID; + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.top; + } + break; + case DrawMode_Triangles: + for(size_t i= first; i < last; ++i) + { + const size_t quad_id= (i-first)/3; + STATE_ID; + switch((i-first)%3) + { + case 0: + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.top; + break; + case 1: + verts[i].t.x= _states[state_id].rect.right; + verts[i].t.y= _states[state_id].rect.top; + break; + case 2: + verts[i].t.x= _states[state_id].rect.right; + verts[i].t.y= _states[state_id].rect.bottom; + break; + } + } + break; + case DrawMode_SymmetricQuadStrip: + for(size_t i= first; i < last; ++i) + { + const size_t quad_id= (i-first)/3; + STATE_ID; + switch((i-first)%3) + { + case 0: + case 2: + verts[i].t.x= _states[state_id].rect.left; + verts[i].t.y= _states[state_id].rect.top; + break; + case 1: + verts[i].t.x= _states[state_id].rect.right; + verts[i].t.y= _states[state_id].rect.top; + break; + } + } + break; + } + } +#undef STATE_ID +} + +void ActorMultiVertex::EnableAnimation(bool bEnable) +{ + bool bWasEnabled = m_bIsAnimating; + Actor::EnableAnimation(bEnable); + + if(bEnable && !bWasEnabled) + { + _skip_next_update = true; + } +} + +void ActorMultiVertex::Update(float fDelta) +{ + Actor::Update(fDelta); // do tweening + const bool skip_this_movie_update= _skip_next_update; + _skip_next_update= false; + if(!m_bIsAnimating) { return; } + if(!_Texture) { return; } + float time_passed = GetEffectDeltaTime(); + _secs_into_state += time_passed; + if(_secs_into_state < 0) + { + wrap(_secs_into_state, GetAnimationLengthSeconds()); + } + UpdateAnimationState(); + if(!skip_this_movie_update && _decode_movie) + { + _Texture->DecodeSeconds(max(0, time_passed)); + } +} + void ActorMultiVertex::SetCurrentTweenStart() { AMV_start= AMV_current; @@ -693,11 +898,14 @@ public: if( lua_isnil(L, 1) ) { p->UnloadTexture(); + p->LoadFromTexture(TEXTUREMAN->GetDefaultTextureID()); } else { RageTextureID ID( SArg(1) ); + TEXTUREMAN->DisableOddDimensionWarning(); p->LoadFromTexture( ID ); + TEXTUREMAN->EnableOddDimensionWarning(); } COMMON_RETURN_SELF; } @@ -719,6 +927,200 @@ public: COMMON_RETURN_SELF; } + DEFINE_METHOD(GetUseAnimationState, _use_animation_state); + static int SetUseAnimationState(T* p, lua_State *L) + { + p->_use_animation_state= BArg(1); + COMMON_RETURN_SELF; + } + static int GetNumStates(T* p, lua_State *L) + { + lua_pushnumber(L, p->GetNumStates()); + return 1; + } + static void FillStateFromLua(lua_State *L, ActorMultiVertex::State& state, + RageTexture* tex, int index) + { + if(tex == NULL) + { + luaL_error(L, "The texture must be set before adding states."); + } + // State looks like this: + // {{left, top, right, bottom}, delay} +#define DATA_ERROR(i) \ + if(!lua_istable(L, i)) \ + { \ + luaL_error(L, "The state data must be in a table like this: {{left, top, right, bottom}, delay}"); \ + } +#define SET_SIDE(i, side) \ + lua_rawgeti(L, -1, i); \ + state.side= FArg(-1); \ + lua_pop(L, 1); + + DATA_ERROR(index); + lua_rawgeti(L, index, 1); + DATA_ERROR(-1); + SET_SIDE(1, rect.left); + SET_SIDE(2, rect.top); + SET_SIDE(3, rect.right); + SET_SIDE(4, rect.bottom); + lua_pop(L, 1); + SET_SIDE(2, delay); + const float width_ratio= tex->GetImageToTexCoordsRatioX(); + const float height_ratio= tex->GetImageToTexCoordsRatioY(); + state.rect.left= state.rect.left * width_ratio; + state.rect.top= state.rect.top * height_ratio; + // Pixel centers are at .5, so add an extra pixel to the size to adjust. + state.rect.right= (state.rect.right * width_ratio) + width_ratio; + state.rect.bottom= (state.rect.bottom * height_ratio) + height_ratio; +#undef SET_SIDE +#undef DATA_ERROR + } + static int AddState(T* p, lua_State *L) + { + ActorMultiVertex::State s; + FillStateFromLua(L, s, p->GetTexture(), 1); + p->AddState(s); + COMMON_RETURN_SELF; + } + static size_t ValidStateIndex(T* p, lua_State *L, int pos) + { + int index= IArg(pos)-1; + if(index < 0 || static_cast(index) >= p->GetNumStates()) + { + luaL_error(L, "Invalid state index %d.", index+1); + } + return static_cast(index); + } + static int RemoveState(T* p, lua_State *L) + { + p->RemoveState(ValidStateIndex(p, L, 1)); + COMMON_RETURN_SELF; + } + static int GetState(T* p, lua_State *L) + { + lua_pushnumber(L, p->GetState()+1); + return 1; + } + static int SetState(T* p, lua_State *L) + { + p->SetState(ValidStateIndex(p, L, 1)); + COMMON_RETURN_SELF; + } + static int GetStateData(T* p, lua_State *L) + { + RageTexture* tex= p->GetTexture(); + if(tex == NULL) + { + luaL_error(L, "The texture must be set before adding states."); + } + const float width_pix= tex->GetImageToTexCoordsRatioX(); + const float height_pix= tex->GetImageToTexCoordsRatioY(); + const float width_ratio= 1.0f / tex->GetImageToTexCoordsRatioX(); + const float height_ratio= 1.0f / tex->GetImageToTexCoordsRatioY(); + const ActorMultiVertex::State& state= + p->GetStateData(ValidStateIndex(p, L, 1)); + lua_createtable(L, 2, 0); + lua_createtable(L, 4, 0); + lua_pushnumber(L, state.rect.left * width_ratio); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, state.rect.top * height_ratio); + lua_rawseti(L, -2, 2); + lua_pushnumber(L, (state.rect.right - width_pix) * width_ratio); + lua_rawseti(L, -2, 3); + lua_pushnumber(L, (state.rect.bottom + height_pix) * height_ratio); + lua_rawseti(L, -2, 4); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, state.delay); + lua_rawseti(L, -2, 2); + return 1; + } + static int SetStateData(T* p, lua_State *L) + { + ActorMultiVertex::State& state= p->GetStateData(ValidStateIndex(p, L, 1)); + FillStateFromLua(L, state, p->GetTexture(), 2); + COMMON_RETURN_SELF; + } + static int SetStateProperties(T* p, lua_State *L) + { + if(!lua_istable(L, 1)) + { + luaL_error(L, "The states must be inside a table."); + } + RageTexture* tex= p->GetTexture(); + if(tex == NULL) + { + luaL_error(L, "The texture must be set before adding states."); + } + vector new_states; + size_t num_states= lua_objlen(L, 1); + new_states.resize(num_states); + for(size_t i= 0; i < num_states; ++i) + { + lua_rawgeti(L, 1, i+1); + FillStateFromLua(L, new_states[i], tex, -1); + lua_pop(L, 1); + } + p->SetStateProperties(new_states); + COMMON_RETURN_SELF; + } + static int SetAllStateDelays(T* p, lua_State *L) + { + p->SetAllStateDelays(FArg(1)); + COMMON_RETURN_SELF; + } + DEFINE_METHOD(GetAnimationLengthSeconds, GetAnimationLengthSeconds()); + static int SetSecondsIntoAnimation(T* p, lua_State *L) + { + p->SetSecondsIntoAnimation(FArg(1)); + COMMON_RETURN_SELF; + } + static int GetNumQuadStates(T* p, lua_State *L) + { + lua_pushnumber(L, p->GetNumQuadStates()); + return 1; + } + static size_t QuadStateIndex(T* p, lua_State *L, int pos) + { + int index= IArg(pos)-1; + if(index < 0 || static_cast(index) >= p->GetNumQuadStates()) + { + luaL_error(L, "Invalid state index %d.", index+1); + } + return static_cast(index); + } + static int AddQuadState(T* p, lua_State *L) + { + p->AddQuadState(IArg(1)-1); + COMMON_RETURN_SELF; + } + static int RemoveQuadState(T* p, lua_State *L) + { + p->RemoveQuadState(QuadStateIndex(p, L, 1)); + COMMON_RETURN_SELF; + } + static int GetQuadState(T* p, lua_State *L) + { + lua_pushnumber(L, p->GetQuadState(QuadStateIndex(p, L, 1))+1); + return 1; + } + static int SetQuadState(T* p, lua_State *L) + { + p->SetQuadState(QuadStateIndex(p, L, 1), IArg(2)-1); + COMMON_RETURN_SELF; + } + static int ForceStateUpdate(T* p, lua_State *L) + { + p->UpdateAnimationState(true); + COMMON_RETURN_SELF; + } + DEFINE_METHOD(GetDecodeMovie, _decode_movie); + static int SetDecodeMovie(T* p, lua_State *L) + { + p->_decode_movie= BArg(1); + COMMON_RETURN_SELF; + } + static int SetTexture( T* p, lua_State *L ) { RageTexture *Texture = Luna::check(L, 1); @@ -763,6 +1165,27 @@ public: ADD_METHOD( GetSpline ); ADD_METHOD( SetVertsFromSplines ); + ADD_METHOD(GetUseAnimationState); + ADD_METHOD(SetUseAnimationState); + ADD_METHOD(GetNumStates); + ADD_METHOD(GetNumQuadStates); + ADD_METHOD(AddState); + ADD_METHOD(RemoveState); + ADD_METHOD(GetState); + ADD_METHOD(SetState); + ADD_METHOD(GetStateData); + ADD_METHOD(SetStateData); + ADD_METHOD(SetStateProperties); + ADD_METHOD(SetAllStateDelays); + ADD_METHOD(SetSecondsIntoAnimation); + ADD_METHOD(AddQuadState); + ADD_METHOD(RemoveQuadState); + ADD_METHOD(GetQuadState); + ADD_METHOD(SetQuadState); + ADD_METHOD(ForceStateUpdate); + ADD_METHOD(GetDecodeMovie); + ADD_METHOD(SetDecodeMovie); + // Copy from RageTexture ADD_METHOD( SetTexture ); ADD_METHOD( GetTexture ); diff --git a/src/ActorMultiVertex.h b/src/ActorMultiVertex.h index 5b598cb310..2c4f949aec 100644 --- a/src/ActorMultiVertex.h +++ b/src/ActorMultiVertex.h @@ -38,7 +38,7 @@ public: struct AMV_TweenState { - AMV_TweenState(): _DrawMode(DrawMode_Invalid), FirstToDraw(0), + AMV_TweenState(): _DrawMode(DrawMode_Invalid), FirstToDraw(0), NumToDraw(-1), line_width(1.0f) {} static void MakeWeightedAverage(AMV_TweenState& average_out, const AMV_TweenState& ts1, const AMV_TweenState& ts2, float percent_between); @@ -49,6 +49,7 @@ public: int GetSafeNumToDraw( DrawMode dm, int num ) const; vector vertices; + vector quad_states; DrawMode _DrawMode; int FirstToDraw; @@ -67,6 +68,8 @@ public: } const AMV_TweenState& AMV_DestTweenState() const { return const_cast(this)->AMV_DestTweenState(); } + virtual void EnableAnimation(bool bEnable); + virtual void Update(float fDelta); virtual bool EarlyAbortDraw() const; virtual void DrawPrimitives(); virtual void DrawInternal( const AMV_TweenState *TS ); @@ -111,6 +114,40 @@ public: void SetVertsFromSplines(); CubicSplineN* GetSpline(size_t i); + struct State + { + RectF rect; + float delay; + }; + int GetNumStates() const { return _states.size(); } + void AddState(const State& new_state) { _states.push_back(new_state); } + void RemoveState(size_t i) + { ASSERT(i < _states.size()); _states.erase(_states.begin()+i); } + size_t GetState() { return _cur_state; } + State& GetStateData(size_t i) + { ASSERT(i < _states.size()); return _states[i]; } + void SetStateData(size_t i, const State& s) + { ASSERT(i < _states.size()); _states[i]= s; } + void SetStateProperties(const vector& new_states) + { _states= new_states; SetState(0); } + void SetState(size_t i); + void SetAllStateDelays(float delay); + float GetAnimationLengthSeconds() const; + void SetSecondsIntoAnimation(float seconds); + void UpdateAnimationState(bool force_update= false); + size_t GetNumQuadStates() const + { return AMV_DestTweenState().quad_states.size(); } + void AddQuadState(size_t s) + { AMV_DestTweenState().quad_states.push_back(s); } + void RemoveQuadState(size_t i) + { AMV_DestTweenState().quad_states.erase(AMV_DestTweenState().quad_states.begin()+i); } + size_t GetQuadState(size_t i) + { return AMV_DestTweenState().quad_states[i]; } + void SetQuadState(size_t i, size_t s) + { AMV_DestTweenState().quad_states[i]= s; } + bool _use_animation_state; + bool _decode_movie; + virtual void PushSelf( lua_State *L ); private: @@ -130,6 +167,11 @@ private: // Four splines for controlling vert positions, because quads drawmode // requires four. -Kyz vector _splines; + + bool _skip_next_update; + float _secs_into_state; + size_t _cur_state; + vector _states; }; /** diff --git a/src/Background.cpp b/src/Background.cpp index e70e86e6e9..d75abfbd49 100644 --- a/src/Background.cpp +++ b/src/Background.cpp @@ -765,10 +765,16 @@ void BackgroundImpl::Layer::UpdateCurBGChange( const Song *pSong, float fLastMus if( !change.m_sTransition.empty() ) { map::const_iterator lIter = mapNameToTransition.find( change.m_sTransition ); - ASSERT( lIter != mapNameToTransition.end() ); - const BackgroundTransition &bt = lIter->second; - m_pFadingBGA->RunCommandsOnLeaves( *bt.cmdLeaves ); - m_pFadingBGA->RunCommands( *bt.cmdRoot ); + if(lIter == mapNameToTransition.end()) + { + LuaHelpers::ReportScriptErrorFmt("'%s' is not the name of a BackgroundTransition file.", change.m_sTransition.c_str()); + } + else + { + const BackgroundTransition &bt = lIter->second; + m_pFadingBGA->RunCommandsOnLeaves( *bt.cmdLeaves ); + m_pFadingBGA->RunCommands( *bt.cmdRoot ); + } } } } diff --git a/src/CommandLineActions.cpp b/src/CommandLineActions.cpp index 91b20f7897..3aac6f784e 100644 --- a/src/CommandLineActions.cpp +++ b/src/CommandLineActions.cpp @@ -17,6 +17,7 @@ #include "Preference.h" #include "JsonUtil.h" #include "ScreenInstallOverlay.h" +#include "ver.h" // only used for Version() #if defined(_WINDOWS) @@ -69,7 +70,7 @@ static void LuaInformation() pNode->AppendAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); pNode->AppendAttr("xsi:schemaLocation", "http://www.stepmania.com Lua.xsd"); - pNode->AppendChild("Version", PRODUCT_ID_VER); + pNode->AppendChild("Version", string(PRODUCT_FAMILY) + product_version); pNode->AppendChild("Date", DateTime::GetNowDate().GetString()); XmlFileUtil::SaveToFile(pNode, "Lua.xml", "Lua.xsl"); @@ -77,12 +78,6 @@ static void LuaInformation() delete pNode; } -#if defined(HAVE_VERSION_INFO) -extern unsigned long version_num; -extern const char *const version_date; -extern const char *const version_time; -#endif - /** * @brief Print out version information. * @@ -92,7 +87,7 @@ extern const char *const version_time; static void Version() { #if defined(WIN32) - RString sProductID = ssprintf("%s", PRODUCT_ID_VER); + RString sProductID = ssprintf("%s", (string(PRODUCT_FAMILY) + product_version).c_str() ); RString sVersion = "(StepMania was built without HAVE_VERSION_INFO)"; #if defined(HAVE_VERSION_INFO) sVersion = ssprintf("build %lu\nCompile Date: %s @ %s", version_num, version_date, version_time); diff --git a/src/HighScore.cpp b/src/HighScore.cpp index e70bf6a701..cc9e17c0c6 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -17,10 +17,10 @@ struct HighScoreImpl { RString sName; // name that shows in the machine's ranking screen Grade grade; - int iScore; + unsigned int iScore; float fPercentDP; float fSurviveSeconds; - int iMaxCombo; // maximum combo obtained [SM5 alpha 1a+] + unsigned int iMaxCombo; // maximum combo obtained [SM5 alpha 1a+] StageAward stageAward; // stage award [SM5 alpha 1a+] PeakComboAward peakComboAward; // peak combo award [SM5 alpha 1a+] RString sModifiers; @@ -191,8 +191,8 @@ bool HighScore::IsEmpty() const RString HighScore::GetName() const { return m_Impl->sName; } Grade HighScore::GetGrade() const { return m_Impl->grade; } -int HighScore::GetScore() const { return m_Impl->iScore; } -int HighScore::GetMaxCombo() const { return m_Impl->iMaxCombo; } +unsigned int HighScore::GetScore() const { return m_Impl->iScore; } +unsigned int HighScore::GetMaxCombo() const { return m_Impl->iMaxCombo; } StageAward HighScore::GetStageAward() const { return m_Impl->stageAward; } PeakComboAward HighScore::GetPeakComboAward() const { return m_Impl->peakComboAward; } float HighScore::GetPercentDP() const { return m_Impl->fPercentDP; } @@ -211,8 +211,8 @@ bool HighScore::GetDisqualified() const { return m_Impl->bDisqualified; } void HighScore::SetName( const RString &sName ) { m_Impl->sName = sName; } void HighScore::SetGrade( Grade g ) { m_Impl->grade = g; } -void HighScore::SetScore( int iScore ) { m_Impl->iScore = iScore; } -void HighScore::SetMaxCombo( int i ) { m_Impl->iMaxCombo = i; } +void HighScore::SetScore( unsigned int iScore ) { m_Impl->iScore = iScore; } +void HighScore::SetMaxCombo( unsigned int i ) { m_Impl->iMaxCombo = i; } void HighScore::SetStageAward( StageAward a ) { m_Impl->stageAward = a; } void HighScore::SetPeakComboAward( PeakComboAward a ) { m_Impl->peakComboAward = a; } void HighScore::SetPercentDP( float f ) { m_Impl->fPercentDP = f; } diff --git a/src/HighScore.h b/src/HighScore.h index c3e8ed86bc..568ad191ea 100644 --- a/src/HighScore.h +++ b/src/HighScore.h @@ -30,7 +30,7 @@ struct HighScore /** * @brief Retrieve the score earned. * @return the score. */ - int GetScore() const; + unsigned int GetScore() const; /** * @brief Determine if any judgments were tallied during this run. * @return true if no judgments were recorded, false otherwise. */ @@ -41,7 +41,7 @@ struct HighScore * @return the number of seconds left. */ float GetSurviveSeconds() const; float GetSurvivalSeconds() const; - int GetMaxCombo() const; + unsigned int GetMaxCombo() const; StageAward GetStageAward() const; PeakComboAward GetPeakComboAward() const; /** @@ -66,10 +66,10 @@ struct HighScore * @param sName the name of the Player. */ void SetName( const RString &sName ); void SetGrade( Grade g ); - void SetScore( int iScore ); + void SetScore( unsigned int iScore ); void SetPercentDP( float f ); void SetAliveSeconds( float f ); - void SetMaxCombo( int i ); + void SetMaxCombo( unsigned int i ); void SetStageAward( StageAward a ); void SetPeakComboAward( PeakComboAward a ); void SetModifiers( RString s ); diff --git a/src/Inventory.cpp b/src/Inventory.cpp index 5124d15c33..aabb821bad 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -25,7 +25,7 @@ ThemeMetric ITEM_USE_RATE_SECONDS("Inventory","ItemUseRateSeconds"); struct Item { AttackLevel level; - int iCombo; + unsigned int iCombo; RString sModifier; }; static vector g_Items; @@ -100,9 +100,9 @@ void Inventory::Update( float fDelta ) // check to see if they deserve a new item if( STATSMAN->m_CurStageStats.m_player[pn].m_iCurCombo != m_iLastSeenCombo ) { - int iOldCombo = m_iLastSeenCombo; + unsigned int iOldCombo = m_iLastSeenCombo; m_iLastSeenCombo = STATSMAN->m_CurStageStats.m_player[pn].m_iCurCombo; - int iNewCombo = m_iLastSeenCombo; + unsigned int iNewCombo = m_iLastSeenCombo; #define CROSSED(i) (iOldCombo=i) #define BROKE_ABOVE(i) (iNewCombo=i) diff --git a/src/Inventory.h b/src/Inventory.h index 5ad36dfe71..93712c3e17 100644 --- a/src/Inventory.h +++ b/src/Inventory.h @@ -28,7 +28,7 @@ protected: void AwardItem( int iItemIndex ); PlayerState* m_pPlayerState; - int m_iLastSeenCombo; + unsigned int m_iLastSeenCombo; /** @brief a sound played when an item has been acquired. */ RageSound m_soundAcquireItem; diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index 3e703474fb..3d2f12e50b 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -12,6 +12,7 @@ #include "RageLog.h" #include "RageTypes.h" #include "MessageManager.h" +#include "ver.h" #include // conversion for lua functions. #include @@ -81,6 +82,7 @@ namespace LuaHelpers template<> void Push( lua_State *L, const bool &Object ) { lua_pushboolean( L, Object ); } template<> void Push( lua_State *L, const float &Object ) { lua_pushnumber( L, Object ); } template<> void Push( lua_State *L, const int &Object ) { lua_pushinteger( L, Object ); } + template<> void Push( lua_State *L, const unsigned int &Object ) { lua_pushnumber( L, double(Object) ); } template<> void Push( lua_State *L, const RString &Object ) { lua_pushlstring( L, Object.data(), Object.size() ); } template<> bool FromStack( Lua *L, bool &Object, int iOffset ) { Object = !!lua_toboolean( L, iOffset ); return true; } @@ -1039,7 +1041,7 @@ void LuaHelpers::PushValueFunc( lua_State *L, int iArgs ) #include "ProductInfo.h" LuaFunction( ProductFamily, (RString) PRODUCT_FAMILY ); -LuaFunction( ProductVersion, (RString) PRODUCT_VER ); +LuaFunction( ProductVersion, (RString) product_version ); LuaFunction( ProductID, (RString) PRODUCT_ID ); extern const char *const version_date; diff --git a/src/Makefile.am b/src/Makefile.am index bda964f867..c56731c03d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,6 @@ AM_CFLAGS = noinst_LIBRARIES = EXTRA_DIST = - AM_CXXFLAGS += -fno-exceptions # Relax inlining; the default of 600 takes way too long to compile and @@ -28,31 +27,31 @@ AM_CXXFLAGS += -finline-limit=300 AM_CXXFLAGS += $(GL_CFLAGS) -.PHONY: increment_version gitversion +.PHONY: update_version -increment_version: - if test -e ver.h; then \ - build=`sed -rs 's/.*version_num = ([[:digit:]]+);/\1/;q' ver.cpp`; \ +update_version: + if test -e ver.cpp; then \ + build=`sed -rs 's/.*version_num = ([[:digit:]]+);/\1/;2q;d' ver.cpp`; \ build=`expr $$build + 1`; \ else \ build=0; \ fi; \ - echo "extern const unsigned long version_num = $$build;" > ver.cpp; \ - echo "extern const char *const version_time = \"`date +"%X %Z (UTC%:z)"`\";" >> ver.cpp; - echo "extern const char *const version_date = \"`date +"%Y%m%d"`\";" >> ver.cpp; - -ver.cpp: increment_version - -gitversion: - rm -f gitversion.h - touch gitversion.h + echo "#include \"ver.h\"" > ver.cpp; \ + echo "const unsigned long version_num = $$build;" >> ver.cpp +# Header inclusion necessary to get linker symbols right + echo "const char *const version_time = \"`date +"%X %Z (UTC%:z)"`\";" >> ver.cpp + echo "const char *const version_date = \"`date +"%Y%m%d"`\";" >> ver.cpp if git rev-parse --short HEAD; then \ - echo "#define PRODUCT_VER_BARE 5.0-git-`git rev-parse --short HEAD`" > gitversion.h; \ + echo "const char *const product_version = \"5.0-git-`git rev-parse --short HEAD`\";" >> ver.cpp; \ + else \ + echo "const char *const product_version = \"5.0-UNKNOWN\";" >> ver.cpp; \ fi -gitversion.h: gitversion - -BUILT_SOURCES = gitversion.h ver.cpp +ver.cpp: update_version +# make doesn't recognize a file it updated during the current invocation +# (in this case ver.cpp) as being updated. So remake and delete stepmania-ver.o +# every time. +.INTERMEDIATE: stepmania-ver.o PNG = \ ../extern/libpng/include/png.c ../extern/libpng/include/.png.h \ @@ -486,8 +485,13 @@ ScoreDisplayNormal.cpp ScoreDisplayNormal.h ScoreDisplayOni.cpp ScoreDisplayOni. ScoreDisplayPercentage.cpp ScoreDisplayPercentage.h ScoreDisplayRave.cpp ScoreDisplayRave.h \ SongPosition.cpp SongPosition.h -PCRE = ../extern/pcre/get.c ../extern/pcre/internal.h ../extern/pcre/maketables.c ../extern/pcre/pcre.c ../extern/pcre/pcre.h ../extern/pcre/study.c +Rage = +all_test_SOURCES = +if !USE_SYSTEM_PCRE +Rage += ../extern/pcre/get.c ../extern/pcre/internal.h ../extern/pcre/maketables.c ../extern/pcre/pcre.c ../extern/pcre/pcre.h ../extern/pcre/study.c +all_test_SOURCES += ../extern/pcre/get.c ../extern/pcre/internal.h ../extern/pcre/maketables.c ../extern/pcre/pcre.c ../extern/pcre/pcre.h ../extern/pcre/study.c EXTRA_DIST += ../extern/pcre/chartables.c +endif Lua = ../extern/lua-5.1/src/lapi.c ../extern/lua-5.1/src/lauxlib.c ../extern/lua-5.1/src/lbaselib.c ../extern/lua-5.1/src/lcode.c ../extern/lua-5.1/src/ldblib.c \ ../extern/lua-5.1/src/ldebug.c ../extern/lua-5.1/src/ldo.c ../extern/lua-5.1/src/ldump.c ../extern/lua-5.1/src/lfunc.c ../extern/lua-5.1/src/lgc.c ../extern/lua-5.1/src/linit.c \ @@ -523,7 +527,7 @@ RageFileDriverReadAhead.cpp RageFileDriverReadAhead.h \ RageFileDriverSlice.cpp RageFileDriverSlice.h \ RageFileDriverTimeout.cpp RageFileDriverTimeout.h -Rage = $(PCRE) $(Lua) $(jsoncpp) $(RageFile) $(RageSoundFileReaders) \ +Rage += $(Lua) $(jsoncpp) $(RageFile) $(RageSoundFileReaders) \ CubicSpline.cpp CubicSpline.h \ RageBitmapTexture.cpp RageBitmapTexture.h \ RageDisplay.cpp RageDisplay.h \ @@ -745,7 +749,7 @@ main_LDADD = \ $(GL_LIBS) \ libtomcrypt.a libtommath.a -nodist_stepmania_SOURCES = ver.cpp gitversion.h +nodist_stepmania_SOURCES = ver.cpp stepmania_CPPFLAGS = $(main_CPPFLAGS) stepmania_SOURCES = $(main_SOURCES) @@ -769,9 +773,8 @@ if HAVE_GTK GtkModule_so_SOURCES = arch/LoadingWindow/LoadingWindow_GtkModule.cpp endif -all_test_SOURCES = \ +all_test_SOURCES += \ $(ArchUtils) \ - $(PCRE) \ $(RageFile) \ $(Lua) \ $(ArchHooks) \ diff --git a/src/MusicWheel.cpp b/src/MusicWheel.cpp index 82d87c33e0..c70537a21b 100644 --- a/src/MusicWheel.cpp +++ b/src/MusicWheel.cpp @@ -87,6 +87,7 @@ void MusicWheel::Load( RString sType ) SHOW_EASY_FLAG .Load(sType,"UseEasyMarkerFlag"); USE_SECTIONS_WITH_PREFERRED_GROUP .Load(sType,"UseSectionsWithPreferredGroup"); HIDE_INACTIVE_SECTIONS .Load(sType,"OnlyShowActiveSection"); + HIDE_ACTIVE_SECTION_TITLE .Load(sType,"HideActiveSectionTitle"); REMIND_WHEEL_POSITIONS .Load(sType,"RemindWheelPositions"); vector vsModeChoiceNames; split( MODE_MENU_CHOICE_NAMES, ",", vsModeChoiceNames ); @@ -677,10 +678,7 @@ void MusicWheel::BuildWheelItemDatas( vector &arrayWheelIt // todo: preferred sort section color handling? -aj RageColor colorSection = (so==SORT_GROUP) ? SONGMAN->GetSongGroupColor(pSong->m_sGroupName) : SECTION_COLORS.GetValue(iSectionColorIndex); iSectionColorIndex = (iSectionColorIndex+1) % NUM_SECTION_COLORS; - // In certain situations (e.g. simulating Pump it Up), themes may - // want to only show one group at a time. - if( !HIDE_INACTIVE_SECTIONS ) - arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, NULL, sThisSection, NULL, colorSection, iSectionCount) ); + arrayWheelItemDatas.push_back( new MusicWheelItemData(WheelItemDataType_Section, NULL, sThisSection, NULL, colorSection, iSectionCount) ); sLastSection = sThisSection; } } @@ -1361,10 +1359,22 @@ void MusicWheel::SetOpenSection( RString group ) for( unsigned i = 0; i < from.size(); ++i ) { MusicWheelItemData &d = *from[i]; + + // Hide songs/courses which are not in the active section if( (d.m_Type == WheelItemDataType_Song || d.m_Type == WheelItemDataType_Course) && !d.m_sText.empty() && d.m_sText != group ) continue; + // In certain situations (e.g. simulating Pump it Up or IIDX), + // themes may want to hide inactive section headings as well. + if( HIDE_INACTIVE_SECTIONS && d.m_Type == WheelItemDataType_Section && group != "" ) { + // Based on the HideActiveSectionTitle metric, we either + // hide all section titles, or only those which are not + // currently open. + if ( HIDE_ACTIVE_SECTION_TITLE || d.m_sText != group ) + continue; + } + // If AUTO_SET_STYLE, hide courses that prefer a style that isn't available. if( d.m_Type == WheelItemDataType_Course && CommonMetrics::AUTO_SET_STYLE ) { diff --git a/src/MusicWheel.h b/src/MusicWheel.h index d0fb3c107f..83c20aa29f 100644 --- a/src/MusicWheel.h +++ b/src/MusicWheel.h @@ -90,6 +90,7 @@ protected: // sm-ssc additions: ThemeMetric USE_SECTIONS_WITH_PREFERRED_GROUP; ThemeMetric HIDE_INACTIVE_SECTIONS; + ThemeMetric HIDE_ACTIVE_SECTION_TITLE; ThemeMetric REMIND_WHEEL_POSITIONS; ThemeMetric ROULETTE_COLOR; ThemeMetric RANDOM_COLOR; diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 7fed108439..047eda4332 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -6,9 +6,10 @@ NetworkSyncManager *NSMAN; -// Aldo: used by GetCurrentSMVersion() +// Aldo: version_num used by GetCurrentSMVersion() +// XXX: That's probably not what you want... --root #if defined(HAVE_VERSION_INFO) -extern unsigned long version_num; +#include "ver.h" #endif #if defined(WITHOUT_NETWORKING) @@ -165,7 +166,7 @@ void NetworkSyncManager::PostStartUp( const RString& ServerIP ) m_packet.Write1( NETPROTOCOLVERSION ); - m_packet.WriteNT( RString(PRODUCT_ID_VER) ); + m_packet.WriteNT( RString( string(PRODUCT_FAMILY) + product_version ) ); /* Block until response is received. * Move mode to blocking in order to give CPU back to the system, diff --git a/src/NoteDataUtil.cpp b/src/NoteDataUtil.cpp index 2017f704dd..3d7a54ea0f 100644 --- a/src/NoteDataUtil.cpp +++ b/src/NoteDataUtil.cpp @@ -556,7 +556,8 @@ void NoteDataUtil::LoadTransformedSlidingWindow( const NoteData &in, NoteData &o { int iOldTrack = t; int iNewTrack = (iOldTrack + iCurTrackOffset) % iNewNumTracks; - const TapNote &tn = in.GetTapNote( iOldTrack, r ); + TapNote tn = in.GetTapNote( iOldTrack, r ); + tn.pn= PLAYER_INVALID; out.SetTapNote( iNewTrack, r, tn ); } } @@ -622,9 +623,10 @@ void NoteDataUtil::LoadOverlapped( const NoteData &in, NoteData &out, int iNewNu { for( int iTrackFrom = 0; iTrackFrom < in.GetNumTracks(); ++iTrackFrom ) { - const TapNote &tnFrom = in.GetTapNote( iTrackFrom, row ); + TapNote tnFrom = in.GetTapNote( iTrackFrom, row ); if( tnFrom.type == TapNoteType_Empty || tnFrom.type == TapNoteType_AutoKeysound ) continue; + tnFrom.pn= PLAYER_INVALID; // If this is a hold note, find the end. int iEndIndex = row; diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 1d7672af4d..33a3b04b94 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -137,7 +137,10 @@ void NoteField::CacheAllUsedNoteSkins() GAMESTATE->GetAllUsedNoteSkins( asSkinsLower ); asSkinsLower.push_back( m_pPlayerState->m_PlayerOptions.GetStage().m_sNoteSkin ); FOREACH( RString, asSkinsLower, s ) + { + NOTESKIN->ValidateNoteSkinName(*s); s->MakeLower(); + } for( unsigned i=0; i < asSkinsLower.size(); ++i ) CacheNoteSkin( asSkinsLower[i] ); @@ -155,6 +158,7 @@ void NoteField::CacheAllUsedNoteSkins() UncacheNoteSkin( *s ); RString sCurrentNoteSkinLower = m_pPlayerState->m_PlayerOptions.GetCurrent().m_sNoteSkin; + NOTESKIN->ValidateNoteSkinName(sCurrentNoteSkinLower); sCurrentNoteSkinLower.MakeLower(); map::iterator it = m_NoteDisplays.find( sCurrentNoteSkinLower ); @@ -165,6 +169,7 @@ void NoteField::CacheAllUsedNoteSkins() FOREACH_EnabledPlayer( pn ) { RString sNoteSkinLower = GAMESTATE->m_pPlayerState[pn]->m_PlayerOptions.GetCurrent().m_sNoteSkin; + NOTESKIN->ValidateNoteSkinName(sNoteSkinLower); sNoteSkinLower.MakeLower(); it = m_NoteDisplays.find( sNoteSkinLower ); ASSERT_M( it != m_NoteDisplays.end(), sNoteSkinLower ); diff --git a/src/NoteSkinManager.cpp b/src/NoteSkinManager.cpp index 9d3dd0d7f7..02948b2ddd 100644 --- a/src/NoteSkinManager.cpp +++ b/src/NoteSkinManager.cpp @@ -246,6 +246,15 @@ RString NoteSkinManager::GetDefaultNoteSkinName() return name; } +void NoteSkinManager::ValidateNoteSkinName(RString& name) +{ + if(name.empty() || !DoesNoteSkinExist(name)) + { + LuaHelpers::ReportScriptError("Someone set a noteskin that doesn't exist. Good job."); + name= GetDefaultNoteSkinName(); + } +} + void NoteSkinManager::GetAllNoteSkinNamesForGame( const Game *pGame, vector &AddTo ) { if( pGame == m_pCurGame ) diff --git a/src/NoteSkinManager.h b/src/NoteSkinManager.h index f5ad944020..db06b25719 100644 --- a/src/NoteSkinManager.h +++ b/src/NoteSkinManager.h @@ -25,9 +25,11 @@ public: bool DoNoteSkinsExistForGame( const Game *pGame ); RString GetDefaultNoteSkinName(); // looks up current const Game* in GAMESTATE + void ValidateNoteSkinName(RString& name); + void SetCurrentNoteSkin( const RString &sNoteSkin ) { m_sCurrentNoteSkin = sNoteSkin; } const RString &GetCurrentNoteSkin() { return m_sCurrentNoteSkin; } - void SetPlayerNumber( PlayerNumber pn ) { m_PlayerNumber = pn; } + void SetPlayerNumber( PlayerNumber pn ) { m_PlayerNumber = pn; } void SetGameController( GameController gc ) { m_GameController = gc; } RString GetPath( const RString &sButtonName, const RString &sElement ); bool PushActorTemplate( Lua *L, const RString &sButton, const RString &sElement, bool bSpriteOnly ); diff --git a/src/Player.cpp b/src/Player.cpp index dfa4bb3ef8..e23d707d9b 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -370,8 +370,9 @@ void Player::Init( m_pPrimaryScoreKeeper = pPrimaryScoreKeeper; m_pSecondaryScoreKeeper = pSecondaryScoreKeeper; - m_iLastSeenCombo = -1; - + m_iLastSeenCombo = 0; + m_bSeenComboYet = false; + // set initial life if( m_pLifeMeter && m_pPlayerStageStats ) { @@ -763,10 +764,10 @@ void Player::Load() m_pIterUnjudgedMineRows = new NoteData::all_tracks_iterator( m_NoteData.GetTapNoteRangeAllTracks(iNoteRow, MAX_NOTE_ROW ) ); } -void Player::SendComboMessages( int iOldCombo, int iOldMissCombo ) +void Player::SendComboMessages( unsigned int iOldCombo, unsigned int iOldMissCombo ) { - const int iCurCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; - if( iOldCombo > COMBO_STOPPED_AT && iCurCombo < COMBO_STOPPED_AT ) + const unsigned int iCurCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; + if( iOldCombo > (unsigned int)COMBO_STOPPED_AT && iCurCombo < (unsigned int)COMBO_STOPPED_AT ) { SCREENMAN->PostMessageToTopScreen( SM_ComboStopped, 0 ); } @@ -1411,7 +1412,7 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vectorTrace("initiated note and didn't let go"); fLife = 1; // xxx: should be MAX_HOLD_LIFE instead? -aj hns = HNS_Held; - bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD; + bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo>(unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD; if( m_pNoteField ) { FOREACH( TrackRowTapNote, vTN, trtn ) @@ -1463,19 +1464,7 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vectorm_iCurCombo : 0; - const int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; - - if( m_pPlayerStageStats ) - { - m_pPlayerStageStats->m_iCurCombo = 0; - m_pPlayerStageStats->m_iCurMissCombo++; - SetCombo( m_pPlayerStageStats->m_iCurCombo, m_pPlayerStageStats->m_iCurMissCombo ); - } - - SendComboMessages( iOldCombo, iOldMissCombo ); - } + IncrementMissCombo(); if( hns != HNS_None ) { @@ -1919,8 +1908,8 @@ void Player::DoTapScoreNone() Message msg( "ScoreNone" ); MESSAGEMAN->Broadcast( msg ); - const int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; - const int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; + const unsigned int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; + const unsigned int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; /* The only real way to tell if a mine has been scored is if it has disappeared * but this only works for hit mines so update the scores for avoided mines here. */ @@ -2106,21 +2095,9 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b if( ROLL_BODY_INCREMENTS_COMBO && m_pPlayerState->m_PlayerController != PC_AUTOPLAY ) { - // increment combo - const int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; - const int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; - - if( m_pPlayerStageStats ) - { - m_pPlayerStageStats->m_iCurCombo++; - m_pPlayerStageStats->m_iCurMissCombo = 0; - } - - SendComboMessages( iOldCombo, iOldMissCombo ); - if( m_pPlayerStageStats ) - SetCombo( m_pPlayerStageStats->m_iCurCombo, m_pPlayerStageStats->m_iCurMissCombo ); - - bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD; + IncrementCombo(); + + bool bBright = m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo>(unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD; if( m_pNoteField ) m_pNoteField->DidHoldNote( col, HNS_Held, bBright ); } @@ -2582,7 +2559,7 @@ void Player::StepStrumHopo( int col, int row, const RageTimer &tm, bool bHeld, b const bool bBlind = (m_pPlayerState->m_PlayerOptions.GetCurrent().m_fBlind != 0); // XXX: This is the wrong combo for shared players. // STATSMAN->m_CurStageStats.m_Player[pn] might work, but could be wrong. - const bool bBright = ( m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo > int(BRIGHT_GHOST_COMBO_THRESHOLD) ) || bBlind; + const bool bBright = ( m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo > (unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD ) || bBlind; if( m_pNoteField ) m_pNoteField->DidTapNote( col, bBlind? TNS_W1:score, bBright ); if( score >= m_pPlayerState->m_PlayerOptions.GetCurrent().m_MinTNSToHideNotes || bBlind ) @@ -2921,7 +2898,7 @@ void Player::FlashGhostRow( int iRow ) { TapNoteScore lastTNS = NoteDataWithScoring::LastTapNoteWithResult( m_NoteData, iRow ).result.tns; const bool bBlind = (m_pPlayerState->m_PlayerOptions.GetCurrent().m_fBlind != 0); - const bool bBright = ( m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo > int(BRIGHT_GHOST_COMBO_THRESHOLD) ) || bBlind; + const bool bBright = ( m_pPlayerStageStats && m_pPlayerStageStats->m_iCurCombo > (unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD ) || bBlind; for( int iTrack = 0; iTrack < m_NoteData.GetNumTracks(); ++iTrack ) { @@ -3124,8 +3101,8 @@ void Player::HandleTapRowScore( unsigned row ) return; TapNoteScore scoreOfLastTap = NoteDataWithScoring::LastTapNoteWithResult(m_NoteData, row).result.tns; - const int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; - const int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; + const unsigned int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; + const unsigned int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; if( scoreOfLastTap == TNS_Miss ) m_LastTapNoteScore = TNS_Miss; @@ -3150,8 +3127,8 @@ void Player::HandleTapRowScore( unsigned row ) if( m_pSecondaryScoreKeeper != NULL ) m_pSecondaryScoreKeeper->HandleTapRowScore( m_NoteData, row ); - const int iCurCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; - const int iCurMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; + const unsigned int iCurCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; + const unsigned int iCurMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; SendComboMessages( iOldCombo, iOldMissCombo ); @@ -3231,8 +3208,8 @@ void Player::HandleHoldCheckpoint(int iRow, if( bNoCheating && m_pPlayerState->m_PlayerController == PC_AUTOPLAY ) return; - const int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; - const int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; + const unsigned int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; + const unsigned int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; if( m_pPrimaryScoreKeeper ) m_pPrimaryScoreKeeper->HandleHoldCheckpointScore(m_NoteData, @@ -3253,7 +3230,7 @@ void Player::HandleHoldCheckpoint(int iRow, FOREACH_CONST( int, viColsWithHold, i ) { bool bBright = m_pPlayerStageStats - && m_pPlayerStageStats->m_iCurCombo>(int)BRIGHT_GHOST_COMBO_THRESHOLD; + && m_pPlayerStageStats->m_iCurCombo>(unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD; if( m_pNoteField ) m_pNoteField->DidHoldNote( *i, HNS_Held, bBright ); } @@ -3422,30 +3399,35 @@ void Player::SetHoldJudgment( TapNote &tn, int iTrack ) } } -void Player::SetCombo( int iCombo, int iMisses ) +void Player::SetCombo( unsigned int iCombo, unsigned int iMisses ) { - if( m_iLastSeenCombo == -1 ) // first update, don't set bIsMilestone=true + if( !m_bSeenComboYet ) // first update, don't set bIsMilestone=true + { + m_bSeenComboYet = true; m_iLastSeenCombo = iCombo; - + } + bool b25Milestone = false; bool b50Milestone = false; bool b100Milestone = false; bool b250Milestone = false; bool b1000Milestone = false; - for( int i=m_iLastSeenCombo+1; i<=iCombo; i++ ) + +#define MILESTONE_CHECK(amount) ((iCombo / amount) > (m_iLastSeenCombo / amount)) + if(m_iLastSeenCombo < 600) { - if( i < 600 ) - { - b25Milestone |= ((i % 25) == 0); - b50Milestone |= ((i % 50) == 0); - b100Milestone |= ((i % 100) == 0); - b250Milestone |= ((i % 250) == 0); - } - else - { - b1000Milestone |= ((i % 200) == 0); - } + b25Milestone= MILESTONE_CHECK(25); + b50Milestone= MILESTONE_CHECK(50); + b100Milestone= MILESTONE_CHECK(100); + b250Milestone= MILESTONE_CHECK(250); + b1000Milestone= MILESTONE_CHECK(1000); } + else + { + b1000Milestone= MILESTONE_CHECK(1000); + } +#undef MILESTONE_CHECK + m_iLastSeenCombo = iCombo; if( b25Milestone ) @@ -3504,6 +3486,29 @@ void Player::SetCombo( int iCombo, int iMisses ) } } +void Player::IncrementComboOrMissCombo(bool bComboOrMissCombo) +{ + const unsigned int iOldCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurCombo : 0; + const unsigned int iOldMissCombo = m_pPlayerStageStats ? m_pPlayerStageStats->m_iCurMissCombo : 0; + + if( m_pPlayerStageStats ) + { + if( bComboOrMissCombo ) + { + m_pPlayerStageStats->m_iCurCombo++; + m_pPlayerStageStats->m_iCurMissCombo = 0; + } + else + { + m_pPlayerStageStats->m_iCurCombo = 0; + m_pPlayerStageStats->m_iCurMissCombo++; + } + SetCombo( m_pPlayerStageStats->m_iCurCombo, m_pPlayerStageStats->m_iCurMissCombo ); + } + + SendComboMessages( iOldCombo, iOldMissCombo ); +} + RString Player::ApplyRandomAttack() { if( GAMESTATE->m_RandomAttacks.size() < 1 ) diff --git a/src/Player.h b/src/Player.h index 9d75b98235..acdb82bed2 100644 --- a/src/Player.h +++ b/src/Player.h @@ -128,14 +128,17 @@ protected: void HandleHoldCheckpoint( int iRow, int iNumHoldsHeldThisRow, int iNumHoldsMissedThisRow, const vector &viColsWithHold ); void DrawTapJudgments(); void DrawHoldJudgments(); - void SendComboMessages( int iOldCombo, int iOldMissCombo ); + void SendComboMessages( unsigned int iOldCombo, unsigned int iOldMissCombo ); void PlayKeysound( const TapNote &tn, TapNoteScore score ); void SetMineJudgment( TapNoteScore tns , int iTrack ); void SetJudgment( int iRow, int iFirstTrack, const TapNote &tn ) { SetJudgment( iRow, iFirstTrack, tn, tn.result.tns, tn.result.fTapNoteOffset ); } void SetJudgment( int iRow, int iFirstTrack, const TapNote &tn, TapNoteScore tns, float fTapNoteOffset ); // -1 if no track as in TNS_Miss void SetHoldJudgment( TapNote &tn, int iTrack ); - void SetCombo( int iCombo, int iMisses ); + void SetCombo( unsigned int iCombo, unsigned int iMisses ); + void IncrementComboOrMissCombo( bool bComboOrMissCombo ); + void IncrementCombo() { IncrementComboOrMissCombo(true); }; + void IncrementMissCombo() { IncrementComboOrMissCombo(false); }; void ChangeLife( TapNoteScore tns ); void ChangeLife( HoldNoteScore hns, TapNoteScore tns ); @@ -194,7 +197,8 @@ protected: NoteData::all_tracks_iterator *m_pIterUncrossedRows; NoteData::all_tracks_iterator *m_pIterUnjudgedRows; NoteData::all_tracks_iterator *m_pIterUnjudgedMineRows; - int m_iLastSeenCombo; + unsigned int m_iLastSeenCombo; + bool m_bSeenComboYet; JudgedRows *m_pJudgedRows; RageSound m_soundMine; diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 8efefb4f0d..94a4991c13 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -811,7 +811,11 @@ PlayerOptions& PlayerOptions::operator=(PlayerOptions const& other) CPY_SPEED(fPlayerAutoPlay); CPY_SPEED(fPerspectiveTilt); CPY_SPEED(fSkew); - CPY(m_sNoteSkin); + if(!other.m_sNoteSkin.empty() && + NOTESKIN->DoesNoteSkinExist(other.m_sNoteSkin)) + { + CPY(m_sNoteSkin); + } for( int i = 0; i < PlayerOptions::NUM_ACCELS; ++i ) { CPY_SPEED(fAccels[i]); diff --git a/src/PlayerStageStats.h b/src/PlayerStageStats.h index 6c95c49aaf..3098fba4d2 100644 --- a/src/PlayerStageStats.h +++ b/src/PlayerStageStats.h @@ -65,18 +65,18 @@ public: int m_iTapNoteScores[NUM_TapNoteScore]; int m_iHoldNoteScores[NUM_HoldNoteScore]; /** @brief The Player's current combo. */ - int m_iCurCombo; + unsigned int m_iCurCombo; /** @brief The Player's max combo. */ - int m_iMaxCombo; + unsigned int m_iMaxCombo; /** @brief The Player's current miss combo. */ - int m_iCurMissCombo; + unsigned int m_iCurMissCombo; int m_iCurScoreMultiplier; /** @brief The player's current score. */ - int m_iScore; + unsigned int m_iScore; /** @brief The theoretically highest score the Player could have at this point. */ - int m_iCurMaxScore; + unsigned int m_iCurMaxScore; /** @brief The maximum score the Player can get this goaround. */ - int m_iMaxScore; + unsigned int m_iMaxScore; /** * @brief The possible RadarValues for a song. diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index 9931f3a027..a17b113221 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -11,6 +11,10 @@ #include "RageLog.h" #include "SpecialFiles.h" +#if !defined(WITHOUT_NETWORKING) && defined(HAVE_VERSION_INFO) +#include "ver.h" +#endif + //DEFAULTS_INI_PATH = "Data/Defaults.ini"; // these can be overridden //PREFERENCES_INI_PATH // overlay on Defaults.ini, contains the user's choices //STATIC_INI_PATH = "Data/Static.ini"; // overlay on the 2 above, can't be overridden @@ -143,10 +147,6 @@ bool g_bAutoRestart = false; # define TRUE_IF_DEBUG false #endif -#if !defined(WITHOUT_NETWORKING) && defined(HAVE_VERSION_INFO) -extern unsigned long version_num; -#endif - void ValidateDisplayAspectRatio( float &val ) { if( val < 0 ) @@ -258,6 +258,7 @@ PrefsManager::PrefsManager() : m_fDebounceCoinInputTime ( "DebounceCoinInputTime", 0 ), m_fPadStickSeconds ( "PadStickSeconds", 0 ), + m_EditRecordModeLeadIn("EditRecordModeLeadIn", 1.0f), m_bForceMipMaps ( "ForceMipMaps", false ), m_bTrilinearFiltering ( "TrilinearFiltering", false ), m_bAnisotropicFiltering ( "AnisotropicFiltering", false ), diff --git a/src/PrefsManager.h b/src/PrefsManager.h index c95692a1e6..4caee949fc 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -253,6 +253,9 @@ public: // after pressed. Preference m_fPadStickSeconds; + // Lead in time before recording starts in edit mode. + Preference m_EditRecordModeLeadIn; + // Useful for non 4:3 displays and resolutions < 640x480 where texels don't // map directly to pixels. Preference m_bForceMipMaps; diff --git a/src/ProductInfo.h b/src/ProductInfo.h index a09e70ccfc..4512ee66da 100644 --- a/src/ProductInfo.h +++ b/src/ProductInfo.h @@ -3,12 +3,6 @@ #ifndef PRODUCT_INFO_H #define PRODUCT_INFO_H -// XXX: VC doesn't generate this yet. Hack around it for now -#include "config.h" -#ifdef USE_GITVERSION -#include "gitversion.h" -#endif - /** * @brief A friendly string to refer to the product in crash dialogs, etc. * @@ -22,29 +16,7 @@ * As an example, use "StepMania4" here, not "StepMania". * It would cause a conflict with older versions such as StepMania 3.X. */ -#define PRODUCT_ID_BARE StepMania 5.0 - -/** - * @brief Version info displayed to the user. - * - * These are the 'official' version designations: - *
    - *
  • "v5.0 alpha #": Alpha versions (bug squashing, polishing until we reach beta)
  • - *
  • "v5.0 beta #": Beta versions (bug squashing, _focus_ is on high priority bugs)
  • - *
  • "v5.0 rc#": Release Candidates (if there are no problems, move on to final)
  • - *
  • "v5.0.0": Final Releases
  • - *
- */ -#ifndef PRODUCT_VER_BARE -#define PRODUCT_VER_BARE 5.0-UNKNOWN -#endif - -/** - * @brief A unique ID for a build of an application. - * - * This is used in crash reports and in the network code's version handling. - */ -#define PRODUCT_ID_VER_BARE PRODUCT_FAMILY_BARE PRODUCT_VER_BARE +#define PRODUCT_ID_BARE StepMania 5 // These cannot be #undef'd so make them unlikely to conflict with anything #define PRODUCT_STRINGIFY(x) #x @@ -52,8 +24,6 @@ #define PRODUCT_FAMILY PRODUCT_XSTRINGIFY(PRODUCT_FAMILY_BARE) #define PRODUCT_ID PRODUCT_XSTRINGIFY(PRODUCT_ID_BARE) -#define PRODUCT_VER PRODUCT_XSTRINGIFY(PRODUCT_VER_BARE) -#define PRODUCT_ID_VER PRODUCT_XSTRINGIFY(PRODUCT_ID_VER_BARE) #define VIDEO_TROUBLESHOOTING_URL "http://old.stepmania.com/stepmaniawiki.php?title=Video_Driver_Troubleshooting" /** @brief The URL to report bugs on the program. */ diff --git a/src/ProductInfo.inc b/src/ProductInfo.inc index bb271ea572..eb9079f405 100644 --- a/src/ProductInfo.inc +++ b/src/ProductInfo.inc @@ -6,8 +6,9 @@ ; PRODUCT_ID must NOT be "StepMania" unless you want people to uninstall 3.9 ; when they install StepMania 5. (not recommended) -!define PRODUCT_ID "StepMania 5" -!define PRODUCT_VER "v5.0 beta 4a" +!define PRODUCT_ID "StepMania 5.0" +; TODO: This needs to be updated with the git rev hash +!define PRODUCT_VER "5.0-UNKNOWN" !define PRODUCT_DISPLAY "${PRODUCT_FAMILY} ${PRODUCT_VER}" !define PRODUCT_BITMAP "sm5" diff --git a/src/RageTexture.cpp b/src/RageTexture.cpp index 210ee7997a..bdd02897e2 100644 --- a/src/RageTexture.cpp +++ b/src/RageTexture.cpp @@ -108,6 +108,12 @@ public: p->Reload(); COMMON_RETURN_SELF; } + DEFINE_METHOD(GetSourceWidth, GetSourceWidth()); + DEFINE_METHOD(GetSourceHeight, GetSourceHeight()); + DEFINE_METHOD(GetTextureWidth, GetTextureWidth()); + DEFINE_METHOD(GetTextureHeight, GetTextureHeight()); + DEFINE_METHOD(GetImageWidth, GetImageWidth()); + DEFINE_METHOD(GetImageHeight, GetImageHeight()); LunaRageTexture() { @@ -117,6 +123,12 @@ public: ADD_METHOD( GetTextureCoordRect ); ADD_METHOD( GetNumFrames ); ADD_METHOD( Reload ); + ADD_METHOD(GetSourceWidth); + ADD_METHOD(GetSourceHeight); + ADD_METHOD(GetTextureWidth); + ADD_METHOD(GetTextureHeight); + ADD_METHOD(GetImageWidth); + ADD_METHOD(GetImageHeight); } }; diff --git a/src/RageUtil.cpp b/src/RageUtil.cpp index c2d033f87e..b61b3f12b3 100644 --- a/src/RageUtil.cpp +++ b/src/RageUtil.cpp @@ -1342,7 +1342,11 @@ bool GetFileContents( const RString &sFile, vector &asOut ) return true; } +#ifndef USE_SYSTEM_PCRE #include "../extern/pcre/pcre.h" +#else +#include +#endif void Regex::Compile() { const char *error; diff --git a/src/ReceptorArrowRow.cpp b/src/ReceptorArrowRow.cpp index 5a0a1d9870..c339601a7b 100644 --- a/src/ReceptorArrowRow.cpp +++ b/src/ReceptorArrowRow.cpp @@ -12,6 +12,7 @@ ReceptorArrowRow::ReceptorArrowRow() m_pPlayerState = NULL; m_fYReverseOffsetPixels = 0; m_fFadeToFailPercent = 0; + m_renderers= NULL; } void ReceptorArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOffset ) @@ -62,8 +63,18 @@ void ReceptorArrowRow::Update( float fDeltaTime ) CLAMP( fBaseAlpha, 0.0f, 1.0f ); m_ReceptorArrow[c]->SetBaseAlpha( fBaseAlpha ); - // set arrow XYZ - (*m_renderers)[c].UpdateReceptorGhostStuff(m_ReceptorArrow[c]); + if(m_renderers != NULL) + { + // set arrow XYZ + (*m_renderers)[c].UpdateReceptorGhostStuff(m_ReceptorArrow[c]); + } + else + { + // ScreenNameEntry uses ReceptorArrowRow but doesn't have or need + // column renderers. Just do the lazy thing and offset x. -Kyz + const Style* style= GAMESTATE->GetCurrentStyle(m_pPlayerState->m_PlayerNumber); + m_ReceptorArrow[c]->SetX(style->m_ColumnInfo[m_pPlayerState->m_PlayerNumber][c].fXOffset); + } } } diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index ddc40cf237..81f815bcc5 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -198,7 +198,7 @@ void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps, GAMESTATE->SetProcessedTimingData(NULL); } -static int GetScore(int p, int Z, int S, int n) +static int GetScore(int p, int Z, int64_t S, int n) { /* There's a problem with the scoring system described below. Z/S is truncated * to an int. However, in some cases we can end up with very small base scores. @@ -260,8 +260,8 @@ void ScoreKeeperNormal::AddScoreInternal( TapNoteScore score ) if( m_UseInternalScoring ) { - int &iScore = m_pPlayerStageStats->m_iScore; - int &iCurMaxScore = m_pPlayerStageStats->m_iCurMaxScore; + unsigned int &iScore = m_pPlayerStageStats->m_iScore; + unsigned int &iCurMaxScore = m_pPlayerStageStats->m_iCurMaxScore; // See Aaron In Japan for more details about the scoring formulas. // Note: this assumes no custom scoring systems are in use. @@ -277,8 +277,8 @@ void ScoreKeeperNormal::AddScoreInternal( TapNoteScore score ) m_iTapNotesHit++; - const int N = m_iNumTapsAndHolds; - const int sum = (N * (N + 1)) / 2; + const int64_t N = uint64_t(m_iNumTapsAndHolds); + const int64_t sum = (N * (N + 1)) / 2; const int Z = m_iMaxPossiblePoints/10; // Don't use a multiplier if the player has failed @@ -320,15 +320,11 @@ void ScoreKeeperNormal::AddScoreInternal( TapNoteScore score ) iCurMaxScore += m_iPointBonus; } - ASSERT_M( iScore >= 0, "iScore < 0 before re-rounding" ); - // Undo rounding from the last tap, and re-round. iScore += m_iScoreRemainder; m_iScoreRemainder = (iScore % m_iRoundTo); iScore = iScore - m_iScoreRemainder; - ASSERT_M( iScore >= 0, "iScore < 0 after re-rounding" ); - // LOG->Trace( "score: %i", iScore ); } } diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 8f5d5221fe..f9d17bc839 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3200,9 +3200,9 @@ void ScreenEdit::TransitionEditState( EditState em ) if( bStateChanging ) AdjustSync::ResetOriginalSyncData(); - /* Give a 1 second lead-in. If we're loading Player, this must be done first. + /* Give a lead-in. If we're loading Player, this must be done first. * Also be sure to get the right timing. */ - float fSeconds = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - 1; + float fSeconds = GetAppropriateTiming().GetElapsedTimeFromBeat( NoteRowToBeat(m_iStartPlayingAt) ) - PREFSMAN->m_EditRecordModeLeadIn; GAMESTATE->UpdateSongPosition( fSeconds, GetAppropriateTiming(), RageZeroTimer ); GAMESTATE->m_bGameplayLeadIn.Set( false ); diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 9ae8b40011..6567f96ab3 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1932,7 +1932,7 @@ void ScreenGameplay::Update( float fDeltaTime ) } if (bAllHumanHaveBigMissCombo) // possible to get in here. { - bAllHumanHaveBigMissCombo = FAIL_ON_MISS_COMBO.GetValue() != -1 && STATSMAN->m_CurStageStats.GetMinimumMissCombo() >= FAIL_ON_MISS_COMBO; + bAllHumanHaveBigMissCombo = FAIL_ON_MISS_COMBO.GetValue() != -1 && STATSMAN->m_CurStageStats.GetMinimumMissCombo() >= (unsigned int)FAIL_ON_MISS_COMBO; } if( bGiveUpTimerFired || bAllHumanHaveBigMissCombo ) { diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 8dca990655..c8395978e8 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -680,6 +680,16 @@ static void GlobalOffsetSeconds( int &sel, bool ToSel, const ConfOption *pConfOp MoveMap( sel, pConfOption, ToSel, mapping, ARRAYLEN(mapping) ); } +static void EditRecordModeLeadIn(int &sel, bool to_sel, const ConfOption* conf_option) +{ + float mapping[32]; + for(int i= 0; i < 32; ++i) + { + mapping[i]= static_cast(i); + } + MoveMap(sel, conf_option, to_sel, mapping, ARRAYLEN(mapping)); +} + static vector g_ConfOptions; static void InitializeConfOptions() { @@ -725,6 +735,14 @@ static void InitializeConfOptions() ADD( ConfOption( "AutogenGroupCourses", MovePref, "Off","On" ) ); ADD( ConfOption( "FastLoad", MovePref, "Off","On" ) ); ADD( ConfOption( "FastLoadAdditionalSongs", MovePref, "Off","On" ) ); + { + ConfOption c("EditRecordModeLeadIn", EditRecordModeLeadIn); + for(int i= 0; i < 32; ++i) + { + c.AddOption(ssprintf("%+i s", i)); + } + ADD(c); + } // Background options ADD( ConfOption( "RandomBackgroundMode", MovePref, "Off","Animations","Random Movies" ) ); diff --git a/src/ScreenSyncOverlay.cpp b/src/ScreenSyncOverlay.cpp index be23fc1c08..8c87f6bb0f 100644 --- a/src/ScreenSyncOverlay.cpp +++ b/src/ScreenSyncOverlay.cpp @@ -29,13 +29,14 @@ void ScreenSyncOverlay::Init() Screen::Init(); m_quad.SetDiffuse( RageColor(0,0,0,0) ); - m_quad.SetHorizAlign( align_left ); - m_quad.SetXY( SCREEN_CENTER_X+10, SCREEN_TOP+100 ); + m_quad.SetHorizAlign(align_right); + m_quad.SetVertAlign(align_top); + m_quad.SetXY(SCREEN_WIDTH, SCREEN_TOP); this->AddChild( &m_quad ); m_textHelp.LoadFromFont( THEME->GetPathF("Common", "normal") ); m_textHelp.SetHorizAlign( align_left ); - m_textHelp.SetXY( SCREEN_CENTER_X+20, SCREEN_TOP+100 ); + m_textHelp.SetVertAlign(align_top); m_textHelp.SetDiffuseAlpha( 0 ); m_textHelp.SetShadowLength( 2 ); m_textHelp.SetText( @@ -48,6 +49,8 @@ void ScreenSyncOverlay::Init() MACHINE_OFFSET.GetValue()+":\n" " Shift + F11/F12\n" + HOLD_ALT.GetValue() ); + m_textHelp.SetXY(SCREEN_WIDTH - m_textHelp.GetZoomedWidth() - 10, + SCREEN_TOP + 10); this->AddChild( &m_textHelp ); m_quad.ZoomToWidth( m_textHelp.GetZoomedWidth()+20 ); diff --git a/src/Song.cpp b/src/Song.cpp index 54f62fed82..1ccdf2c8f2 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -1916,6 +1916,33 @@ public: return 1; } static int GetTimingData( T* p, lua_State *L ) { p->m_SongTiming.PushSelf(L); return 1; } + static int GetBGChanges(T* p, lua_State* L) + { + const vector& changes= p->GetBackgroundChanges(BACKGROUND_LAYER_1); + lua_createtable(L, changes.size(), 0); + for(size_t c= 0; c < changes.size(); ++c) + { + lua_createtable(L, 0, 8); + lua_pushnumber(L, changes[c].m_fStartBeat); + lua_setfield(L, -2, "start_beat"); + lua_pushnumber(L, changes[c].m_fRate); + lua_setfield(L, -2, "rate"); + LuaHelpers::Push(L, changes[c].m_sTransition); + lua_setfield(L, -2, "transition"); + LuaHelpers::Push(L, changes[c].m_def.m_sEffect); + lua_setfield(L, -2, "effect"); + LuaHelpers::Push(L, changes[c].m_def.m_sFile1); + lua_setfield(L, -2, "file1"); + LuaHelpers::Push(L, changes[c].m_def.m_sFile2); + lua_setfield(L, -2, "file2"); + LuaHelpers::Push(L, changes[c].m_def.m_sColor1); + lua_setfield(L, -2, "color1"); + LuaHelpers::Push(L, changes[c].m_def.m_sColor2); + lua_setfield(L, -2, "color2"); + lua_rawseti(L, -2, c+1); + } + return 1; + } // has functions static int HasMusic( T* p, lua_State *L ) { lua_pushboolean(L, p->HasMusic()); return 1; } static int HasBanner( T* p, lua_State *L ) { lua_pushboolean(L, p->HasBanner()); return 1; } @@ -2053,6 +2080,7 @@ public: ADD_METHOD( HasStepsTypeAndDifficulty ); ADD_METHOD( GetOneSteps ); ADD_METHOD( GetTimingData ); + ADD_METHOD(GetBGChanges); ADD_METHOD( HasMusic ); ADD_METHOD( HasBanner ); ADD_METHOD( HasBackground ); diff --git a/src/Sprite.cpp b/src/Sprite.cpp index 307ec13e76..da98194523 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -26,6 +26,7 @@ Sprite::Sprite() m_bUsingCustomTexCoords = false; m_bUsingCustomPosCoords = false; m_bSkipNextUpdate = true; + m_DecodeMovie= true; m_EffectMode = EffectMode_Normal; m_fRememberedClipWidth = -1; @@ -62,6 +63,7 @@ Sprite::Sprite( const Sprite &cpy ): CPY( m_bUsingCustomTexCoords ); CPY( m_bUsingCustomPosCoords ); CPY( m_bSkipNextUpdate ); + CPY( m_DecodeMovie ); CPY( m_EffectMode ); memcpy( m_CustomTexCoords, cpy.m_CustomTexCoords, sizeof(m_CustomTexCoords) ); memcpy( m_CustomPosCoords, cpy.m_CustomPosCoords, sizeof(m_CustomPosCoords) ); @@ -186,11 +188,6 @@ void Sprite::LoadFromNode( const XNode* pNode ) { newState.fDelay = 0.1f; } - if(newState.fDelay <= min_state_delay) - { - LuaHelpers::ReportScriptErrorFmt("%s: State #%i has near-zero delay.", ActorUtil::GetWhere(pNode).c_str(), i+1); - newState.fDelay= 0.1f; - } pFrame->GetAttrValue( "Frame", iFrameIndex ); if( iFrameIndex >= m_pTexture->GetNumFrames() ) @@ -362,7 +359,12 @@ void Sprite::UpdateAnimationState() // We already know what's going to show. if( m_States.size() > 1 ) { - while( m_fSecsIntoState+min_state_delay > m_States[m_iCurState].fDelay ) // it's time to switch frames + // UpdateAnimationState changed to not loop forever on negative state + // delay. This allows a state to last forever when it is reached, so + // the animation has a built-in ending point. -Kyz + while(m_States[m_iCurState].fDelay > min_state_delay && + m_fSecsIntoState+min_state_delay > m_States[m_iCurState].fDelay) + // it's time to switch frames { // increment frame and reset the counter m_fSecsIntoState -= m_States[m_iCurState].fDelay; // leave the left over time for the next frame @@ -408,7 +410,7 @@ void Sprite::Update( float fDelta ) UpdateAnimationState(); // If the texture is a movie, decode frames. - if( !bSkipThisMovieUpdate ) + if(!bSkipThisMovieUpdate && m_DecodeMovie) m_pTexture->DecodeSeconds( max(0, fTimePassed) ); // update scrolling @@ -1047,15 +1049,6 @@ void Sprite::AddImageCoords( float fX, float fY ) class LunaSprite: public Luna { public: - static float valid_state_delay(lua_State* L, int i) - { - float delay= FArg(i); - if(delay <= min_state_delay) - { - luaL_error(L, "State delay cannot be less than or equal to zero."); - } - return delay; - } static int Load( T* p, lua_State *L ) { if( lua_isnil(L, 1) ) @@ -1151,7 +1144,7 @@ public: lua_getfield(L, -1, "Delay"); if(lua_isnumber(L, -1)) { - new_state.fDelay= valid_state_delay(L, -1); + new_state.fDelay= FArg(-1); } lua_pop(L, 1); RectF r= new_state.rect; @@ -1216,8 +1209,13 @@ public: static int GetNumStates( T* p, lua_State *L ) { lua_pushnumber( L, p->GetNumStates() ); return 1; } static int SetAllStateDelays( T* p, lua_State *L ) { - float delay= valid_state_delay(L, -1); - p->SetAllStateDelays(delay); + p->SetAllStateDelays(FArg(-1)); + COMMON_RETURN_SELF; + } + DEFINE_METHOD(GetDecodeMovie, m_DecodeMovie); + static int SetDecodeMovie(T* p, lua_State *L) + { + p->m_DecodeMovie= BArg(1); COMMON_RETURN_SELF; } @@ -1245,6 +1243,8 @@ public: ADD_METHOD( SetEffectMode ); ADD_METHOD( GetNumStates ); ADD_METHOD( SetAllStateDelays ); + ADD_METHOD(GetDecodeMovie); + ADD_METHOD(SetDecodeMovie); } }; diff --git a/src/Sprite.h b/src/Sprite.h index 9c136b91f5..30da184a7c 100644 --- a/src/Sprite.h +++ b/src/Sprite.h @@ -90,6 +90,8 @@ public: void SetAllStateDelays(float fDelay); + bool m_DecodeMovie; + protected: void LoadFromTexture( RageTextureID ID ); diff --git a/src/StageStats.cpp b/src/StageStats.cpp index 1b98d59e56..67c4caed84 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -331,9 +331,9 @@ bool StageStats::PlayerHasHighScore( PlayerNumber pn ) const return false; } -int StageStats::GetMinimumMissCombo() const +unsigned int StageStats::GetMinimumMissCombo() const { - int iMin = INT_MAX; + unsigned int iMin = INT_MAX; FOREACH_HumanPlayer( p ) iMin = min( iMin, m_player[p].m_iCurMissCombo ); return iMin; diff --git a/src/StageStats.h b/src/StageStats.h index 487de34250..8e73710123 100644 --- a/src/StageStats.h +++ b/src/StageStats.h @@ -74,7 +74,7 @@ public: * @param pn the PlayerNumber in question. * @return true if the PlayerNumber has a high score, false otherwise. */ bool PlayerHasHighScore( PlayerNumber pn ) const; - int GetMinimumMissCombo() const; + unsigned int GetMinimumMissCombo() const; // Lua void PushSelf( lua_State *L ); diff --git a/src/StepMania-net2011.vcxproj b/src/StepMania-net2011.vcxproj index c487cda738..ede4f0a84f 100644 --- a/src/StepMania-net2011.vcxproj +++ b/src/StepMania-net2011.vcxproj @@ -1225,36 +1225,6 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1920,6 +1890,9 @@ cl /Zl /nologo /c verstub.cpp /Fo"$(IntDir)" {9522f2e6-ffeb-4620-9ee2-79353a55671b} + + {0dcaa088-fc09-4422-892b-8e89f1f798cb} + {046c857a-41c5-4e87-ad44-462ab17bbf4f} diff --git a/src/StepMania-net2011.vcxproj.filters b/src/StepMania-net2011.vcxproj.filters index 3af88b8911..ca8eddefb0 100644 --- a/src/StepMania-net2011.vcxproj.filters +++ b/src/StepMania-net2011.vcxproj.filters @@ -97,12 +97,6 @@ {2d157d5c-7c0e-4967-925a-3976a6ad0dd0} - - {46a5ab77-6eaf-44eb-93ec-43b2db4741ff} - - - {52c8e19c-32ec-4115-bee6-f5957389d7ea} - @@ -1452,15 +1446,6 @@ BaseClasses - - Helpers\jsoncpp - - - Helpers\jsoncpp - - - Helpers\jsoncpp - Data Structures diff --git a/src/StepMania.cpp b/src/StepMania.cpp index 98dbf12cde..69059c5715 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -69,6 +69,10 @@ #include "Profile.h" #include "ActorUtil.h" +#ifdef HAVE_VERSION_INFO +#include "ver.h" +#endif + #if defined(WIN32) #include #endif @@ -907,15 +911,10 @@ static void MountTreeOfZips( const RString &dir ) } } -#if defined(HAVE_VERSION_INFO) -extern unsigned long version_num; -extern const char *const version_date; -extern const char *const version_time; -#endif static void WriteLogHeader() { - LOG->Info( PRODUCT_ID_VER ); + LOG->Info("%s%s", PRODUCT_FAMILY, product_version); #if defined(HAVE_VERSION_INFO) LOG->Info( "Compiled %s @ %s (build %lu)", version_date, version_time, version_num ); diff --git a/src/WheelBase.cpp b/src/WheelBase.cpp index 99142ec4e1..8adb5fd205 100644 --- a/src/WheelBase.cpp +++ b/src/WheelBase.cpp @@ -290,7 +290,7 @@ bool WheelBase::Select() // return true if this selection can end the screen { case WheelItemDataType_Generic: m_LastSelection = m_CurWheelItemData[m_iSelection]; - break; + return true; case WheelItemDataType_Section: { RString sThisItemSectionName = m_CurWheelItemData[m_iSelection]->m_sText; @@ -305,12 +305,11 @@ bool WheelBase::Select() // return true if this selection can end the screen m_soundExpand.Play(); } } - break; + // Opening/closing sections cannot end the screen + return false; default: - break; + return true; } - - return true; } WheelItemBaseData* WheelBase::GetItem( unsigned int iIndex ) diff --git a/src/archutils/Unix/CrashHandlerChild.cpp b/src/archutils/Unix/CrashHandlerChild.cpp index 518ad0c7f6..7c9ef9412f 100644 --- a/src/archutils/Unix/CrashHandlerChild.cpp +++ b/src/archutils/Unix/CrashHandlerChild.cpp @@ -22,11 +22,7 @@ #include "archutils/Darwin/Crash.h" #endif -#if defined(HAVE_VERSION_INFO) -extern const unsigned long version_num; -extern const char *const version_date; -extern const char *const version_time; -#endif +#include "ver.h" bool child_read( int fd, void *p, int size ); @@ -204,7 +200,7 @@ static void child_process() exit(1); } - fprintf( CrashDump, "%s crash report", PRODUCT_ID_VER ); + fprintf( CrashDump, "%s%s crash report", PRODUCT_FAMILY, product_version ); #if defined(HAVE_VERSION_INFO) fprintf( CrashDump, " (build %lu, %s @ %s)", version_num, version_date, version_time ); #endif diff --git a/src/archutils/Win32/CrashHandlerChild.cpp b/src/archutils/Win32/CrashHandlerChild.cpp index 7e377017df..98c1c2f350 100644 --- a/src/archutils/Win32/CrashHandlerChild.cpp +++ b/src/archutils/Win32/CrashHandlerChild.cpp @@ -25,14 +25,14 @@ #include "XmlFileUtil.h" #include "LocalizedString.h" #include "RageFileDriverDeflate.h" +#include "ver.h" #if defined(_MSC_VER) #pragma comment(lib, "archutils/Win32/ddk/dbghelp.lib") #endif -extern unsigned long version_num; -extern const char *const version_date; -extern const char *const version_time; +// XXX: What happens when we *don't* have version info? Does that ever actually happen? +#include "ver.h" // VDI symbol lookup: namespace VDDebugInfo @@ -435,7 +435,7 @@ static void MakeCrashReport( const CompleteCrashData &Data, RString &sOut ) sOut += ssprintf( "%s crash report (build %d, %s @ %s)\n" "--------------------------------------\n\n", - PRODUCT_ID_VER, version_num, version_date, version_time ); + (string(PRODUCT_FAMILY) + product_version).c_str(), version_num, version_date, version_time ); sOut += ssprintf( "Crash reason: %s\n", Data.m_CrashInfo.m_CrashReason ); sOut += ssprintf( "\n" ); @@ -738,7 +738,7 @@ BOOL CrashDialog::HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam ) // Create the form data to send. m_pPost = new NetworkPostData; m_pPost->SetData( "Product", PRODUCT_ID ); - m_pPost->SetData( "Version", PRODUCT_VER ); + m_pPost->SetData( "Version", product_version ); m_pPost->SetData( "Arch", HOOKS->GetArchName().c_str() ); m_pPost->SetData( "Report", m_sCrashReport ); m_pPost->SetData( "Reason", m_CrashData.m_CrashInfo.m_CrashReason ); diff --git a/src/archutils/Win32/SpecialDirs.cpp b/src/archutils/Win32/SpecialDirs.cpp index 5c48528e9e..499dd78538 100644 --- a/src/archutils/Win32/SpecialDirs.cpp +++ b/src/archutils/Win32/SpecialDirs.cpp @@ -6,8 +6,8 @@ static RString GetSpecialFolderPath( int csidl ) { RString sDir; TCHAR szDir[MAX_PATH] = ""; - BOOL bResult = SHGetSpecialFolderPath( NULL, szDir, csidl, FALSE ); - ASSERT( bResult ); + HRESULT hResult = SHGetFolderPath( NULL, csidl, NULL, SHGFP_TYPE_CURRENT, szDir ); + ASSERT( hResult == S_OK ); sDir = szDir; sDir += "/"; return sDir; diff --git a/src/archutils/Win32/verinc.c b/src/archutils/Win32/verinc.c index e12895d408..a0811fbcd0 100644 --- a/src/archutils/Win32/verinc.c +++ b/src/archutils/Win32/verinc.c @@ -1,72 +1,73 @@ -// Ehhh.... -// -// I think I'll just put this one in the public domain -// (with no warranty as usual). -// -// --Avery - -// took some ideas from OpenITG... -aj - -#include -#include -#include -#include - -typedef unsigned long ulong; - -int main(void) -{ - FILE *f; - ulong build=0; - char strdate[10], strtime[64]; - time_t tm; - //struct tm *ptm; - - // try to read the last version seen - if( f = fopen("version.bin","r") ) - { - fread( &build, sizeof(ulong), 1, f ); - fclose( f ); - } - - // increment the build number and write it - build++; - - if ( f = fopen("version.bin","wb") ) - { - fwrite(&build,sizeof(ulong),1,f); - fclose(f); - } -// printf("Incrementing to build %d\n",build); - - // get the current time - time(&tm); - - /* - //memcpy(version_time, asctime(localtime(&tm)), sizeof(version_time)-1); - ptm = localtime(&tm); - strftime(s, sizeof(s), "%Y%m%d", ptm); - s[sizeof(s)-1]=0; - */ - - // print the debug serial date/time - strftime( strdate, 15, "%Y%m%d", localtime(&tm) ); - strftime( strtime, 64, "%H:%M:%S %Z", localtime(&tm) ); - //memcpy( strtime, asctime(localtime(&tm)), 24 ); - - // zero out the newline character - strtime[sizeof(strtime)-1] = 0; - - // write to verstub - if ( f = fopen("verstub.cpp","w") ) - { - fprintf(f, - "unsigned long version_num = %ld;\n" - "extern const char *const version_date = \"%s\";\n" - "extern const char *const version_time = \"%s\";\n", - build, strdate, strtime); - fclose(f); - } - - return 0; -} +// Ehhh.... +// +// I think I'll just put this one in the public domain +// (with no warranty as usual). +// +// --Avery + +// took some ideas from OpenITG... -aj + +#include +#include +#include +#include + +typedef unsigned long ulong; + +int main(void) +{ + FILE *f; + ulong build=0; + char strdate[10], strtime[64]; + time_t tm; + //struct tm *ptm; + + // try to read the last version seen + if( f = fopen("version.bin","r") ) + { + fread( &build, sizeof(ulong), 1, f ); + fclose( f ); + } + + // increment the build number and write it + build++; + + if ( f = fopen("version.bin","wb") ) + { + fwrite(&build,sizeof(ulong),1,f); + fclose(f); + } +// printf("Incrementing to build %d\n",build); + + // get the current time + time(&tm); + + /* + //memcpy(version_time, asctime(localtime(&tm)), sizeof(version_time)-1); + ptm = localtime(&tm); + strftime(s, sizeof(s), "%Y%m%d", ptm); + s[sizeof(s)-1]=0; + */ + + // print the debug serial date/time + strftime( strdate, 15, "%Y%m%d", localtime(&tm) ); + strftime( strtime, 64, "%H:%M:%S %Z", localtime(&tm) ); + //memcpy( strtime, asctime(localtime(&tm)), 24 ); + + // zero out the newline character + strtime[sizeof(strtime)-1] = 0; + + // write to verstub + if ( f = fopen("verstub.cpp","w") ) + { + fprintf(f, + "#include \"ver.h\"\n" + "unsigned long const version_num = %ld;\n" + "extern char const * const version_date = \"%s\";\n" + "extern char const * const version_time = \"%s\";\n", + build, strdate, strtime); + fclose(f); + } + + return 0; +} diff --git a/src/archutils/Win32/verinc.exe b/src/archutils/Win32/verinc.exe index d17008756a..b4d83adbb6 100644 Binary files a/src/archutils/Win32/verinc.exe and b/src/archutils/Win32/verinc.exe differ diff --git a/src/sm5-net2011.sln b/src/sm5-net2011.sln index c7498d19cc..b3c11814db 100644 --- a/src/sm5-net2011.sln +++ b/src/sm5-net2011.sln @@ -15,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libglew", "..\extern\glew-1 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "liblua", "..\extern\lua-5.1\liblua-net2011.vcxproj", "{0555A743-D202-409C-A331-349FEE971025}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libjson", "..\extern\jsoncpp\libjson-net2011.vcxproj", "{0DCAA088-FC09-4422-892B-8E89F1F798CB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -79,6 +81,14 @@ Global {0555A743-D202-409C-A331-349FEE971025}.Release|Win32.Build.0 = Release|Win32 {0555A743-D202-409C-A331-349FEE971025}.Release-SSE2|Win32.ActiveCfg = Release|Win32 {0555A743-D202-409C-A331-349FEE971025}.Release-SSE2|Win32.Build.0 = Release|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.Debug|Win32.ActiveCfg = Debug|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.Debug|Win32.Build.0 = Debug|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.FastDebug|Win32.ActiveCfg = Debug|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.FastDebug|Win32.Build.0 = Debug|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.Release|Win32.ActiveCfg = Release|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.Release|Win32.Build.0 = Release|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.Release-SSE2|Win32.ActiveCfg = Release|Win32 + {0DCAA088-FC09-4422-892B-8E89F1F798CB}.Release-SSE2|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ver.h b/src/ver.h new file mode 100644 index 0000000000..adb3b99e87 --- /dev/null +++ b/src/ver.h @@ -0,0 +1,19 @@ +#ifndef STEPMANIA_VER_H +#define STEPMANIA_VER_H + + + +// HACK: The MSVC project doesn't generate this yet +#if defined(_MSC_VER) || defined(__MACOSX__) +#define product_version "5.0-UNKNOWN" +#else +extern const char *const product_version; +#endif + +// XXX: These names are misnomers. This is actually the BUILD number, time and date. +// NOTE: In GNU toolchain these are defined in ver.cpp. In MSVC these are defined in archutils/Win32/verinc.c I think. Why? I don't know and I don't have MSVC. --root +extern const unsigned long version_num; +extern const char *const version_time; +extern const char *const version_date; + +#endif \ No newline at end of file