client: Add Widget Animation Smoothing

This commit is contained in:
Owain van Brakel
2019-07-10 23:32:24 +02:00
parent e7b15d9cfd
commit e85fc0e7d0
14 changed files with 325 additions and 187 deletions

View File

@@ -163,6 +163,9 @@ public abstract class RSClientMixin implements RSClient
@Inject
private static boolean interpolateObjectAnimations;
@Inject
private static boolean interpolateWidgetAnimations;
@Inject
private static RSPlayer[] oldPlayers = new RSPlayer[2048];
@@ -307,6 +310,20 @@ public abstract class RSClientMixin implements RSClient
interpolateObjectAnimations = interpolate;
}
@Inject
@Override
public boolean isInterpolateWidgetAnimations()
{
return interpolateWidgetAnimations;
}
@Inject
@Override
public void setInterpolateWidgetAnimations(boolean interpolate)
{
interpolateWidgetAnimations = interpolate;
}
@Inject
@Override
public void setInventoryDragDelay(int delay)

View File

@@ -15,10 +15,10 @@ public abstract class RSSequenceDefinitionMixin implements RSSequenceDefinition
@Shadow("client")
private static RSClient client;
@Copy("animateSequence2")
@Copy("applyTransformations")
public abstract RSModel rs$applyTransformations(RSModel model, int actionFrame, RSSequenceDefinition poseSeq, int poseFrame);
@Replace("animateSequence2")
@Replace("applyTransformations")
public RSModel rl$applyTransformations(RSModel model, int actionFrame, RSSequenceDefinition poseSeq, int poseFrame)
{
// reset frame ids because we're not interpolating this
@@ -35,185 +35,253 @@ public abstract class RSSequenceDefinitionMixin implements RSSequenceDefinition
return rs$applyTransformations(model, actionFrame, poseSeq, poseFrame);
}
@Copy("animateSequence")
@Copy("transformActorModel")
public abstract RSModel rs$transformActorModel(RSModel model, int frameIdx);
@Replace("animateSequence")
@Replace("transformActorModel")
public RSModel rl$transformActorModel(RSModel model, int frame)
{
// check if the frame has been modified
if (frame < 0)
{
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
// not sure what toSharedModel does but it is needed
return model.toSharedModel(true);
}
else
{
RSModel animatedModel = model.toSharedModel(!frames.getFrames()[frameIdx].isShowing());
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
return animatedModel;
}
}
else
// check if the frame has not been modified
if (frame >= 0)
{
return rs$transformActorModel(model, frame);
}
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
// not sure what toSharedModel does but it is needed
return model.toSharedModel(true);
}
RSModel animatedModel = model.toSharedModel(!frames.getFrames()[frameIdx].isShowing());
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
return animatedModel;
}
@Copy("animateObject")
@Copy("transformObjectModel")
public abstract RSModel rs$transformObjectModel(RSModel model, int frame, int rotation);
@Replace("animateObject")
@Replace("transformObjectModel")
public RSModel rl$transformObjectModel(RSModel model, int frame, int rotation)
{
// check if the frame has been modified
if (frame < 0)
{
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
return model.toSharedModel(true);
}
else
{
RSModel animatedModel = model.toSharedModel(!frames.getFrames()[frameIdx].isShowing());
// reset rotation before animating
rotation &= 3;
if (rotation == 1)
{
animatedModel.rotateY270Ccw();
}
else if (rotation == 2)
{
animatedModel.rotateY180Ccw();
}
else if (rotation == 3)
{
animatedModel.rotateY90Ccw();
}
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
// reapply rotation after animating
if (rotation == 1)
{
animatedModel.rotateY90Ccw();
}
else if (rotation == 2)
{
animatedModel.rotateY180Ccw();
}
else if (rotation == 3)
{
animatedModel.rotateY270Ccw();
}
return animatedModel;
}
}
else
// check if the frame has not been modified
if (frame >= 0)
{
return rs$transformObjectModel(model, frame, rotation);
}
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
return model.toSharedModel(true);
}
RSModel animatedModel = model.toSharedModel(!frames.getFrames()[frameIdx].isShowing());
// reset rotation before animating
rotation &= 3;
if (rotation == 1)
{
animatedModel.rotateY270Ccw();
}
else if (rotation == 2)
{
animatedModel.rotateY180Ccw();
}
else if (rotation == 3)
{
animatedModel.rotateY90Ccw();
}
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
// reapply rotation after animating
if (rotation == 1)
{
animatedModel.rotateY90Ccw();
}
else if (rotation == 2)
{
animatedModel.rotateY180Ccw();
}
else if (rotation == 3)
{
animatedModel.rotateY270Ccw();
}
return animatedModel;
}
@Copy("animateSpotAnimation")
public abstract RSModel rs$transformSpotAnimModel(RSModel model, int frame);
@Copy("transformSpotAnimationModel")
public abstract RSModel rs$transformSpotAnimationModel(RSModel model, int frame);
@Replace("animateSpotAnimation")
public RSModel rl$transformSpotAnimModel(RSModel model, int frame)
@Replace("transformSpotAnimationModel")
public RSModel rl$transformSpotAnimationModel(RSModel model, int frame)
{
// check if the frame has been modified
if (frame < 0)
// check if the frame has not been modified
if (frame >= 0)
{
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
return model.toSharedSpotAnimModel(true);
}
else
{
RSModel animatedModel = model.toSharedSpotAnimModel(!frames.getFrames()[frameIdx].isShowing());
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
return animatedModel;
}
return rs$transformSpotAnimationModel(model, frame);
}
else
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
return rs$transformSpotAnimModel(model, frame);
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
return model.toSharedSpotAnimModel(true);
}
RSModel animatedModel = model.toSharedSpotAnimModel(!frames.getFrames()[frameIdx].isShowing());
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
return animatedModel;
}
@Copy("transformWidgetModel")
public abstract RSModel rs$transformWidgetModel(RSModel model, int frame);
@Replace("transformWidgetModel")
public RSModel rl$transformWidgetModel(RSModel model, int frame)
{
// check if the frame has not been modified
if (frame >= 0)
{
return rs$transformWidgetModel(model, frame);
}
// remove flag to check if the frame has been modified
int packed = frame ^ Integer.MIN_VALUE;
int interval = packed >> 16;
frame = packed & 0xFFFF;
int nextFrame = frame + 1;
if (nextFrame >= getFrameIDs().length)
{
// dont interpolate last frame
nextFrame = -1;
}
int[] frameIds = getFrameIDs();
int frameId = frameIds[frame];
RSFrames frames = client.getFrames(frameId >> 16);
int frameIdx = frameId & 0xFFFF;
int nextFrameIdx = -1;
RSFrames nextFrames = null;
if (nextFrame != -1)
{
int nextFrameId = frameIds[nextFrame];
nextFrames = client.getFrames(nextFrameId >> 16);
nextFrameIdx = nextFrameId & 0xFFFF;
}
if (frames == null)
{
return model.toSharedModel(true);
}
RSFrames chatFrames = null;
int chatFrameIdx = 0;
if (getChatFrameIds() != null && frame < getChatFrameIds().length)
{
int chatFrameId = getChatFrameIds()[frame];
chatFrames = client.getFrames(chatFrameId >> 16);
chatFrameIdx = chatFrameId & 0xFFFF;
}
if (chatFrames != null && chatFrameIdx != 0xFFFF)
{
RSFrames nextChatFrames = null;
int nextChatFrameIdx = -1;
if (nextFrame != -1 && nextFrame < getChatFrameIds().length)
{
int chatFrameId = getChatFrameIds()[nextFrame];
nextChatFrames = client.getFrames(chatFrameId >> 16);
nextChatFrameIdx = chatFrameId & 0xFFFF;
}
// not sure if this can even happen but the client checks for this so to be safe
if (nextChatFrameIdx == 0xFFFF)
{
nextChatFrames = null;
}
RSModel animatedModel = model.toSharedModel(!frames.getFrames()[frameIdx].isShowing()
& !chatFrames.getFrames()[chatFrameIdx].isShowing());
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
animatedModel.interpolateFrames(chatFrames, chatFrameIdx, nextChatFrames, nextChatFrameIdx,
interval, getFrameLenths()[frame]);
return animatedModel;
}
RSModel animatedModel = model.toSharedModel(!frames.getFrames()[frameIdx].isShowing());
animatedModel.interpolateFrames(frames, frameIdx, nextFrames, nextFrameIdx, interval,
getFrameLenths()[frame]);
return animatedModel;
}
}

