Maybe editing the changelog should only be done after merging a pull, to avoid conflicts.
This commit is contained in:
@@ -8,6 +8,23 @@ ________________________________________________________________________________
|
||||
----------
|
||||
* [Sprite] SetStateProperties function added. [kyzentun]
|
||||
|
||||
2015/01/06
|
||||
----------
|
||||
* [ActorMultiVertex] GetSpline and SetVertsFromSplines functions added.
|
||||
[kyzentun]
|
||||
* [NoteColumnRenderer] Functions for fetching the spline handlers for the
|
||||
column added. [kyzentun]
|
||||
* [NCSplineHandler] New class for setting various parameters of a spline used
|
||||
by a NoteColumnRenderer and containing the spline. [kyzentun]
|
||||
* [CubicSplineN] New class that provides spline functionality. [kyzentun]
|
||||
|
||||
2014/12/26
|
||||
----------
|
||||
* [NoteField] Columns turned into actors that can be fetched with
|
||||
get_column_actors. [kyzentun]
|
||||
Tiny boost in fps when there is a large number of notes on screen.
|
||||
* [NoteColumnRenderer] New class for controlling one column. [kyzentun]
|
||||
|
||||
2014/12/20
|
||||
----------
|
||||
* [Preferences] AllowMultipleHighScoreWithSameName, ComboContinuesBetweenSongs
|
||||
|
||||
+59
-8
@@ -272,6 +272,7 @@
|
||||
<Function name='GetDiffuse'/>
|
||||
<Function name='GetDiffuseAlpha'/>
|
||||
<Function name='GetEffectDelta'/>
|
||||
<Function name='GetFakeParent'/>
|
||||
<Function name='GetGlow'/>
|
||||
<Function name='GetHAlign'/>
|
||||
<Function name='GetHeight'/>
|
||||
@@ -301,6 +302,7 @@
|
||||
<Function name='Real'/>
|
||||
<Function name='RealInverse'/>
|
||||
<Function name='RunCommandsRecursively'/>
|
||||
<Function name='SetFakeParent'/>
|
||||
<Function name='SetHeight'/>
|
||||
<Function name='SetSize'/>
|
||||
<Function name='SetTextureFiltering'/>
|
||||
@@ -494,6 +496,7 @@
|
||||
<Function name='GetDestFirstToDraw'/>
|
||||
<Function name='GetDestNumToDraw'/>
|
||||
<Function name='GetNumVertices'/>
|
||||
<Function name='GetSpline'/>
|
||||
<Function name='GetTexture'/>
|
||||
<Function name='LoadTexture'/>
|
||||
<Function name='SetDrawState'/>
|
||||
@@ -504,6 +507,7 @@
|
||||
<Function name='SetTextureMode'/>
|
||||
<Function name='SetVertex'/>
|
||||
<Function name='SetVertices'/>
|
||||
<Function name='SetVertsFromSplines'/>
|
||||
</Class>
|
||||
<Class base='Actor' name='ActorProxy'>
|
||||
<Function name='GetTarget'/>
|
||||
@@ -676,6 +680,31 @@
|
||||
<Function name='SHA1File'/>
|
||||
<Function name='SHA1String'/>
|
||||
</Class>
|
||||
<Class name='CubicSplineN'>
|
||||
<Function name='solve'/>
|
||||
<Function name='evaluate'/>
|
||||
<Function name='evaluate_derivative'/>
|
||||
<Function name='evaluate_second_derivative'/>
|
||||
<Function name='evaluate_third_derivative'/>
|
||||
<Function name='set_point'/>
|
||||
<Function name='set_coefficients'/>
|
||||
<Function name='get_coefficients'/>
|
||||
<Function name='set_spatial_extent'/>
|
||||
<Function name='get_spatial_extent'/>
|
||||
<Function name='get_max_t'/>
|
||||
<Function name='set_size'/>
|
||||
<Function name='get_size'/>
|
||||
<Function name='set_dimension'/>
|
||||
<Function name='get_dimension'/>
|
||||
<Function name='empty'/>
|
||||
<Function name='set_loop'/>
|
||||
<Function name='get_loop'/>
|
||||
<Function name='set_polygonal'/>
|
||||
<Function name='get_polygonal'/>
|
||||
<Function name='set_dirty'/>
|
||||
<Function name='get_dirty'/>
|
||||
<Function name='destroy'/>
|
||||
</Class>
|
||||
<Class base='Sprite' name='DifficultyIcon'>
|
||||
<Function name='SetFromDifficulty'/>
|
||||
<Function name='SetFromSteps'/>
|
||||
@@ -965,15 +994,32 @@
|
||||
<Function name='SelectCourse'/>
|
||||
<Function name='SelectSong'/>
|
||||
</Class>
|
||||
<Class name='NCSplineHandler'>
|
||||
<Function name='get_spline'/>
|
||||
<Function name='get_beats_per_t'/>
|
||||
<Function name='set_beats_per_t'/>
|
||||
<Function name='get_receptor_t'/>
|
||||
<Function name='set_receptor_t'/>
|
||||
<Function name='get_spline_mode'/>
|
||||
<Function name='set_spline_mode'/>
|
||||
<Function name='get_subtract_song_beat'/>
|
||||
<Function name='set_subtract_song_beat'/>
|
||||
</Class>
|
||||
<Class base='Actor' name='NoteColumnRenderer'>
|
||||
<Function name='get_pos_handler'/>
|
||||
<Function name='get_rot_handler'/>
|
||||
<Function name='get_zoom_handler'/>
|
||||
</Class>
|
||||
<Class base='ActorFrame' name='NoteField'>
|
||||
<Function name='DidHoldNote'/>
|
||||
<Function name='DidTapNote'/>
|
||||
<Function name='SetPressed'/>
|
||||
<Function name='SetDidHoldNoteCallback'/>
|
||||
<Function name='SetDidTapNoteCallback'/>
|
||||
<Function name='SetSetPressedCallback'/>
|
||||
<Function name='SetStepCallback'/>
|
||||
<Function name='Step'/>
|
||||
<Function name='did_hold_note'/>
|
||||
<Function name='did_tap_note'/>
|
||||
<Function name='get_column_actors'/>
|
||||
<Function name='set_pressed'/>
|
||||
<Function name='set_did_hold_note_callback'/>
|
||||
<Function name='set_did_tap_note_callback'/>
|
||||
<Function name='set_set_pressed_callback'/>
|
||||
<Function name='set_step_callback'/>
|
||||
<Function name='step'/>
|
||||
</Class>
|
||||
<Class name='NoteSkinManager'>
|
||||
<Function name='DoesNoteSkinExist'/>
|
||||
@@ -2213,6 +2259,11 @@
|
||||
<EnumValue name=''MusicWheelUsesSections_Always'' value='1'/>
|
||||
<EnumValue name=''MusicWheelUsesSections_ABCOnly'' value='2'/>
|
||||
</Enum>
|
||||
<Enum name='NoteColumnSplineMode'>
|
||||
<EnumValue name=''NoteColumnSplineMode_Disabled'' value='0'/>
|
||||
<EnumValue name=''NoteColumnSplineMode_Offset'' value='1'/>
|
||||
<EnumValue name=''NoteColumnSplineMode_Position'' value='2'/>
|
||||
</Enum>
|
||||
<Enum name='NotePart'>
|
||||
<EnumValue name=''NotePart_TapNote'' value='0'/>
|
||||
<EnumValue name=''NotePart_TapMine'' value='1'/>
|
||||
|
||||
@@ -112,6 +112,9 @@ save yourself some time, copy this for undocumented things:
|
||||
<Function name='ConnectToServer' return='bool' arguments='string sAddress'>
|
||||
Tries to connect to the server at <code>sAddress</code>.
|
||||
</Function>
|
||||
<Function name='create_spline' return='CubicSplineN' arguments=''>
|
||||
Creates a CubicSplineN for you to use. Make sure you destroy the CubicSplineN when you're done with it, or you will have a memory leak.
|
||||
</Function>
|
||||
<Function name='CustomDifficultyToColor' theme='_fallback' return='color' arguments='string cd'>
|
||||
[02 Colors.lua]
|
||||
</Function>
|
||||
@@ -831,6 +834,12 @@ save yourself some time, copy this for undocumented things:
|
||||
<Function name='GetParent' return='Actor' arguments=''>
|
||||
Returns the Actor's parent, or <code>nil</code> if it doesn't have one.
|
||||
</Function>
|
||||
<Function name='GetFakeParent' return='Actor' arguments=''>
|
||||
Returns the Actor's fake parent, or <code>nil</code> if it doesn't have one.
|
||||
</Function>
|
||||
<Function name='SetFakeParent' return='' arguments='Actor p'>
|
||||
Sets the Actor's fake parent to p, or clears it if p is nil.
|
||||
</Function>
|
||||
<Function name='GetVisible' return='bool' arguments=''>
|
||||
Returns the Actor's visibility.
|
||||
</Function>
|
||||
@@ -1515,6 +1524,22 @@ save yourself some time, copy this for undocumented things:
|
||||
Sets multiple vertices at once. The elements of <code>vertices</code> should themselves be tables, of the form provided to <Link class='ActorMultiVertex' function='SetVertex'>SetVertex</Link>. If <code>vertices</code> is the first argument it will start from vertex 1. If an integer is provided before <code>vertices</code> it will start from that vertex. It will add vertices as necessary.
|
||||
Example: self:SetVertices( { { { x1, y1, z1 } , { r1,g1,b1,a1 } , { tcx1,tcy1 } }; { { x2, y2, z2 } , { r2,g2,b2,a2 } , { tcx2,tcy2 } } } )
|
||||
</Function>
|
||||
<Function name='SetVertsFromSplines' return='' arguments=''>
|
||||
Sets all the drawn verts of the ActorMultiVertex by evaluating the splines.<br />
|
||||
("all the drawn verts" means all the verts between FirstToDraw and NumToDraw, the verts that are set to draw in the current tween state.)<br />
|
||||
The parts of the ActorMultiVertex are evenly spaced along the spline in terms of t value.<br />
|
||||
The exact behavior depends on the draw mode.<br />
|
||||
DrawMode_Quads uses all 4 splines, one for each corner.<br />
|
||||
DrawMode_QuadStrip and DrawMode_Strip use 2 splines, one for each edge of the strip.<br />
|
||||
DrawMode_Fan uses one spline, for the edge verts of the fan. The first vert is not touched because it is the center.<br />
|
||||
DrawMode_Triangles uses 3 splines, one for each corner.<br />
|
||||
DrawMode_SymmetricQuadStrip uses 3 splines, one on each edge and one in the center.<br />
|
||||
DrawMode_LineStrip uses 1 spline.<br />
|
||||
</Function>
|
||||
<Function name='GetSpline' return='CubicSplineN' arguments='int i'>
|
||||
Returns the requested spline. Spline indices range from 1 to 4.<br />
|
||||
ActorMultiVertex splines are not inside the tween state, and will not change the verts until you call SetVertsFromSplines.
|
||||
</Function>
|
||||
<Function name='SetNumVertices' return='void' arguments='int num'>
|
||||
Sets the number of vertices.
|
||||
</Function>
|
||||
@@ -2056,6 +2081,92 @@ save yourself some time, copy this for undocumented things:
|
||||
Returns the SHA-1 hash for <code>s</code>.
|
||||
</Function>
|
||||
</Class>
|
||||
<Class name='CubicSplineN'>
|
||||
<Description>
|
||||
All functions in this class have camel case equivalents, use whichever naming style you prefer.<br />
|
||||
This spline implementation is a cubic spline.<br />
|
||||
A spline is a line calculated from a small set of points with mathematical smooting applied.<br />
|
||||
Splines can have any number of dimensions, but splines owned by actors (the ones inside NCSplineHandler and ActorMultiVertex) always have 3 dimensions.<br />
|
||||
</Description>
|
||||
<Function name='solve' return='' arguments=''>
|
||||
Solves the spline, setting the coefficients.
|
||||
</Function>
|
||||
<Function name='evaluate' return='{float}' arguments='float t'>
|
||||
Evaluates the spline at the given t value, returning a table of the results for each dimension of the spline.<br />
|
||||
t can range from 0 to the value returned by get_max_t().<br />
|
||||
A normal spline will return its starting point for any t value less than 0 and its end point for any t value greater than the max.<br />
|
||||
A looped spline adjust the t value to be within the its range by adding or subtracting the max t as needed. (so if the max t is 4 and you evaluate at 5, it will return the same as if you evaluated at 1.)
|
||||
</Function>
|
||||
<Function name='evaluate_derivative' return='{float}' arguments='float t'>
|
||||
Evaluates the derivative at t.
|
||||
</Function>
|
||||
<Function name='evaluate_second_derivative' return='{float}' arguments='float t'>
|
||||
Evaluates the second derivative at t.
|
||||
</Function>
|
||||
<Function name='evaluate_third_derivative' return='{float}' arguments='float t'>
|
||||
Evaluates the third derivative at t.<br />
|
||||
Second and third derivative functions exist because they're possible, not because they're expected to be useful. The fourth derivative would be 0 because the equation for evaluating the spline is "a + (b*t) + (c*t^2) + (d*t^3)".
|
||||
</Function>
|
||||
<Function name='set_point' return='' arguments='int i, {float} p'>
|
||||
Sets point i of the spline to the position specified by the table p.
|
||||
</Function>
|
||||
<Function name='set_coefficients' return= '' arguments='int i, {float} b, {float} c, {float} d'>
|
||||
Sets the coefficients of the spline at point i.<br />
|
||||
Each table must contain a value for each dimension of the spline.<br />
|
||||
Solving the spline normally should cover all normal usage, this is for people that want a spline with an abnormal behavior, so if you set the coefficients directly, expect to end up with an unsmooth shape.
|
||||
</Function>
|
||||
<Function name='get_coefficients' return='{{float}, {float}, {float}}' arguments='int i'>
|
||||
Returns a table containing the tables of coefficients for the point i.
|
||||
</Function>
|
||||
<Function name='set_spatial_extent' return='' arguments='int d, float e'>
|
||||
Sets the spatial extent of dimension d of the spline to e.<br />
|
||||
The spatial extent exists to handle numbers that exist in a finite looped space, instead of the flat infinite space.<br />
|
||||
To put it more concretely, spatial extent exists to allow a spline to control rotation with wrapping behavior at 0.0 and 2pi, instead of suddenly jerking from 2pi to 0.0.
|
||||
</Function>
|
||||
<Function name='get_spatial_extent' return='float' arguments='int d'>
|
||||
Returns the spatial extent of dimension d of the spline.
|
||||
</Function>
|
||||
<Function name='get_max_t' return='float' arguments=''>
|
||||
Returns the max t value the spline extends to. For a normal spline, this will be size()-1. For a looped spline, this will be size().
|
||||
</Function>
|
||||
<Function name='set_size' return='' arguments='int s'>
|
||||
Sets the number of points in the spline. You must set the number of points before trying to set the position of any point.
|
||||
</Function>
|
||||
<Function name='get_size' return='int s' arguments=''>
|
||||
Returns the number of points in the spline.
|
||||
</Function>
|
||||
<Function name='set_dimension' return='' arguments='int d'>
|
||||
Sets the number of dimensions the spline has.<br />
|
||||
Splines that are owned by actors (the ones inside ActorMultiVertex and NCSplineHandler) cannot have their number of dimensions changed because the actors require them to have 3 dimensions.
|
||||
</Function>
|
||||
<Function name='get_dimension' return='int' arguments=''>
|
||||
Returns the number of dimensions the spline has.
|
||||
</Function>
|
||||
<Function name='empty' return='bool' arguments=''>
|
||||
Returns true of the spline has zero points, or false if it has more than zero points.
|
||||
</Function>
|
||||
<Function name='set_loop' return='' arguments='bool'>
|
||||
Sets whether the spline is looped. A looped spline is one where the end point is connected to the start point.
|
||||
</Function>
|
||||
<Function name='get_loop' return='bool' arguments=''>
|
||||
Returns whether the spline is looped.
|
||||
</Function>
|
||||
<Function name='set_polygonal' return='' arguments='bool'>
|
||||
Sets whether the spline is polygonal. If the spline is polygonal, then it will have straight lines between the points instead of curves.
|
||||
</Function>
|
||||
<Function name='get_polygonal' return='bool' arguments=''>
|
||||
Returns whether the spline is polygonal.
|
||||
</Function>
|
||||
<Function name='set_dirty' return='' arguments='bool'>
|
||||
Sets whether the spline is dirty. A dirty spline is one that has been changed in some way that affects its shape. When solve() is called, the spline will only be solved if it is dirty. The dirty flag is automatically set by everything, so you should never have to call this function.
|
||||
</Function>
|
||||
<Function name='get_dirty' return='bool' arguments=''>
|
||||
Returns whether the spline is currently dirty.
|
||||
</Function>
|
||||
<Function name='destroy' return='' arguments=''>
|
||||
Destroys the spline, freeing the memory allocated for it. This can only be called on splines created with create_spline().
|
||||
</Function>
|
||||
</Class>
|
||||
<Class name='DifficultyIcon'>
|
||||
<Function name='SetFromDifficulty' return='void' arguments='Difficulty dc'>
|
||||
Sets the DifficultyIcon's state from the difficulty passed in.
|
||||
@@ -2944,41 +3055,102 @@ save yourself some time, copy this for undocumented things:
|
||||
Returns a table of noteskin names for the current gametype.
|
||||
</Function>
|
||||
</Class>
|
||||
<Class name='NCSplineHandler'>
|
||||
<Description>
|
||||
All functions in this class have camel case equivalents, use whichever naming style you prefer.<br />
|
||||
The spline handler holds info on how the spline is used by the engine.<br />
|
||||
Each get/set pair of functions in this class is for a different aspect of the spline's behavior.
|
||||
</Description>
|
||||
<Function name='get_spline' return='CubicSplineN' arguments=''>
|
||||
Returns the spline for this handler.
|
||||
</Function>
|
||||
<Function name='get_beats_per_t' return='float' arguments=''>
|
||||
Returns the beats per t value of the spline. If the beats_per_t is 4, then a note must be on screen for 4 beats to traverse from one point on the spline to the next.
|
||||
</Function>
|
||||
<Function name='set_beats_per_t' return='' arguments='float per'>
|
||||
Sets the beats per t value for the spline.
|
||||
</Function>
|
||||
<Function name='get_receptor_t' return='float' arguments=''>
|
||||
Returns the t value that receptors are evaluated at.
|
||||
</Function>
|
||||
<Function name='set_receptor_t' return='' arguments='float t'>
|
||||
the t value that receptors are evaluated at.
|
||||
</Function>
|
||||
<Function name='get_spline_mode' return='NoteColumnSplineMode' arguments=''>
|
||||
Returns the mode the spline is set to.<br />
|
||||
"NoteColumnSplineMode_Disabled" means the spline will not affect the notes or receptors at all.<br />
|
||||
"NoteColumnSplineMode_Offset" means the spline will added to the effects from the mods.<br />
|
||||
"NoteColumnSplineMode_Position" means only the spline affect the notes and mods will be ignored. (but only mods that affect the same aspect of the note as the spline will be disabled. So a rotation spline won't disable Mini or Tiny, but a zoom spline will, and a zoom spline won't disable Dizzy, Twirl, or Roll, but a rotation spline will.)
|
||||
</Function>
|
||||
<Function name='set_spline_mode' return='' arguments='NoteColumnSplineMode mode'>
|
||||
Sets the current spline mode for this handler.
|
||||
</Function>
|
||||
<Function name='get_subtract_song_beat' return='bool' arguments=''>
|
||||
Returns whether the current song beat is subtracted from a note's beat when calculating the t value to use on the spline.
|
||||
</Function>
|
||||
<Function name='set_subtract_song_beat' return='' arguments='bool s'>
|
||||
Sets whether the current song beat is subtracted from a note's beat when calculating the t value to use on the spline.
|
||||
</Function>
|
||||
</Class>
|
||||
<Class base='Actor' name='NoteColumnRenderer'>
|
||||
<Description>
|
||||
All functions in this class have camel case equivalents, use whichever naming style you prefer.<br />
|
||||
Position, rotation, and zoom each have separate spline handlers to allow them to have separate independent behavior.<br />
|
||||
It is important to note that the spline handlers are inside the tween state, so whenever you start a new tween on the actor, you need to refetch the spline handlers.<br />
|
||||
</Description>
|
||||
<Function name='get_pos_handler' return='NCSplineHandler' arguments=''>
|
||||
Returns the handler for the position spline.
|
||||
</Function>
|
||||
<Function name='get_rot_handler' return='NCSplineHandler' arguments=''>
|
||||
Returns the handler for the rotation spline.<br />
|
||||
The rotation applied by the rotation spline is in radians.<br />
|
||||
For convenience, the spatial extent of the rotation spline defaults to 2pi.
|
||||
</Function>
|
||||
<Function name='get_zoom_handler' return='NCSplineHandler' arguments=''>
|
||||
Returns the handler for the zoom spline.
|
||||
</Function>
|
||||
</Class>
|
||||
<Class name='NoteField'>
|
||||
<Function name='DidHoldNote' return='' arguments='int column, TapNoteScore tns, bool bright'>
|
||||
<Description>
|
||||
All functions in this class have camel case equivalents, use whichever naming style you prefer.<br />
|
||||
</Description>
|
||||
<Function name='did_hold_note' return='' arguments='int column, TapNoteScore tns, bool bright'>
|
||||
Makes the NoteField act as if a hold note was hit in the column, with the given score and bright setting. <br />
|
||||
The callback for DidHoldNote will not be called.
|
||||
The callback for did_hold_note will not be called.
|
||||
</Function>
|
||||
<Function name='DidTapNote' return='' arguments='int column, TapNoteScore tns, bool bright'>
|
||||
<Function name='did_tap_note' return='' arguments='int column, TapNoteScore tns, bool bright'>
|
||||
Makes the NoteField act as if a tap note was hit in the column, with the given score and bright setting. <br />
|
||||
The callback for DidTapNote will not be called.
|
||||
The callback for did_tap_note will not be called.
|
||||
</Function>
|
||||
<Function name='SetDidHoldNoteCallback' return= '' arguments='function callback'>
|
||||
<Function name='get_column_actors' return='{NoteColumnRenderer}' arguments=''>
|
||||
Returns a table of the actors for the columns. This means that each column is an actor, so you can move it around or animate it like an actor. See the NoteColumnRenderer class for a list of special functions for the column's actor.
|
||||
</Function>
|
||||
<Function name='set_did_hold_note_callback' return= '' arguments='function callback'>
|
||||
Same as SetDidTapNoteCallback, but for hold notes. Uses HoldNoteScore instead of TapNoteScore.
|
||||
</Function>
|
||||
<Function name='SetDidTapNoteCallback' return= '' arguments='function callback'>
|
||||
<Function name='set_did_tap_note_callback' return= '' arguments='function callback'>
|
||||
Sets the function that the NoteField will call whenever a tap note is hit.<br />
|
||||
The callback function is passed the column, the TapNoteScore, and whether the explosion will be bright.<br />
|
||||
The callback function can return changed values for the NoteField to use instead of the ones that were passed.<br />
|
||||
Pass nil instead of a function to clear the callback.
|
||||
</Function>
|
||||
<Function name='SetPressed' return='' arguments='int column'>
|
||||
<Function name='set_pressed' return='' arguments='int column'>
|
||||
Makes the NoteField act as if a press occurred in the column. <br />
|
||||
The callback for SetPressed will not be called.
|
||||
The callback for set_pressed will not be called.
|
||||
</Function>
|
||||
<Function name='SetSetPressedCallback' return= '' arguments='function callback'>
|
||||
<Function name='set_set_pressed_callback' return= '' arguments='function callback'>
|
||||
Sets the function that the NoteField will call whenever a press occurs.<br />
|
||||
The callback function is passed the column for the press.<br />
|
||||
The callback function can return changed values for the NoteField to use instead of the ones that were passed.<br />
|
||||
Pass nil instead of a function to clear the callback.
|
||||
</Function>
|
||||
<Function name='SetStepCallback' return= '' arguments='function callback'>
|
||||
<Function name='set_step_callback' return= '' arguments='function callback'>
|
||||
Sets the function that the NoteField will call whenever a step occurs.<br />
|
||||
The callback function is passed the column and the TapNoteScore for the step.<br />
|
||||
The callback function can return changed values for the NoteField to use instead of the ones that were passed.<br />
|
||||
Pass nil instead of a function to clear the callback.
|
||||
</Function>
|
||||
<Function name='Step' return='' arguments='int column, TapNoteScore tns'>
|
||||
<Function name='step' return='' arguments='int column, TapNoteScore tns'>
|
||||
Makes the NoteField act as if a step occurred in the column with the given score.
|
||||
The callback for Step will not be called.
|
||||
</Function>
|
||||
|
||||
@@ -43,6 +43,30 @@ function math.round(n)
|
||||
end
|
||||
end
|
||||
|
||||
function split(delimiter, text)
|
||||
local list = {}
|
||||
local pos = 1
|
||||
while 1 do
|
||||
local first,last = string.find(text, delimiter, pos)
|
||||
if first then
|
||||
table.insert(list, string.sub(text, pos, first-1))
|
||||
pos = last+1
|
||||
else
|
||||
table.insert(list, string.sub(text, pos))
|
||||
break
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function join(delimiter, list)
|
||||
local ret = list[1]
|
||||
for i = 2,table.getn(list) do
|
||||
ret = ret .. delimiter .. list[i]
|
||||
end
|
||||
return ret or ""
|
||||
end
|
||||
|
||||
-- (c) 2006 Glenn Maynard
|
||||
-- All rights reserved.
|
||||
--
|
||||
|
||||
@@ -24,6 +24,65 @@ _safe = {
|
||||
|
||||
--[[ compatibility aliases ]]
|
||||
|
||||
function alias_one(class, main_name, alt_name)
|
||||
if type(main_name) ~= "string" then
|
||||
lua.ReportScriptError("Name of function to make an alias for must be a string.")
|
||||
return
|
||||
end
|
||||
if type(alt_name) ~= "string" then
|
||||
lua.ReportScriptError("Alias name of function must be a string.")
|
||||
return
|
||||
end
|
||||
if class[alt_name] then return end
|
||||
class[alt_name]= class[main_name]
|
||||
end
|
||||
|
||||
function alias_set(class, set)
|
||||
assert(type(class) == "table" and type(set) == "table",
|
||||
"alias_set must be passed a class and a set of names to make alieases.")
|
||||
for i, fun in ipairs(set) do
|
||||
if type(fun) == "table" then
|
||||
local main_name= fun[1]
|
||||
if type(set[2]) == "table" then
|
||||
for n, alt_name in ipairs(set[2]) do
|
||||
alias_one(class, main_name, alt_name)
|
||||
end
|
||||
elseif type(set[2]) == "string" then
|
||||
alias_one(class, main_name, set[2])
|
||||
end
|
||||
else
|
||||
lua.ReportScriptError("alias entry " .. i .. " in set passed to " ..
|
||||
"alias_set is not a table.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function make_camel_aliases(class)
|
||||
local name_list= {}
|
||||
for name, fun in pairs(class) do
|
||||
if type(fun) == "function" and type(name) == "string" then
|
||||
name_list[#name_list+1]= name
|
||||
end
|
||||
end
|
||||
for i, name in ipairs(name_list) do
|
||||
local words= split("_", name)
|
||||
for o, w in ipairs(words) do
|
||||
words[o]= w:sub(1,1):upper() .. w:sub(2)
|
||||
end
|
||||
local camel_name= join("", words)
|
||||
if name ~= camel_name then
|
||||
alias_one(class, name, camel_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local to_camel_list= {
|
||||
CubicSplineN, NCSplineHandler, NoteColumnRenderer, NoteField}
|
||||
|
||||
for i, class in ipairs(to_camel_list) do
|
||||
make_camel_aliases(class)
|
||||
end
|
||||
|
||||
--[[ ActorScroller: all of these got renamed, so alias the lowercase ones if
|
||||
themes are going to look for them. ]]
|
||||
ActorScroller.getsecondtodestination = ActorScroller.GetSecondsToDestination
|
||||
|
||||
@@ -29,30 +29,6 @@ function TableStringLookup(t, group)
|
||||
return ret
|
||||
end
|
||||
|
||||
function split(delimiter, text)
|
||||
local list = {}
|
||||
local pos = 1
|
||||
while 1 do
|
||||
local first,last = string.find(text, delimiter, pos)
|
||||
if first then
|
||||
table.insert(list, string.sub(text, pos, first-1))
|
||||
pos = last+1
|
||||
else
|
||||
table.insert(list, string.sub(text, pos))
|
||||
break
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
function join(delimiter, list)
|
||||
local ret = list[1]
|
||||
for i = 2,table.getn(list) do
|
||||
ret = ret .. delimiter .. list[i]
|
||||
end
|
||||
return ret or ""
|
||||
end
|
||||
|
||||
function wrap(val,n)
|
||||
local x = val
|
||||
Trace( "wrap "..x.." "..n )
|
||||
|
||||
+64
-2
@@ -164,6 +164,7 @@ Actor::Actor()
|
||||
m_size = RageVector2( 1, 1 );
|
||||
InitState();
|
||||
m_pParent = NULL;
|
||||
m_FakeParent= NULL;
|
||||
m_bFirstUpdate = true;
|
||||
}
|
||||
|
||||
@@ -183,6 +184,7 @@ Actor::Actor( const Actor &cpy ):
|
||||
#define CPY(x) x = cpy.x
|
||||
CPY( m_sName );
|
||||
CPY( m_pParent );
|
||||
CPY( m_FakeParent );
|
||||
CPY( m_pLuaInstance );
|
||||
|
||||
CPY( m_baseRotation );
|
||||
@@ -279,24 +281,56 @@ void Actor::LoadFromNode( const XNode* pNode )
|
||||
PlayCommandNoRecurse( Message("Init") );
|
||||
}
|
||||
|
||||
bool Actor::PartiallyOpaque()
|
||||
{
|
||||
return m_pTempState->diffuse[0].a > 0 || m_pTempState->diffuse[1].a > 0 ||
|
||||
m_pTempState->diffuse[2].a > 0 || m_pTempState->diffuse[3].a > 0 ||
|
||||
m_pTempState->glow.a > 0;
|
||||
}
|
||||
|
||||
void Actor::Draw()
|
||||
{
|
||||
if( !m_bVisible ||
|
||||
m_fHibernateSecondsLeft > 0 ||
|
||||
this->EarlyAbortDraw() )
|
||||
{
|
||||
return; // early abort
|
||||
}
|
||||
bool fake_parent_partially_opaque= true;
|
||||
if(m_FakeParent)
|
||||
{
|
||||
if(!m_FakeParent->m_bVisible || m_FakeParent->m_fHibernateSecondsLeft > 0
|
||||
|| m_FakeParent->EarlyAbortDraw())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_FakeParent->PreDraw();
|
||||
fake_parent_partially_opaque= m_FakeParent->PartiallyOpaque();
|
||||
}
|
||||
|
||||
this->PreDraw();
|
||||
ASSERT( m_pTempState != NULL );
|
||||
if( m_pTempState->diffuse[0].a > 0 || m_pTempState->diffuse[1].a > 0 || m_pTempState->diffuse[2].a > 0 || m_pTempState->diffuse[3].a > 0 || m_pTempState->glow.a > 0 ) // This Actor is not fully transparent
|
||||
{
|
||||
if(PartiallyOpaque() && fake_parent_partially_opaque)
|
||||
{
|
||||
if(m_FakeParent)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
this->PostDraw();
|
||||
if(m_FakeParent)
|
||||
{
|
||||
m_FakeParent->PostDraw();
|
||||
}
|
||||
m_pTempState = NULL;
|
||||
}
|
||||
|
||||
@@ -1705,6 +1739,32 @@ public:
|
||||
pParent->PushSelf(L);
|
||||
return 1;
|
||||
}
|
||||
static int GetFakeParent(T* p, lua_State *L)
|
||||
{
|
||||
Actor* fake= p->GetFakeParent();
|
||||
if(fake == NULL)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
fake->PushSelf(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static int SetFakeParent(T* p, lua_State* L)
|
||||
{
|
||||
if(lua_isnoneornil(L, 1))
|
||||
{
|
||||
p->SetFakeParent(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Actor* fake= Luna<Actor>::check(L, 1);
|
||||
p->SetFakeParent(fake);
|
||||
}
|
||||
COMMON_RETURN_SELF;
|
||||
}
|
||||
static int Draw( T* p, lua_State *L )
|
||||
{
|
||||
LUA->YieldLua();
|
||||
@@ -1876,6 +1936,8 @@ public:
|
||||
|
||||
ADD_METHOD( GetName );
|
||||
ADD_METHOD( GetParent );
|
||||
ADD_METHOD( GetFakeParent );
|
||||
ADD_METHOD( SetFakeParent );
|
||||
|
||||
ADD_METHOD( Draw );
|
||||
}
|
||||
|
||||
@@ -232,6 +232,8 @@ public:
|
||||
float aux;
|
||||
};
|
||||
|
||||
// PartiallyOpaque broken out of Draw for reuse and clarity.
|
||||
bool PartiallyOpaque();
|
||||
/**
|
||||
* @brief Calls multiple functions for drawing the Actors.
|
||||
*
|
||||
@@ -305,6 +307,9 @@ public:
|
||||
* @return the Actor's lineage. */
|
||||
RString GetLineage() const;
|
||||
|
||||
void SetFakeParent(Actor* mailman) { m_FakeParent= mailman; }
|
||||
Actor* GetFakeParent() { return m_FakeParent; }
|
||||
|
||||
/**
|
||||
* @brief Retrieve the Actor's x position.
|
||||
* @return the Actor's x position. */
|
||||
@@ -607,6 +612,10 @@ protected:
|
||||
RString m_sName;
|
||||
/** @brief the current parent of this Actor if it exists. */
|
||||
Actor *m_pParent;
|
||||
// m_FakeParent exists to provide a way to render the actor inside another's
|
||||
// state without making that actor the parent. It's like having multiple
|
||||
// parents. -Kyz
|
||||
Actor* m_FakeParent;
|
||||
|
||||
/** @brief Some general information about the Tween. */
|
||||
struct TweenInfo
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "RageLog.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "RageTexture.h"
|
||||
#include "RageTimer.h"
|
||||
#include "RageUtil.h"
|
||||
#include "ActorUtil.h"
|
||||
#include "Foreach.h"
|
||||
@@ -62,6 +63,12 @@ ActorMultiVertex::ActorMultiVertex()
|
||||
|
||||
_EffectMode = EffectMode_Normal;
|
||||
_TextureMode = TextureMode_Modulate;
|
||||
_splines.resize(num_vert_splines);
|
||||
for(size_t i= 0; i < num_vert_splines; ++i)
|
||||
{
|
||||
_splines[i].redimension(3);
|
||||
_splines[i].m_owned_by_actor= true;
|
||||
}
|
||||
}
|
||||
|
||||
ActorMultiVertex::~ActorMultiVertex()
|
||||
@@ -78,6 +85,7 @@ ActorMultiVertex::ActorMultiVertex( const ActorMultiVertex &cpy ):
|
||||
CPY( AMV_start );
|
||||
CPY( _EffectMode );
|
||||
CPY( _TextureMode );
|
||||
CPY( _splines );
|
||||
#undef CPY
|
||||
|
||||
if( cpy._Texture != NULL )
|
||||
@@ -309,6 +317,61 @@ bool ActorMultiVertex::EarlyAbortDraw() const
|
||||
return false;
|
||||
}
|
||||
|
||||
void ActorMultiVertex::SetVertsFromSplinesInternal(size_t num_splines, size_t offset)
|
||||
{
|
||||
vector<RageSpriteVertex>& verts= AMV_DestTweenState().vertices;
|
||||
size_t first= AMV_DestTweenState().FirstToDraw + offset;
|
||||
size_t num_verts= AMV_DestTweenState().GetSafeNumToDraw(AMV_DestTweenState()._DrawMode, AMV_DestTweenState().NumToDraw) - offset;
|
||||
vector<float> tper(num_splines, 0.0f);
|
||||
float num_parts= static_cast<float>(num_verts) /
|
||||
static_cast<float>(num_splines);
|
||||
for(size_t i= 0; i < num_splines; ++i)
|
||||
{
|
||||
tper[i]= _splines[i].get_max_t() / num_parts;
|
||||
}
|
||||
for(size_t v= 0; v < num_verts; ++v)
|
||||
{
|
||||
vector<float> pos;
|
||||
const int spi= v%num_splines;
|
||||
_splines[spi].evaluate(static_cast<float>(v) * tper[spi], pos);
|
||||
verts[v+first].p.x= pos[0];
|
||||
verts[v+first].p.y= pos[1];
|
||||
verts[v+first].p.z= pos[2];
|
||||
}
|
||||
}
|
||||
|
||||
void ActorMultiVertex::SetVertsFromSplines()
|
||||
{
|
||||
if(AMV_DestTweenState().vertices.empty()) { return; }
|
||||
switch(AMV_DestTweenState()._DrawMode)
|
||||
{
|
||||
case DrawMode_Quads:
|
||||
SetVertsFromSplinesInternal(4, 0);
|
||||
break;
|
||||
case DrawMode_QuadStrip:
|
||||
case DrawMode_Strip:
|
||||
SetVertsFromSplinesInternal(2, 0);
|
||||
break;
|
||||
case DrawMode_Fan:
|
||||
// Skip the first vert because it is the center of the fan. -Kyz
|
||||
SetVertsFromSplinesInternal(1, 1);
|
||||
break;
|
||||
case DrawMode_Triangles:
|
||||
case DrawMode_SymmetricQuadStrip:
|
||||
SetVertsFromSplinesInternal(3, 0);
|
||||
break;
|
||||
case DrawMode_LineStrip:
|
||||
SetVertsFromSplinesInternal(1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CubicSplineN* ActorMultiVertex::GetSpline(size_t i)
|
||||
{
|
||||
ASSERT(i < num_vert_splines);
|
||||
return &(_splines[i]);
|
||||
}
|
||||
|
||||
void ActorMultiVertex::SetCurrentTweenStart()
|
||||
{
|
||||
AMV_start= AMV_current;
|
||||
@@ -638,6 +701,23 @@ public:
|
||||
COMMON_RETURN_SELF;
|
||||
}
|
||||
|
||||
static int GetSpline(T* p, lua_State* L)
|
||||
{
|
||||
size_t i= static_cast<size_t>(IArg(1)-1);
|
||||
if(i >= ActorMultiVertex::num_vert_splines)
|
||||
{
|
||||
luaL_error(L, "Spline index must be greater than 0 and less than or equal to %zu.", ActorMultiVertex::num_vert_splines);
|
||||
}
|
||||
p->GetSpline(i)->PushSelf(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SetVertsFromSplines(T* p, lua_State* L)
|
||||
{
|
||||
p->SetVertsFromSplines();
|
||||
COMMON_RETURN_SELF;
|
||||
}
|
||||
|
||||
static int SetTexture( T* p, lua_State *L )
|
||||
{
|
||||
RageTexture *Texture = Luna<RageTexture>::check(L, 1);
|
||||
@@ -679,6 +759,9 @@ public:
|
||||
ADD_METHOD( GetCurrFirstToDraw );
|
||||
ADD_METHOD( GetCurrNumToDraw );
|
||||
|
||||
ADD_METHOD( GetSpline );
|
||||
ADD_METHOD( SetVertsFromSplines );
|
||||
|
||||
// Copy from RageTexture
|
||||
ADD_METHOD( SetTexture );
|
||||
ADD_METHOD( GetTexture );
|
||||
|
||||
+14
-1
@@ -1,7 +1,9 @@
|
||||
/** @brief ActorMultiVertex - A texture created from multiple textures. */
|
||||
|
||||
#include "Actor.h"
|
||||
#include "CubicSpline.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "RageMath.h"
|
||||
#include "RageTextureID.h"
|
||||
|
||||
enum DrawMode
|
||||
@@ -26,6 +28,7 @@ class RageTexture;
|
||||
class ActorMultiVertex: public Actor
|
||||
{
|
||||
public:
|
||||
static const size_t num_vert_splines= 4;
|
||||
ActorMultiVertex();
|
||||
ActorMultiVertex( const ActorMultiVertex &cpy );
|
||||
virtual ~ActorMultiVertex();
|
||||
@@ -35,7 +38,9 @@ public:
|
||||
|
||||
struct AMV_TweenState
|
||||
{
|
||||
AMV_TweenState(): _DrawMode(DrawMode_Invalid), FirstToDraw(0), NumToDraw(-1), line_width(1.0f) {}
|
||||
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);
|
||||
bool operator==(const AMV_TweenState& other) const;
|
||||
bool operator!=(const AMV_TweenState& other) const { return !operator==(other); }
|
||||
@@ -102,6 +107,10 @@ public:
|
||||
void SetVertexColor( int index , RageColor c );
|
||||
void SetVertexCoords( int index , float TexCoordX , float TexCoordY );
|
||||
|
||||
inline void SetVertsFromSplinesInternal(size_t num_splines, size_t start_vert);
|
||||
void SetVertsFromSplines();
|
||||
CubicSplineN* GetSpline(size_t i);
|
||||
|
||||
virtual void PushSelf( lua_State *L );
|
||||
|
||||
private:
|
||||
@@ -117,6 +126,10 @@ private:
|
||||
|
||||
EffectMode _EffectMode;
|
||||
TextureMode _TextureMode;
|
||||
|
||||
// Four splines for controlling vert positions, because quads drawmode
|
||||
// requires four. -Kyz
|
||||
vector<CubicSplineN> _splines;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,14 @@ public:
|
||||
return GetYOffset( pPlayerState, iCol, fNoteBeat, fThrowAway, bThrowAway, bAbsolute );
|
||||
}
|
||||
|
||||
static void GetXYZPos(const PlayerState* player_state, int col, float y_offset, float y_reverse_offset, vector<float>& ret, bool with_reverse= true)
|
||||
{
|
||||
ASSERT(ret.size() == 3);
|
||||
ret[0]= GetXPos(player_state, col, y_offset);
|
||||
ret[1]= GetYPos(player_state, col, y_offset, y_reverse_offset, with_reverse);
|
||||
ret[2]= GetZPos(player_state, col, y_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the actual display position.
|
||||
*
|
||||
|
||||
+1037
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,111 @@
|
||||
#ifndef CUBIC_SPLINE_H
|
||||
#define CUBIC_SPLINE_H
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
struct lua_State;
|
||||
|
||||
struct CubicSpline
|
||||
{
|
||||
CubicSpline() :m_spatial_extent(0.0f) {}
|
||||
void solve_looped();
|
||||
void solve_straight();
|
||||
void solve_polygonal();
|
||||
void p_and_tfrac_from_t(float t, bool loop, size_t& p, float& tfrac) const;
|
||||
float evaluate(float t, bool loop) const;
|
||||
float evaluate_derivative(float t, bool loop) const;
|
||||
float evaluate_second_derivative(float t, bool loop) const;
|
||||
float evaluate_third_derivative(float t, bool loop) const;
|
||||
void set_point(size_t i, float v);
|
||||
void set_coefficients(size_t i, float b, float c, float d);
|
||||
void get_coefficients(size_t i, float& b, float& c, float& d) const;
|
||||
void set_point_and_coefficients(size_t i, float a, float b, float c, float d);
|
||||
void get_point_and_coefficients(size_t i, float& a, float& b, float& c, float& d) const;
|
||||
void resize(size_t s);
|
||||
size_t size() const;
|
||||
bool empty() const;
|
||||
float m_spatial_extent;
|
||||
private:
|
||||
bool check_minimum_size();
|
||||
void prep_inner(size_t last, vector<float>& results);
|
||||
void set_results(size_t last, vector<float>& diagonals, vector<float>& results);
|
||||
|
||||
struct SplinePoint
|
||||
{
|
||||
float a, b, c, d;
|
||||
};
|
||||
vector<SplinePoint> m_points;
|
||||
};
|
||||
|
||||
struct CubicSplineN
|
||||
{
|
||||
CubicSplineN()
|
||||
:m_owned_by_actor(false), m_loop(false), m_polygonal(false), m_dirty(true)
|
||||
{}
|
||||
static void weighted_average(CubicSplineN& out, const CubicSplineN& from,
|
||||
const CubicSplineN& to, float between);
|
||||
void solve();
|
||||
void evaluate(float t, vector<float>& v) const;
|
||||
void evaluate_derivative(float t, vector<float>& v) const;
|
||||
void evaluate_second_derivative(float t, vector<float>& v) const;
|
||||
void evaluate_third_derivative(float t, vector<float>& v) const;
|
||||
void set_point(size_t i, const vector<float>& v);
|
||||
void set_coefficients(size_t i, const vector<float>& b,
|
||||
const vector<float>& c, const vector<float>& d);
|
||||
void get_coefficients(size_t i, vector<float>& b,
|
||||
vector<float>& c, vector<float>& d);
|
||||
void set_spatial_extent(size_t i, float extent);
|
||||
float get_spatial_extent(size_t i);
|
||||
void resize(size_t s);
|
||||
size_t size() const;
|
||||
void redimension(size_t d);
|
||||
size_t dimension() const;
|
||||
bool empty() const;
|
||||
float get_max_t() const {
|
||||
if(m_loop) { return static_cast<float>(size()); }
|
||||
else { return static_cast<float>(size()-1); }
|
||||
}
|
||||
typedef vector<CubicSpline> spline_cont_t;
|
||||
void set_loop(bool l);
|
||||
bool get_loop() const;
|
||||
void set_polygonal(bool p);
|
||||
bool get_polygonal() const;
|
||||
void set_dirty(bool d);
|
||||
bool get_dirty() const;
|
||||
bool m_owned_by_actor;
|
||||
|
||||
void PushSelf(lua_State* L);
|
||||
private:
|
||||
bool m_loop;
|
||||
bool m_polygonal;
|
||||
bool m_dirty;
|
||||
spline_cont_t m_splines;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// Side note: Actually written between 2014/12/26 and 2014/12/28
|
||||
/*
|
||||
* Copyright (c) 2014-2015 Eric Reese
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
+11
-14
@@ -35,6 +35,16 @@ void GhostArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOffset
|
||||
}
|
||||
}
|
||||
|
||||
void GhostArrowRow::SetColumnRenderers(vector<NoteColumnRenderer>& renderers)
|
||||
{
|
||||
ASSERT_M(renderers.size() == m_Ghost.size(), "Notefield has different number of columns than ghost row.");
|
||||
for(size_t c= 0; c < m_Ghost.size(); ++c)
|
||||
{
|
||||
m_Ghost[c]->SetFakeParent(&(renderers[c]));
|
||||
}
|
||||
m_renderers= &renderers;
|
||||
}
|
||||
|
||||
GhostArrowRow::~GhostArrowRow()
|
||||
{
|
||||
for( unsigned i = 0; i < m_Ghost.size(); ++i )
|
||||
@@ -47,20 +57,7 @@ void GhostArrowRow::Update( float fDeltaTime )
|
||||
for( unsigned c=0; c<m_Ghost.size(); c++ )
|
||||
{
|
||||
m_Ghost[c]->Update( fDeltaTime );
|
||||
|
||||
float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 );
|
||||
float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels );
|
||||
float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 );
|
||||
|
||||
m_Ghost[c]->SetX( fX );
|
||||
m_Ghost[c]->SetY( fY );
|
||||
m_Ghost[c]->SetZ( fZ );
|
||||
|
||||
const float fRotation = ArrowEffects::ReceptorGetRotationZ( m_pPlayerState );
|
||||
m_Ghost[c]->SetRotationZ( fRotation );
|
||||
|
||||
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
|
||||
m_Ghost[c]->SetZoom( fZoom );
|
||||
(*m_renderers)[c].UpdateReceptorGhostStuff(m_Ghost[c]);
|
||||
}
|
||||
|
||||
for( unsigned i = 0; i < m_bHoldShowing.size(); ++i )
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "ActorFrame.h"
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "NoteTypes.h"
|
||||
#include "NoteDisplay.h"
|
||||
|
||||
class PlayerState;
|
||||
/** @brief Row of GhostArrow Actors. */
|
||||
@@ -15,6 +16,7 @@ public:
|
||||
virtual void DrawPrimitives();
|
||||
|
||||
void Load( const PlayerState* pPlayerState, float fYReverseOffset );
|
||||
void SetColumnRenderers(vector<NoteColumnRenderer>& renderers);
|
||||
|
||||
void DidTapNote( int iCol, TapNoteScore tns, bool bBright );
|
||||
void DidHoldNote( int iCol, HoldNoteScore hns, bool bBright );
|
||||
@@ -24,6 +26,7 @@ protected:
|
||||
float m_fYReverseOffsetPixels;
|
||||
const PlayerState* m_pPlayerState;
|
||||
|
||||
vector<NoteColumnRenderer> const* m_renderers;
|
||||
vector<Actor *> m_Ghost;
|
||||
vector<TapNoteSubType> m_bHoldShowing;
|
||||
vector<TapNoteSubType> m_bLastHoldShowing;
|
||||
|
||||
@@ -516,6 +516,7 @@ RageFileDriverSlice.cpp RageFileDriverSlice.h \
|
||||
RageFileDriverTimeout.cpp RageFileDriverTimeout.h
|
||||
|
||||
Rage = $(PCRE) $(Lua) $(jsoncpp) $(RageFile) $(RageSoundFileReaders) \
|
||||
CubicSpline.cpp CubicSpline.h \
|
||||
RageBitmapTexture.cpp RageBitmapTexture.h \
|
||||
RageDisplay.cpp RageDisplay.h \
|
||||
RageDisplay_OGL.cpp RageDisplay_OGL.h \
|
||||
|
||||
+838
-96
File diff suppressed because it is too large
Load Diff
+184
-21
@@ -1,13 +1,17 @@
|
||||
#ifndef NOTE_DISPLAY_H
|
||||
#define NOTE_DISPLAY_H
|
||||
|
||||
#include "ActorFrame.h"
|
||||
#include "CubicSpline.h"
|
||||
#include "NoteData.h"
|
||||
#include "PlayerNumber.h"
|
||||
#include "GameInput.h"
|
||||
|
||||
class Actor;
|
||||
class Sprite;
|
||||
class Model;
|
||||
class PlayerState;
|
||||
class GhostArrowRow;
|
||||
class ReceptorArrowRow;
|
||||
struct TapNote;
|
||||
struct HoldNoteResult;
|
||||
struct NoteMetricCache_t;
|
||||
@@ -83,6 +87,88 @@ enum ActiveType
|
||||
#define FOREACH_ActiveType( i ) FOREACH_ENUM( ActiveType, i )
|
||||
const RString &ActiveTypeToString( ActiveType at );
|
||||
|
||||
enum NoteColumnSplineMode
|
||||
{
|
||||
NCSM_Disabled,
|
||||
NCSM_Offset,
|
||||
NCSM_Position,
|
||||
NUM_NoteColumnSplineMode,
|
||||
NoteColumnSplineMode_Invalid
|
||||
};
|
||||
|
||||
const RString& NoteColumnSplineModeToString(NoteColumnSplineMode ncsm);
|
||||
LuaDeclareType(NoteColumnSplineMode);
|
||||
|
||||
// A little pod struct to carry the data the NoteField needs to pass to the
|
||||
// NoteDisplay during rendering.
|
||||
struct NoteFieldRenderArgs
|
||||
{
|
||||
const PlayerState* player_state; // to look up PlayerOptions
|
||||
float reverse_offset_pixels;
|
||||
ReceptorArrowRow* receptor_row;
|
||||
GhostArrowRow* ghost_row;
|
||||
const NoteData* note_data;
|
||||
float first_beat;
|
||||
float last_beat;
|
||||
int first_row;
|
||||
int last_row;
|
||||
float draw_pixels_before_targets;
|
||||
float draw_pixels_after_targets;
|
||||
int* selection_begin_marker;
|
||||
int* selection_end_marker;
|
||||
float selection_glow;
|
||||
float fail_fade;
|
||||
float fade_before_targets;
|
||||
};
|
||||
|
||||
// NCSplineHandler exists to allow NoteColumnRenderer to have separate
|
||||
// splines for position, rotation, and zoom, while concisely presenting the
|
||||
// same interface for all three.
|
||||
struct NCSplineHandler
|
||||
{
|
||||
NCSplineHandler()
|
||||
{
|
||||
m_spline.redimension(3);
|
||||
m_spline.m_owned_by_actor= true;
|
||||
m_spline_mode= NCSM_Disabled;
|
||||
m_receptor_t= 0.0f;
|
||||
m_beats_per_t= 1.0f;
|
||||
m_subtract_song_beat_from_curr= true;
|
||||
}
|
||||
float BeatToTValue(float song_beat, float note_beat) const;
|
||||
void EvalForBeat(float song_beat, float note_beat, vector<float>& ret) const;
|
||||
void EvalDerivForBeat(float song_beat, float note_beat, vector<float>& ret) const;
|
||||
void EvalForReceptor(float song_beat, vector<float>& ret) const;
|
||||
static void MakeWeightedAverage(NCSplineHandler& out,
|
||||
const NCSplineHandler& from, const NCSplineHandler& to, float between);
|
||||
|
||||
CubicSplineN m_spline;
|
||||
NoteColumnSplineMode m_spline_mode;
|
||||
float m_receptor_t;
|
||||
float m_beats_per_t;
|
||||
bool m_subtract_song_beat_from_curr;
|
||||
|
||||
void PushSelf(lua_State* L);
|
||||
};
|
||||
|
||||
struct NoteColumnRenderArgs
|
||||
{
|
||||
void spae_pos_for_beat(const PlayerState* state,
|
||||
float beat, float y_offset, float y_reverse_offset,
|
||||
vector<float>& sp_pos, vector<float>& ae_pos) const;
|
||||
void spae_zoom_for_beat(const PlayerState* state, float beat,
|
||||
vector<float>& sp_zoom, vector<float>& ae_zoom) const;
|
||||
void SetPRZForActor(Actor* actor,
|
||||
const vector<float>& sp_pos, const vector<float>& ae_pos,
|
||||
const vector<float>& sp_rot, const vector<float>& ae_rot,
|
||||
const vector<float>& sp_zoom, const vector<float>& ae_zoom) const;
|
||||
const NCSplineHandler* pos_handler;
|
||||
const NCSplineHandler* rot_handler;
|
||||
const NCSplineHandler* zoom_handler;
|
||||
float song_beat;
|
||||
int column;
|
||||
};
|
||||
|
||||
/** @brief Draws TapNotes and HoldNotes. */
|
||||
class NoteDisplay
|
||||
{
|
||||
@@ -94,6 +180,14 @@ public:
|
||||
|
||||
static void Update( float fDeltaTime );
|
||||
|
||||
bool IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTargetsPixels, int iDrawDistanceBeforeTargetsPixels ) const;
|
||||
|
||||
bool DrawHoldsInRange(const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args,
|
||||
const vector<NoteData::TrackMap::const_iterator>& tap_set);
|
||||
bool DrawTapsInRange(const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args,
|
||||
const vector<NoteData::TrackMap::const_iterator>& tap_set);
|
||||
/**
|
||||
* @brief Draw the TapNote onto the NoteField.
|
||||
* @param tn the TapNote in question.
|
||||
@@ -107,19 +201,16 @@ public:
|
||||
* @param fDrawDistanceAfterTargetsPixels how much to draw after the receptors.
|
||||
* @param fDrawDistanceBeforeTargetsPixels how much ot draw before the receptors.
|
||||
* @param fFadeInPercentOfDrawFar when to start fading in. */
|
||||
void DrawTap(const TapNote& tn, int iCol, float fBeat,
|
||||
bool bOnSameRowAsHoldStart, bool bOnSameRowAsRollBeat,
|
||||
bool bIsAddition, float fPercentFadeToFail,
|
||||
float fReverseOffsetPixels,
|
||||
float fDrawDistanceAfterTargetsPixels,
|
||||
float fDrawDistanceBeforeTargetsPixels,
|
||||
float fFadeInPercentOfDrawFar );
|
||||
void DrawHold( const TapNote& tn, int iCol, int iRow, bool bIsBeingHeld, const HoldNoteResult &Result,
|
||||
bool bIsAddition, float fPercentFadeToFail, float fReverseOffsetPixels, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels,
|
||||
float fDrawDistanceBeforeTargetsPixels2, float fFadeInPercentOfDrawFar );
|
||||
|
||||
void DrawTap(const TapNote& tn, const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args, float fBeat,
|
||||
bool bOnSameRowAsHoldStart,
|
||||
bool bOnSameRowAsRollBeat, bool bIsAddition, float fPercentFadeToFail);
|
||||
void DrawHold(const TapNote& tn, const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args, int iRow, bool bIsBeingHeld,
|
||||
const HoldNoteResult &Result,
|
||||
bool bIsAddition, float fPercentFadeToFail);
|
||||
|
||||
bool DrawHoldHeadForTapsOnSameRow() const;
|
||||
|
||||
bool DrawRollHeadForTapsOnSameRow() const;
|
||||
|
||||
private:
|
||||
@@ -128,14 +219,23 @@ private:
|
||||
Actor *GetHoldActor( NoteColorActor nca[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld );
|
||||
Sprite *GetHoldSprite( NoteColorSprite ncs[NUM_HoldType][NUM_ActiveType], NotePart part, float fNoteBeat, bool bIsRoll, bool bIsBeingHeld );
|
||||
|
||||
void DrawActor( const TapNote& tn, Actor* pActor, NotePart part, int iCol, float fYOffset, float fBeat, bool bIsAddition, float fPercentFadeToFail,
|
||||
float fReverseOffsetPixels, float fColorScale, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar );
|
||||
void DrawHoldBody( const TapNote& tn, int iCol, float fBeat, bool bIsBeingHeld, float fYHead, float fYTail, bool bIsAddition, float fPercentFadeToFail,
|
||||
float fColorScale,
|
||||
bool bGlow, float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar );
|
||||
void DrawHoldPart( vector<Sprite*> &vpSpr, int iCol, int fYStep, float fPercentFadeToFail, float fColorScale, bool bGlow,
|
||||
float fDrawDistanceAfterTargetsPixels, float fDrawDistanceBeforeTargetsPixels, float fFadeInPercentOfDrawFar, float fOverlappedTime,
|
||||
float fYTop, float fYBottom, float fYStartPos, float fYEndPos, bool bWrapping, bool bAnchorToTop, bool bFlipTextureVertically );
|
||||
void DrawActor(const TapNote& tn, Actor* pActor, NotePart part,
|
||||
const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args, float fYOffset, float fBeat,
|
||||
bool bIsAddition, float fPercentFadeToFail, float fColorScale,
|
||||
bool is_being_held);
|
||||
void DrawHoldBody(const TapNote& tn, const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args, float fBeat, bool bIsBeingHeld,
|
||||
float fYHead, float fYTail,
|
||||
bool bIsAddition, float fPercentFadeToFail, float fColorScale,
|
||||
bool bGlow, float top_beat, float bottom_beat);
|
||||
void DrawHoldPart(vector<Sprite*> &vpSpr,
|
||||
const NoteFieldRenderArgs& field_args,
|
||||
const NoteColumnRenderArgs& column_args, int fYStep,
|
||||
float fPercentFadeToFail, float fColorScale, bool bGlow,
|
||||
float fOverlappedTime, float fYTop, float fYBottom, float fYStartPos,
|
||||
float fYEndPos, bool bWrapping, bool bAnchorToTop,
|
||||
bool bFlipTextureVertically, float top_beat, float bottom_beat);
|
||||
|
||||
const PlayerState *m_pPlayerState; // to look up PlayerOptions
|
||||
NoteMetricCache_t *cache;
|
||||
@@ -152,9 +252,72 @@ private:
|
||||
float m_fYReverseOffsetPixels;
|
||||
};
|
||||
|
||||
// So, this is a bit screwy, and it's partly because routine forces rendering
|
||||
// notes from different noteskins in the same column.
|
||||
// NoteColumnRenderer exists to hold all the data needed for rendering a
|
||||
// column and apply any transforms from that column's actor to the
|
||||
// NoteDisplays that render the notes.
|
||||
// NoteColumnRenderer is also used as a fake parent for the receptor and ghost
|
||||
// actors so they can move with the rest of the column. I didn't use
|
||||
// ActorProxy because the receptor/ghost actors need to pull in the parent
|
||||
// state of their rows and the parent state of the column. -Kyz
|
||||
|
||||
struct NoteColumnRenderer : public Actor
|
||||
{
|
||||
NoteDisplay* m_displays[PLAYER_INVALID+1];
|
||||
NoteFieldRenderArgs* m_field_render_args;
|
||||
NoteColumnRenderArgs m_column_render_args;
|
||||
int m_column;
|
||||
|
||||
// UpdateReceptorGhostStuff takes care of the logic for making the ghost
|
||||
// and receptor positions follow the splines. It's called by their row
|
||||
// update functions. -Kyz
|
||||
void UpdateReceptorGhostStuff(Actor* receptor) const;
|
||||
virtual void DrawPrimitives();
|
||||
virtual void PushSelf(lua_State* L);
|
||||
|
||||
struct NCR_TweenState
|
||||
{
|
||||
NCR_TweenState();
|
||||
NCSplineHandler m_pos_handler;
|
||||
NCSplineHandler m_rot_handler;
|
||||
NCSplineHandler m_zoom_handler;
|
||||
static void MakeWeightedAverage(NCR_TweenState& out,
|
||||
const NCR_TweenState& from, const NCR_TweenState& to, float between);
|
||||
bool operator==(const NCR_TweenState& other) const;
|
||||
bool operator!=(const NCR_TweenState& other) const { return !operator==(other); }
|
||||
};
|
||||
|
||||
NCR_TweenState& NCR_DestTweenState()
|
||||
{
|
||||
if(NCR_Tweens.empty())
|
||||
{ return NCR_current; }
|
||||
else
|
||||
{ return NCR_Tweens.back(); }
|
||||
}
|
||||
const NCR_TweenState& NCR_DestTweenState() const { return const_cast<NoteColumnRenderer*>(this)->NCR_DestTweenState(); }
|
||||
|
||||
virtual void SetCurrentTweenStart();
|
||||
virtual void EraseHeadTween();
|
||||
virtual void UpdatePercentThroughTween(float between);
|
||||
virtual void BeginTweening(float time, ITween* interp);
|
||||
virtual void StopTweening();
|
||||
virtual void FinishTweening();
|
||||
|
||||
NCSplineHandler* GetPosHandler() { return &NCR_DestTweenState().m_pos_handler; }
|
||||
NCSplineHandler* GetRotHandler() { return &NCR_DestTweenState().m_rot_handler; }
|
||||
NCSplineHandler* GetZoomHandler() { return &NCR_DestTweenState().m_zoom_handler; }
|
||||
|
||||
private:
|
||||
vector<NCR_TweenState> NCR_Tweens;
|
||||
NCR_TweenState NCR_current;
|
||||
NCR_TweenState NCR_start;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* NoteColumnRenderer and associated spline stuff (c) Eric Reese 2014-2015
|
||||
* @file
|
||||
* @author Brian Bugh, Ben Nordstrom, Chris Danford, Steve Checkoway (c) 2001-2006
|
||||
* @section LICENSE
|
||||
|
||||
+111
-225
@@ -36,11 +36,8 @@ static ThemeMetric<float> FADE_FAIL_TIME( "NoteField", "FadeFailTime" );
|
||||
static RString RoutineNoteSkinName( size_t i ) { return ssprintf("RoutineNoteSkinP%i",int(i+1)); }
|
||||
static ThemeMetric1D<RString> ROUTINE_NOTESKIN( "NoteField", RoutineNoteSkinName, NUM_PLAYERS );
|
||||
|
||||
static bool FAST_NOTE_RENDERING_PREF_CACHED= false;
|
||||
|
||||
NoteField::NoteField()
|
||||
{
|
||||
FAST_NOTE_RENDERING_PREF_CACHED= PREFSMAN->m_FastNoteRendering;
|
||||
m_pNoteData = NULL;
|
||||
m_pCurDisplay = NULL;
|
||||
|
||||
@@ -64,9 +61,13 @@ NoteField::NoteField()
|
||||
m_sprBeatBars.Load( THEME->GetPathG("NoteField","bars") );
|
||||
m_sprBeatBars.StopAnimating();
|
||||
|
||||
// I decided to do it this way because I don't want to dig through
|
||||
// ScreenEdit to change all the places it touches the markers. -Kyz
|
||||
m_FieldRenderArgs.selection_begin_marker= &m_iBeginMarker;
|
||||
m_FieldRenderArgs.selection_end_marker= &m_iEndMarker;
|
||||
m_iBeginMarker = m_iEndMarker = -1;
|
||||
|
||||
m_fPercentFadeToFail = -1;
|
||||
m_FieldRenderArgs.fail_fade = -1;
|
||||
|
||||
m_StepCallback.SetFromNil();
|
||||
m_SetPressedCallback.SetFromNil();
|
||||
@@ -169,6 +170,8 @@ void NoteField::CacheAllUsedNoteSkins()
|
||||
ASSERT_M( it != m_NoteDisplays.end(), sNoteSkinLower );
|
||||
m_pDisplays[pn] = it->second;
|
||||
}
|
||||
|
||||
InitColumnRenderers();
|
||||
}
|
||||
|
||||
void NoteField::Init( const PlayerState* pPlayerState, float fYReverseOffsetPixels )
|
||||
@@ -189,7 +192,7 @@ void NoteField::Load(
|
||||
m_iDrawDistanceBeforeTargetsPixels = iDrawDistanceBeforeTargetsPixels;
|
||||
ASSERT( m_iDrawDistanceBeforeTargetsPixels >= m_iDrawDistanceAfterTargetsPixels );
|
||||
|
||||
m_fPercentFadeToFail = -1;
|
||||
m_FieldRenderArgs.fail_fade = -1;
|
||||
|
||||
//int i1 = m_pNoteData->GetNumTracks();
|
||||
//int i2 = GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer;
|
||||
@@ -240,6 +243,30 @@ void NoteField::Load(
|
||||
ASSERT_M( it != m_NoteDisplays.end(), sNoteSkinLower );
|
||||
m_pDisplays[pn] = it->second;
|
||||
}
|
||||
InitColumnRenderers();
|
||||
}
|
||||
|
||||
void NoteField::InitColumnRenderers()
|
||||
{
|
||||
m_FieldRenderArgs.player_state= m_pPlayerState;
|
||||
m_FieldRenderArgs.reverse_offset_pixels= m_fYReverseOffsetPixels;
|
||||
m_FieldRenderArgs.receptor_row= &(m_pCurDisplay->m_ReceptorArrowRow);
|
||||
m_FieldRenderArgs.ghost_row= &(m_pCurDisplay->m_GhostArrowRow);
|
||||
m_FieldRenderArgs.note_data= m_pNoteData;
|
||||
m_ColumnRenderers.resize(GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer);
|
||||
for(size_t ncr= 0; ncr < m_ColumnRenderers.size(); ++ncr)
|
||||
{
|
||||
FOREACH_EnabledPlayer(pn)
|
||||
{
|
||||
m_ColumnRenderers[ncr].m_displays[pn]= &(m_pDisplays[pn]->display[ncr]);
|
||||
}
|
||||
m_ColumnRenderers[ncr].m_displays[PLAYER_INVALID]= &(m_pCurDisplay->display[ncr]);
|
||||
m_ColumnRenderers[ncr].m_column= ncr;
|
||||
m_ColumnRenderers[ncr].m_column_render_args.column= ncr;
|
||||
m_ColumnRenderers[ncr].m_field_render_args= &m_FieldRenderArgs;
|
||||
}
|
||||
m_pCurDisplay->m_ReceptorArrowRow.SetColumnRenderers(m_ColumnRenderers);
|
||||
m_pCurDisplay->m_GhostArrowRow.SetColumnRenderers(m_ColumnRenderers);
|
||||
}
|
||||
|
||||
void NoteField::Update( float fDeltaTime )
|
||||
@@ -251,6 +278,11 @@ void NoteField::Update( float fDeltaTime )
|
||||
|
||||
ActorFrame::Update( fDeltaTime );
|
||||
|
||||
for(size_t c= 0; c < m_ColumnRenderers.size(); ++c)
|
||||
{
|
||||
m_ColumnRenderers[c].Update(fDeltaTime);
|
||||
}
|
||||
|
||||
// update m_fBoardOffsetPixels, m_fCurrentBeatLastUpdate, m_fYPosCurrentBeatLastUpdate
|
||||
const float fCurrentBeat = m_pPlayerState->GetDisplayedPosition().m_fSongBeat;
|
||||
bool bTweeningOn = m_sprBoard->GetCurrentDiffuseAlpha() >= 0.98 && m_sprBoard->GetCurrentDiffuseAlpha() < 1.00; // HACK
|
||||
@@ -276,11 +308,11 @@ void NoteField::Update( float fDeltaTime )
|
||||
cur->m_ReceptorArrowRow.Update( fDeltaTime );
|
||||
cur->m_GhostArrowRow.Update( fDeltaTime );
|
||||
|
||||
if( m_fPercentFadeToFail >= 0 )
|
||||
m_fPercentFadeToFail = min( m_fPercentFadeToFail + fDeltaTime/FADE_FAIL_TIME, 1 );
|
||||
if( m_FieldRenderArgs.fail_fade >= 0 )
|
||||
m_FieldRenderArgs.fail_fade = min( m_FieldRenderArgs.fail_fade + fDeltaTime/FADE_FAIL_TIME, 1 );
|
||||
|
||||
// Update fade to failed
|
||||
m_pCurDisplay->m_ReceptorArrowRow.SetFadeToFailPercent( m_fPercentFadeToFail );
|
||||
m_pCurDisplay->m_ReceptorArrowRow.SetFadeToFailPercent( m_FieldRenderArgs.fail_fade );
|
||||
|
||||
NoteDisplay::Update( fDeltaTime );
|
||||
/* Update all NoteDisplays. Hack: We need to call this once per frame, not
|
||||
@@ -801,13 +833,11 @@ float FindLastDisplayedBeat( const PlayerState* pPlayerState, int iDrawDistanceB
|
||||
return fLastBeatToDraw;
|
||||
}
|
||||
|
||||
inline float NoteRowToVisibleBeat( const PlayerState *pPlayerState, int iRow )
|
||||
{
|
||||
return NoteRowToBeat(iRow);
|
||||
}
|
||||
|
||||
bool NoteField::IsOnScreen( float fBeat, int iCol, int iDrawDistanceAfterTargetsPixels, int iDrawDistanceBeforeTargetsPixels ) const
|
||||
{
|
||||
// IMPORTANT: Do not modify this function without also modifying the
|
||||
// version that is in NoteDisplay.cpp or coming up with a good way to
|
||||
// merge them. -Kyz
|
||||
// TRICKY: If boomerang is on, then ones in the range
|
||||
// [iFirstRowToDraw,iLastRowToDraw] aren't necessarily visible.
|
||||
// Test to see if this beat is visible before drawing.
|
||||
@@ -834,41 +864,41 @@ void NoteField::DrawPrimitives()
|
||||
const PlayerOptions ¤t_po = m_pPlayerState->m_PlayerOptions.GetCurrent();
|
||||
|
||||
// Adjust draw range depending on some effects
|
||||
int iDrawDistanceAfterTargetsPixels = m_iDrawDistanceAfterTargetsPixels;
|
||||
m_FieldRenderArgs.draw_pixels_after_targets= m_iDrawDistanceAfterTargetsPixels;
|
||||
// HACK: If boomerang and centered are on, then we want to draw much
|
||||
// earlier so that the notes don't pop on screen.
|
||||
float fCenteredTimesBoomerang =
|
||||
current_po.m_fScrolls[PlayerOptions::SCROLL_CENTERED] *
|
||||
current_po.m_fAccels[PlayerOptions::ACCEL_BOOMERANG];
|
||||
iDrawDistanceAfterTargetsPixels += int(SCALE( fCenteredTimesBoomerang, 0.f, 1.f, 0.f, -SCREEN_HEIGHT/2 ));
|
||||
int iDrawDistanceBeforeTargetsPixels = m_iDrawDistanceBeforeTargetsPixels;
|
||||
m_FieldRenderArgs.draw_pixels_after_targets += int(SCALE( fCenteredTimesBoomerang, 0.f, 1.f, 0.f, -SCREEN_HEIGHT/2 ));
|
||||
m_FieldRenderArgs.draw_pixels_before_targets = m_iDrawDistanceBeforeTargetsPixels;
|
||||
|
||||
float fDrawScale = 1;
|
||||
fDrawScale *= 1 + 0.5f * fabsf( current_po.m_fPerspectiveTilt );
|
||||
fDrawScale *= 1 + fabsf( current_po.m_fEffects[PlayerOptions::EFFECT_MINI] );
|
||||
|
||||
iDrawDistanceAfterTargetsPixels = (int)(iDrawDistanceAfterTargetsPixels * fDrawScale);
|
||||
iDrawDistanceBeforeTargetsPixels = (int)(iDrawDistanceBeforeTargetsPixels * fDrawScale);
|
||||
m_FieldRenderArgs.draw_pixels_after_targets = (int)(m_FieldRenderArgs.draw_pixels_after_targets * fDrawScale);
|
||||
m_FieldRenderArgs.draw_pixels_before_targets = (int)(m_FieldRenderArgs.draw_pixels_before_targets * fDrawScale);
|
||||
|
||||
|
||||
// Probe for first and last notes on the screen
|
||||
float fFirstBeatToDraw = FindFirstDisplayedBeat( m_pPlayerState, iDrawDistanceAfterTargetsPixels );
|
||||
float fLastBeatToDraw = FindLastDisplayedBeat( m_pPlayerState, iDrawDistanceBeforeTargetsPixels );
|
||||
float fFirstBeatToDraw = FindFirstDisplayedBeat( m_pPlayerState, m_FieldRenderArgs.draw_pixels_after_targets );
|
||||
float fLastBeatToDraw = FindLastDisplayedBeat( m_pPlayerState, m_FieldRenderArgs.draw_pixels_before_targets );
|
||||
|
||||
m_pPlayerState->m_fLastDrawnBeat = fLastBeatToDraw;
|
||||
|
||||
const int iFirstRowToDraw = BeatToNoteRow(fFirstBeatToDraw);
|
||||
const int iLastRowToDraw = BeatToNoteRow(fLastBeatToDraw);
|
||||
m_FieldRenderArgs.first_row = BeatToNoteRow(fFirstBeatToDraw);
|
||||
m_FieldRenderArgs.last_row = BeatToNoteRow(fLastBeatToDraw);
|
||||
|
||||
//LOG->Trace( "start = %f.1, end = %f.1", fFirstBeatToDraw-fSongBeat, fLastBeatToDraw-fSongBeat );
|
||||
//LOG->Trace( "Drawing elements %d through %d", iFirstRowToDraw, iLastRowToDraw );
|
||||
//LOG->Trace( "Drawing elements %d through %d", m_FieldRenderArgs.first_row, m_FieldRenderArgs.last_row );
|
||||
|
||||
#define IS_ON_SCREEN( fBeat ) ( fFirstBeatToDraw <= (fBeat) && (fBeat) <= fLastBeatToDraw && IsOnScreen( fBeat, 0, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) )
|
||||
#define IS_ON_SCREEN( fBeat ) ( fFirstBeatToDraw <= (fBeat) && (fBeat) <= fLastBeatToDraw && IsOnScreen( fBeat, 0, m_FieldRenderArgs.draw_pixels_after_targets, m_FieldRenderArgs.draw_pixels_before_targets ) )
|
||||
|
||||
// Draw board
|
||||
if( SHOW_BOARD )
|
||||
{
|
||||
DrawBoard( iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels );
|
||||
DrawBoard( m_FieldRenderArgs.draw_pixels_after_targets, m_FieldRenderArgs.draw_pixels_before_targets );
|
||||
}
|
||||
|
||||
// Draw Receptors
|
||||
@@ -891,7 +921,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < tSigs.size(); i++)
|
||||
{
|
||||
const TimeSignatureSegment *ts = ToTimeSignature(tSigs[i]);
|
||||
int iSegmentEndRow = (i + 1 == tSigs.size()) ? iLastRowToDraw : tSigs[i+1]->GetRow();
|
||||
int iSegmentEndRow = (i + 1 == tSigs.size()) ? m_FieldRenderArgs.last_row : tSigs[i+1]->GetRow();
|
||||
|
||||
// beat bars every 16th note
|
||||
int iDrawBeatBarsEveryRows = BeatToNoteRow( ((float)ts->GetDen()) / 4 ) / 4;
|
||||
@@ -934,7 +964,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_SCROLL]->size(); i++)
|
||||
{
|
||||
ScrollSegment *seg = ToScroll( segs[SEGMENT_SCROLL]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -946,7 +976,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_BPM]->size(); i++)
|
||||
{
|
||||
const BPMSegment *seg = ToBPM( segs[SEGMENT_BPM]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -958,7 +988,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_STOP]->size(); i++)
|
||||
{
|
||||
const StopSegment *seg = ToStop( segs[SEGMENT_STOP]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -970,7 +1000,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_DELAY]->size(); i++)
|
||||
{
|
||||
const DelaySegment *seg = ToDelay( segs[SEGMENT_DELAY]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -982,7 +1012,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_WARP]->size(); i++)
|
||||
{
|
||||
const WarpSegment *seg = ToWarp( segs[SEGMENT_WARP]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -994,7 +1024,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_TIME_SIG]->size(); i++)
|
||||
{
|
||||
const TimeSignatureSegment *seg = ToTimeSignature( segs[SEGMENT_TIME_SIG]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -1006,7 +1036,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_TICKCOUNT]->size(); i++)
|
||||
{
|
||||
const TickcountSegment *seg = ToTickcount( segs[SEGMENT_TICKCOUNT]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -1018,7 +1048,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_COMBO]->size(); i++)
|
||||
{
|
||||
const ComboSegment *seg = ToCombo( segs[SEGMENT_COMBO]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -1030,7 +1060,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_LABEL]->size(); i++)
|
||||
{
|
||||
const LabelSegment *seg = ToLabel( segs[SEGMENT_LABEL]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -1042,7 +1072,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_SPEED]->size(); i++)
|
||||
{
|
||||
const SpeedSegment *seg = ToSpeed( segs[SEGMENT_SPEED]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -1055,7 +1085,7 @@ void NoteField::DrawPrimitives()
|
||||
for (i = 0; i < segs[SEGMENT_FAKE]->size(); i++)
|
||||
{
|
||||
const FakeSegment *seg = ToFake( segs[SEGMENT_FAKE]->at(i) );
|
||||
if( seg->GetRow() >= iFirstRowToDraw && seg->GetRow() <= iLastRowToDraw )
|
||||
if( seg->GetRow() >= m_FieldRenderArgs.first_row && seg->GetRow() <= m_FieldRenderArgs.last_row )
|
||||
{
|
||||
float fBeat = seg->GetBeat();
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
@@ -1075,8 +1105,8 @@ void NoteField::DrawPrimitives()
|
||||
float fSecond = a->fStartSecond;
|
||||
float fBeat = timing.GetBeatFromElapsedTime( fSecond );
|
||||
|
||||
if( BeatToNoteRow(fBeat) >= iFirstRowToDraw &&
|
||||
BeatToNoteRow(fBeat) <= iLastRowToDraw)
|
||||
if( BeatToNoteRow(fBeat) >= m_FieldRenderArgs.first_row &&
|
||||
BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row)
|
||||
{
|
||||
if( IS_ON_SCREEN(fBeat) )
|
||||
DrawAttackText( fBeat, *a );
|
||||
@@ -1094,8 +1124,8 @@ void NoteField::DrawPrimitives()
|
||||
FOREACH_CONST(Attack, attacks, a)
|
||||
{
|
||||
float fBeat = timing.GetBeatFromElapsedTime(a->fStartSecond);
|
||||
if (BeatToNoteRow(fBeat) >= iFirstRowToDraw &&
|
||||
BeatToNoteRow(fBeat) <= iLastRowToDraw &&
|
||||
if (BeatToNoteRow(fBeat) >= m_FieldRenderArgs.first_row &&
|
||||
BeatToNoteRow(fBeat) <= m_FieldRenderArgs.last_row &&
|
||||
IS_ON_SCREEN(fBeat))
|
||||
{
|
||||
this->DrawAttackText(fBeat, *a);
|
||||
@@ -1179,20 +1209,20 @@ void NoteField::DrawPrimitives()
|
||||
{
|
||||
int iBegin = m_iBeginMarker;
|
||||
int iEnd = m_iEndMarker;
|
||||
CLAMP( iBegin, iFirstRowToDraw, iLastRowToDraw );
|
||||
CLAMP( iEnd, iFirstRowToDraw, iLastRowToDraw );
|
||||
CLAMP( iBegin, m_FieldRenderArgs.first_row, m_FieldRenderArgs.last_row );
|
||||
CLAMP( iEnd, m_FieldRenderArgs.first_row, m_FieldRenderArgs.last_row );
|
||||
DrawAreaHighlight( iBegin, iEnd );
|
||||
}
|
||||
else if( m_iBeginMarker != -1 )
|
||||
{
|
||||
if( m_iBeginMarker >= iFirstRowToDraw &&
|
||||
m_iBeginMarker <= iLastRowToDraw )
|
||||
if( m_iBeginMarker >= m_FieldRenderArgs.first_row &&
|
||||
m_iBeginMarker <= m_FieldRenderArgs.last_row )
|
||||
DrawMarkerBar( m_iBeginMarker );
|
||||
}
|
||||
else if( m_iEndMarker != -1 )
|
||||
{
|
||||
if( m_iEndMarker >= iFirstRowToDraw &&
|
||||
m_iEndMarker <= iLastRowToDraw )
|
||||
if( m_iEndMarker >= m_FieldRenderArgs.first_row &&
|
||||
m_iEndMarker <= m_FieldRenderArgs.last_row )
|
||||
DrawMarkerBar( m_iEndMarker );
|
||||
}
|
||||
}
|
||||
@@ -1201,175 +1231,19 @@ void NoteField::DrawPrimitives()
|
||||
// Draw the arrows in order of column. This minimizes texture switches and
|
||||
// lets us draw in big batches.
|
||||
|
||||
float fSelectedRangeGlow = SCALE( RageFastCos(RageTimer::GetTimeSinceStartFast()*2), -1, 1, 0.1f, 0.3f );
|
||||
|
||||
const Style* pStyle = GAMESTATE->GetCurrentStyle();
|
||||
ASSERT_M(m_pNoteData->GetNumTracks() == GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer,
|
||||
ssprintf("NumTracks %d != ColsPerPlayer %d",m_pNoteData->GetNumTracks(),
|
||||
GAMESTATE->GetCurrentStyle()->m_iColsPerPlayer));
|
||||
|
||||
m_FieldRenderArgs.selection_glow= SCALE(
|
||||
RageFastCos(RageTimer::GetTimeSinceStartFast()*2), -1, 1, 0.1f, 0.3f);
|
||||
m_FieldRenderArgs.fade_before_targets= FADE_BEFORE_TARGETS_PERCENT;
|
||||
|
||||
for( int j=0; j<m_pNoteData->GetNumTracks(); j++ ) // for each arrow column
|
||||
{
|
||||
const int c = pStyle->m_iColumnDrawOrder[j];
|
||||
|
||||
bool bAnyUpcomingInThisCol = false;
|
||||
|
||||
// Draw all HoldNotes in this column (so that they appear under the tap notes)
|
||||
{
|
||||
NoteData::TrackMap::const_iterator begin, end;
|
||||
m_pNoteData->GetTapNoteRangeInclusive( c, iFirstRowToDraw, iLastRowToDraw+1, begin, end );
|
||||
|
||||
for( ; begin != end; ++begin )
|
||||
{
|
||||
const TapNote &tn = begin->second; //m_pNoteData->GetTapNote(c, j);
|
||||
if( tn.type != TapNoteType_HoldHead )
|
||||
continue; // skip
|
||||
|
||||
const HoldNoteResult &Result = tn.HoldResult;
|
||||
if( Result.hns == HNS_Held ) // if this HoldNote was completed
|
||||
continue; // don't draw anything
|
||||
|
||||
int iStartRow = begin->first;
|
||||
int iEndRow = iStartRow + tn.iDuration;
|
||||
|
||||
// TRICKY: If boomerang is on, then all notes in the range
|
||||
// [iFirstRowToDraw,iLastRowToDraw] aren't necessarily visible.
|
||||
// Test every note to make sure it's on screen before drawing
|
||||
float fThrowAway;
|
||||
bool bStartIsPastPeak = false;
|
||||
bool bEndIsPastPeak = false;
|
||||
float fStartYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToVisibleBeat(m_pPlayerState, iStartRow), fThrowAway, bStartIsPastPeak );
|
||||
float fEndYOffset = ArrowEffects::GetYOffset( m_pPlayerState, c, NoteRowToVisibleBeat(m_pPlayerState, iEndRow), fThrowAway, bEndIsPastPeak );
|
||||
|
||||
bool bTailIsOnVisible = iDrawDistanceAfterTargetsPixels <= fEndYOffset && fEndYOffset <= iDrawDistanceBeforeTargetsPixels;
|
||||
bool bHeadIsVisible = iDrawDistanceAfterTargetsPixels <= fStartYOffset && fStartYOffset <= iDrawDistanceBeforeTargetsPixels;
|
||||
bool bStraddlingVisible = fStartYOffset <= iDrawDistanceAfterTargetsPixels && iDrawDistanceBeforeTargetsPixels <= fEndYOffset;
|
||||
bool bStaddlingPeak = bStartIsPastPeak && !bEndIsPastPeak;
|
||||
if( !(bTailIsOnVisible || bHeadIsVisible || bStraddlingVisible || bStaddlingPeak) )
|
||||
{
|
||||
//LOG->Trace( "skip drawing this hold." );
|
||||
continue; // skip
|
||||
}
|
||||
|
||||
bool bIsAddition = (tn.source == TapNoteSource_Addition);
|
||||
bool bIsHopoPossible = (tn.bHopoPossible);
|
||||
bool bUseAdditionColoring = bIsAddition || bIsHopoPossible;
|
||||
const bool bHoldGhostShowing = tn.HoldResult.bActive && tn.HoldResult.fLife > 0;
|
||||
const bool bIsHoldingNote = tn.HoldResult.bHeld;
|
||||
if( bHoldGhostShowing )
|
||||
m_pCurDisplay->m_GhostArrowRow.SetHoldShowing( c, tn );
|
||||
|
||||
ASSERT_M( NoteRowToBeat(iStartRow) > -2000, ssprintf("%i %i %i", iStartRow, iEndRow, c) );
|
||||
|
||||
bool bIsInSelectionRange = false;
|
||||
if( m_iBeginMarker!=-1 && m_iEndMarker!=-1 )
|
||||
bIsInSelectionRange = (m_iBeginMarker <= iStartRow && iEndRow < m_iEndMarker);
|
||||
|
||||
NoteDisplayCols *displayCols = tn.pn == PLAYER_INVALID ? m_pCurDisplay : m_pDisplays[tn.pn];
|
||||
displayCols->display[c].DrawHold( tn, c, iStartRow, bIsHoldingNote, Result, bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail,
|
||||
m_fYReverseOffsetPixels, (float) iDrawDistanceAfterTargetsPixels, (float) iDrawDistanceBeforeTargetsPixels, iDrawDistanceBeforeTargetsPixels, FADE_BEFORE_TARGETS_PERCENT );
|
||||
|
||||
bool bNoteIsUpcoming = NoteRowToBeat(iStartRow) > m_pPlayerState->GetDisplayedPosition().m_fSongBeat;
|
||||
bAnyUpcomingInThisCol |= bNoteIsUpcoming;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw all TapNotes in this column
|
||||
|
||||
// draw notes from furthest to closest
|
||||
NoteData::TrackMap::const_iterator begin, end;
|
||||
m_pNoteData->GetTapNoteRange( c, iFirstRowToDraw, iLastRowToDraw+1, begin, end );
|
||||
for( ; begin != end; ++begin )
|
||||
{
|
||||
int q = begin->first;
|
||||
const TapNote &tn = begin->second; //m_pNoteData->GetTapNote(c, q);
|
||||
|
||||
// Switch modified by Wolfman2000, tested by Saturn2888
|
||||
// Fixes hold head overlapping issue, but not the rolls.
|
||||
switch( tn.type )
|
||||
{
|
||||
case TapNoteType_Empty: // no note here
|
||||
{
|
||||
continue;
|
||||
}
|
||||
case TapNoteType_HoldHead:
|
||||
{
|
||||
//if (tn.subType == TapNoteSubType_Roll)
|
||||
continue; // skip
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Don't draw hidden (fully judged) steps.
|
||||
if( tn.result.bHidden )
|
||||
continue;
|
||||
|
||||
// TRICKY: If boomerang is on, then all notes in the range
|
||||
// [iFirstRowToDraw,iLastRowToDraw] aren't necessarily visible.
|
||||
// Test every note to make sure it's on screen before drawing.
|
||||
if( !IsOnScreen( NoteRowToBeat(q), c, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels ) )
|
||||
continue; // skip
|
||||
|
||||
ASSERT_M( NoteRowToBeat(q) > -2000, ssprintf("%i %i %i, %f %f", q, iLastRowToDraw,
|
||||
iFirstRowToDraw, m_pPlayerState->GetDisplayedPosition().m_fSongBeat, m_pPlayerState->GetDisplayedPosition().m_fMusicSeconds) );
|
||||
|
||||
// See if there is a hold step that begins on this index.
|
||||
// Only do this if the noteskin cares.
|
||||
bool bHoldNoteBeginsOnThisBeat = false;
|
||||
if( m_pCurDisplay->display[c].DrawHoldHeadForTapsOnSameRow() )
|
||||
{
|
||||
for( int c2=0; c2<m_pNoteData->GetNumTracks(); c2++ )
|
||||
{
|
||||
const TapNote &tmp = m_pNoteData->GetTapNote(c2, q);
|
||||
if(tmp.type == TapNoteType_HoldHead &&
|
||||
tmp.subType == TapNoteSubType_Hold)
|
||||
{
|
||||
bHoldNoteBeginsOnThisBeat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do the same for a roll.
|
||||
bool bRollNoteBeginsOnThisBeat = false;
|
||||
if (m_pCurDisplay->display[c].DrawRollHeadForTapsOnSameRow() )
|
||||
{
|
||||
for( int c2=0; c2<m_pNoteData->GetNumTracks(); c2++ )
|
||||
{
|
||||
const TapNote &tmp = m_pNoteData->GetTapNote(c2, q);
|
||||
if(tmp.type == TapNoteType_HoldHead &&
|
||||
tmp.subType == TapNoteSubType_Roll)
|
||||
{
|
||||
bRollNoteBeginsOnThisBeat = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bIsInSelectionRange = false;
|
||||
if( m_iBeginMarker!=-1 && m_iEndMarker!=-1 )
|
||||
bIsInSelectionRange = m_iBeginMarker<=q && q<m_iEndMarker;
|
||||
|
||||
bool bIsAddition = (tn.source == TapNoteSource_Addition);
|
||||
bool bIsHopoPossible = (tn.bHopoPossible);
|
||||
bool bUseAdditionColoring = bIsAddition || bIsHopoPossible;
|
||||
NoteDisplayCols *displayCols = tn.pn == PLAYER_INVALID ? m_pCurDisplay : m_pDisplays[tn.pn];
|
||||
displayCols->display[c].DrawTap(tn, c, NoteRowToVisibleBeat(m_pPlayerState, q),
|
||||
bHoldNoteBeginsOnThisBeat, bRollNoteBeginsOnThisBeat,
|
||||
bUseAdditionColoring, bIsInSelectionRange ? fSelectedRangeGlow : m_fPercentFadeToFail,
|
||||
m_fYReverseOffsetPixels, iDrawDistanceAfterTargetsPixels, iDrawDistanceBeforeTargetsPixels,
|
||||
FADE_BEFORE_TARGETS_PERCENT );
|
||||
|
||||
bool bNoteIsUpcoming = NoteRowToBeat(q) > m_pPlayerState->GetDisplayedPosition().m_fSongBeat;
|
||||
bAnyUpcomingInThisCol |= bNoteIsUpcoming;
|
||||
|
||||
if(!FAST_NOTE_RENDERING_PREF_CACHED)
|
||||
{
|
||||
DISPLAY->ClearZBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
cur->m_ReceptorArrowRow.SetNoteUpcoming( c, bAnyUpcomingInThisCol );
|
||||
m_ColumnRenderers[c].Draw();
|
||||
}
|
||||
|
||||
cur->m_GhostArrowRow.Draw();
|
||||
@@ -1377,7 +1251,7 @@ void NoteField::DrawPrimitives()
|
||||
|
||||
void NoteField::FadeToFail()
|
||||
{
|
||||
m_fPercentFadeToFail = max( 0.0f, m_fPercentFadeToFail ); // this will slowly increase every Update()
|
||||
m_FieldRenderArgs.fail_fade = max( 0.0f, m_FieldRenderArgs.fail_fade ); // this will slowly increase every Update()
|
||||
// don't fade all over again if this is called twice
|
||||
}
|
||||
|
||||
@@ -1523,10 +1397,10 @@ public:
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
SET_CALLBACK_GENERIC(SetStepCallback, m_StepCallback);
|
||||
SET_CALLBACK_GENERIC(SetSetPressedCallback, m_SetPressedCallback);
|
||||
SET_CALLBACK_GENERIC(SetDidTapNoteCallback, m_DidTapNoteCallback);
|
||||
SET_CALLBACK_GENERIC(SetDidHoldNoteCallback, m_DidHoldNoteCallback);
|
||||
SET_CALLBACK_GENERIC(set_step_callback, m_StepCallback);
|
||||
SET_CALLBACK_GENERIC(set_set_pressed_callback, m_SetPressedCallback);
|
||||
SET_CALLBACK_GENERIC(set_did_tap_note_callback, m_DidTapNoteCallback);
|
||||
SET_CALLBACK_GENERIC(set_did_hold_note_callback, m_DidHoldNoteCallback);
|
||||
#undef SET_CALLBACK_GENERIC
|
||||
|
||||
static int check_column(lua_State* L, int index)
|
||||
@@ -1542,7 +1416,7 @@ public:
|
||||
return col;
|
||||
}
|
||||
|
||||
static int Step(T* p, lua_State* L)
|
||||
static int step(T* p, lua_State* L)
|
||||
{
|
||||
int col= check_column(L, 1);
|
||||
TapNoteScore tns= Enum::Check<TapNoteScore>(L, 2);
|
||||
@@ -1550,14 +1424,14 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetPressed(T* p, lua_State* L)
|
||||
static int set_pressed(T* p, lua_State* L)
|
||||
{
|
||||
int col= check_column(L, 1);
|
||||
p->SetPressed(col, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DidTapNote(T* p, lua_State* L)
|
||||
static int did_tap_note(T* p, lua_State* L)
|
||||
{
|
||||
int col= check_column(L, 1);
|
||||
TapNoteScore tns= Enum::Check<TapNoteScore>(L, 2);
|
||||
@@ -1566,7 +1440,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DidHoldNote(T* p, lua_State* L)
|
||||
static int did_hold_note(T* p, lua_State* L)
|
||||
{
|
||||
int col= check_column(L, 1);
|
||||
HoldNoteScore hns= Enum::Check<HoldNoteScore>(L, 2);
|
||||
@@ -1575,16 +1449,28 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_column_actors(T* p, lua_State* L)
|
||||
{
|
||||
lua_createtable(L, p->m_ColumnRenderers.size(), 0);
|
||||
for(size_t i= 0; i < p->m_ColumnRenderers.size(); ++i)
|
||||
{
|
||||
p->m_ColumnRenderers[i].PushSelf(L);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
LunaNoteField()
|
||||
{
|
||||
ADD_METHOD(SetStepCallback);
|
||||
ADD_METHOD(SetSetPressedCallback);
|
||||
ADD_METHOD(SetDidTapNoteCallback);
|
||||
ADD_METHOD(SetDidHoldNoteCallback);
|
||||
ADD_METHOD(Step);
|
||||
ADD_METHOD(SetPressed);
|
||||
ADD_METHOD(DidTapNote);
|
||||
ADD_METHOD(DidHoldNote);
|
||||
ADD_METHOD(set_step_callback);
|
||||
ADD_METHOD(set_set_pressed_callback);
|
||||
ADD_METHOD(set_did_tap_note_callback);
|
||||
ADD_METHOD(set_did_hold_note_callback);
|
||||
ADD_METHOD(step);
|
||||
ADD_METHOD(set_pressed);
|
||||
ADD_METHOD(did_tap_note);
|
||||
ADD_METHOD(did_hold_note);
|
||||
ADD_METHOD(get_column_actors);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+8
-2
@@ -29,6 +29,8 @@ public:
|
||||
int iDrawDistanceBeforeTargetsPixels );
|
||||
virtual void Unload();
|
||||
|
||||
void InitColumnRenderers();
|
||||
|
||||
virtual void HandleMessage( const Message &msg );
|
||||
|
||||
// This is done automatically by Init(), but can be re-called explicitly if the
|
||||
@@ -55,6 +57,10 @@ public:
|
||||
|
||||
int m_iBeginMarker, m_iEndMarker; // only used with MODE_EDIT
|
||||
|
||||
// m_ColumnRenderers belongs in the protected section, but it's here in
|
||||
// public so that the Lua API can access it. -Kyz
|
||||
vector<NoteColumnRenderer> m_ColumnRenderers;
|
||||
|
||||
protected:
|
||||
void CacheNoteSkin( const RString &sNoteSkin );
|
||||
void UncacheNoteSkin( const RString &sNoteSkin );
|
||||
@@ -84,8 +90,6 @@ protected:
|
||||
|
||||
const NoteData *m_pNoteData;
|
||||
|
||||
float m_fPercentFadeToFail; // -1 if not fading to fail
|
||||
|
||||
const PlayerState* m_pPlayerState;
|
||||
int m_iDrawDistanceAfterTargetsPixels; // this should be a negative number
|
||||
int m_iDrawDistanceBeforeTargetsPixels; // this should be a positive number
|
||||
@@ -101,6 +105,8 @@ protected:
|
||||
~NoteDisplayCols() { delete [] display; }
|
||||
};
|
||||
|
||||
NoteFieldRenderArgs m_FieldRenderArgs;
|
||||
|
||||
/* All loaded note displays, mapped by their name. */
|
||||
map<RString, NoteDisplayCols *> m_NoteDisplays;
|
||||
NoteDisplayCols *m_pCurDisplay;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "global.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageMath.h"
|
||||
#include "RageTypes.h"
|
||||
#include <float.h>
|
||||
@@ -40,6 +41,22 @@ void RageVec3Normalize( RageVector3* pOut, const RageVector3* pV )
|
||||
pOut->z = pV->z * scale;
|
||||
}
|
||||
|
||||
void VectorFloatNormalize(vector<float>& v)
|
||||
{
|
||||
ASSERT_M(v.size() == 3, "Can't normalize a non-3D vector.");
|
||||
float scale = 1.0f / sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
||||
v[0]*= scale;
|
||||
v[1]*= scale;
|
||||
v[2]*= scale;
|
||||
}
|
||||
|
||||
void RageVec3Cross(RageVector3* ret, RageVector3 const* a, RageVector3 const* b)
|
||||
{
|
||||
ret->x= (a->y * b->z) - (a->z * b->y);
|
||||
ret->y= ((a->x * b->z) - (a->z * b->x));
|
||||
ret->z= (a->x * b->y) - (a->y * b->x);
|
||||
}
|
||||
|
||||
void RageVec3TransformCoord( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM )
|
||||
{
|
||||
RageVector4 temp( pV->x, pV->y, pV->z, 1.0f ); // translate
|
||||
@@ -313,6 +330,21 @@ void RageMatrixRotationXYZ( RageMatrix* pOut, float rX, float rY, float rZ )
|
||||
pOut->m33 = 1;
|
||||
}
|
||||
|
||||
void RageAARotate(RageVector3* inret, RageVector3 const* axis, float angle)
|
||||
{
|
||||
float ha= angle/2.0f;
|
||||
float ca2= RageFastCos(ha);
|
||||
float sa2= RageFastSin(ha);
|
||||
RageVector4 quat(axis->x * sa2, axis->y * sa2, axis->z * sa2, ca2);
|
||||
RageVector4 quatc(-quat.x, -quat.y, -quat.z, ca2);
|
||||
RageVector4 point(inret->x, inret->y, inret->z, 0.0f);
|
||||
RageQuatMultiply(&point, quat, point);
|
||||
RageQuatMultiply(&point, point, quatc);
|
||||
inret->x= point.x;
|
||||
inret->y= point.y;
|
||||
inret->z= point.z;
|
||||
}
|
||||
|
||||
void RageQuatMultiply( RageVector4* pOut, const RageVector4 &pA, const RageVector4 &pB )
|
||||
{
|
||||
RageVector4 out;
|
||||
|
||||
@@ -18,6 +18,8 @@ void RageVec3AddToBounds( const RageVector3 &p, RageVector3 &mins, RageVector3 &
|
||||
|
||||
void RageVec2Normalize( RageVector2* pOut, const RageVector2* pV );
|
||||
void RageVec3Normalize( RageVector3* pOut, const RageVector3* pV );
|
||||
void VectorFloatNormalize(vector<float>& v);
|
||||
void RageVec3Cross(RageVector3* ret, RageVector3 const* a, RageVector3 const* b);
|
||||
void RageVec3TransformCoord( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM );
|
||||
void RageVec3TransformNormal( RageVector3* pOut, const RageVector3* pV, const RageMatrix* pM );
|
||||
void RageVec4TransformCoord( RageVector4* pOut, const RageVector4* pV, const RageMatrix* pM );
|
||||
@@ -34,6 +36,7 @@ void RageMatrixRotationX( RageMatrix* pOut, float fTheta );
|
||||
void RageMatrixRotationY( RageMatrix* pOut, float fTheta );
|
||||
void RageMatrixRotationZ( RageMatrix* pOut, float fTheta );
|
||||
void RageMatrixRotationXYZ( RageMatrix* pOut, float rX, float rY, float rZ );
|
||||
void RageAARotate(RageVector3* inret, RageVector3 const* axis, float angle);
|
||||
void RageQuatFromHPR(RageVector4* pOut, RageVector3 hpr );
|
||||
void RageQuatFromPRH(RageVector4* pOut, RageVector3 prh );
|
||||
void RageMatrixFromQuat( RageMatrix* pOut, const RageVector4 q );
|
||||
|
||||
@@ -61,6 +61,12 @@ inline bool CLAMP( unsigned &x, unsigned l, unsigned h )
|
||||
else if (x < l) { x = l; return true; }
|
||||
return false;
|
||||
}
|
||||
inline bool CLAMP( size_t &x, size_t l, size_t h )
|
||||
{
|
||||
if (x > h) { x = h; return true; }
|
||||
else if (x < l) { x = l; return true; }
|
||||
return false;
|
||||
}
|
||||
inline bool CLAMP( float &x, float l, float h )
|
||||
{
|
||||
if (x > h) { x = h; return true; }
|
||||
|
||||
+11
-12
@@ -30,6 +30,16 @@ void ReceptorArrowRow::Load( const PlayerState* pPlayerState, float fYReverseOff
|
||||
}
|
||||
}
|
||||
|
||||
void ReceptorArrowRow::SetColumnRenderers(vector<NoteColumnRenderer>& renderers)
|
||||
{
|
||||
ASSERT_M(renderers.size() == m_ReceptorArrow.size(), "Notefield has different number of columns than receptor row.");
|
||||
for(size_t c= 0; c < m_ReceptorArrow.size(); ++c)
|
||||
{
|
||||
m_ReceptorArrow[c]->SetFakeParent(&(renderers[c]));
|
||||
}
|
||||
m_renderers= &renderers;
|
||||
}
|
||||
|
||||
ReceptorArrowRow::~ReceptorArrowRow()
|
||||
{
|
||||
for( unsigned i = 0; i < m_ReceptorArrow.size(); ++i )
|
||||
@@ -53,18 +63,7 @@ void ReceptorArrowRow::Update( float fDeltaTime )
|
||||
m_ReceptorArrow[c]->SetBaseAlpha( fBaseAlpha );
|
||||
|
||||
// set arrow XYZ
|
||||
float fX = ArrowEffects::GetXPos( m_pPlayerState, c, 0 );
|
||||
const float fY = ArrowEffects::GetYPos( m_pPlayerState, c, 0, m_fYReverseOffsetPixels );
|
||||
const float fZ = ArrowEffects::GetZPos( m_pPlayerState, c, 0 );
|
||||
m_ReceptorArrow[c]->SetX( fX );
|
||||
m_ReceptorArrow[c]->SetY( fY );
|
||||
m_ReceptorArrow[c]->SetZ( fZ );
|
||||
|
||||
const float fRotation = ArrowEffects::ReceptorGetRotationZ( m_pPlayerState );
|
||||
m_ReceptorArrow[c]->SetRotationZ( fRotation );
|
||||
|
||||
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
|
||||
m_ReceptorArrow[c]->SetZoom( fZoom );
|
||||
(*m_renderers)[c].UpdateReceptorGhostStuff(m_ReceptorArrow[c]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "ReceptorArrow.h"
|
||||
#include "ActorFrame.h"
|
||||
#include "GameConstantsAndTypes.h"
|
||||
#include "NoteDisplay.h"
|
||||
|
||||
class PlayerState;
|
||||
/** @brief A row of ReceptorArrow objects. */
|
||||
@@ -16,6 +17,7 @@ public:
|
||||
virtual void DrawPrimitives();
|
||||
|
||||
void Load( const PlayerState* pPlayerState, float fYReverseOffset );
|
||||
void SetColumnRenderers(vector<NoteColumnRenderer>& renderers);
|
||||
|
||||
void Step( int iCol, TapNoteScore score );
|
||||
void SetPressed( int iCol );
|
||||
@@ -28,6 +30,7 @@ protected:
|
||||
float m_fYReverseOffsetPixels;
|
||||
float m_fFadeToFailPercent;
|
||||
|
||||
vector<NoteColumnRenderer> const* m_renderers;
|
||||
vector<ReceptorArrow *> m_ReceptorArrow;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user