View File

@@ -30,6 +30,8 @@ import net.runelite.api.Point;
import net.runelite.api.WidgetNode;
import net.runelite.api.events.WidgetHiddenChanged;
import net.runelite.api.events.WidgetPositioned;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Replace;
import net.runelite.api.widgets.Widget;
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
@@ -44,8 +46,11 @@ import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Shadow;
import net.runelite.rs.api.RSClient;
import net.runelite.rs.api.RSModel;
import net.runelite.rs.api.RSNode;
import net.runelite.rs.api.RSNodeHashTable;
import net.runelite.rs.api.RSPlayerAppearance;
import net.runelite.rs.api.RSSequenceDefinition;
import net.runelite.rs.api.RSWidget;
@Mixin(RSWidget.class)
@@ -581,4 +586,17 @@ public abstract class RSWidgetMixin implements RSWidget
Arrays.fill(getChildren(), null);
}
}
@Copy("getModel")
public abstract RSModel rs$getModel(RSSequenceDefinition sequence, int frame, boolean alternate, RSPlayerAppearance playerComposition);
@Replace("getModel")
public RSModel rl$getModel(RSSequenceDefinition sequence, int frame, boolean alternate, RSPlayerAppearance playerComposition)
{
if (frame != -1 && client.isInterpolateWidgetAnimations())
{
frame = frame | getModelFrameCycle() << 16 | Integer.MIN_VALUE;
}
return rs$getModel(sequence, frame, alternate, playerComposition);
}
}