Skip to content

Commit

Permalink
Merge pull request #2620 from ivan-mogilko/ags4--flippingstuff
Browse files Browse the repository at this point in the history
AGS 4.0: Support all 3 flip styles in ViewFrame
  • Loading branch information
ivan-mogilko authored Dec 18, 2024
2 parents e7075a6 + c4007b4 commit 36d9efb
Show file tree
Hide file tree
Showing 39 changed files with 294 additions and 262 deletions.
14 changes: 1 addition & 13 deletions Common/ac/view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,14 @@

using namespace AGS::Common;

ViewFrame::ViewFrame()
: pic(0)
, xoffs(0)
, yoffs(0)
, speed(0)
, flags(0)
, sound(-1)
{
reserved_for_future[0] = 0;
reserved_for_future[1] = 0;
}

void ViewFrame::ReadFromFile(Stream *in)
{
pic = in->ReadInt32();
xoffs = in->ReadInt16();
yoffs = in->ReadInt16();
speed = in->ReadInt16();
in->ReadInt16(); // alignment padding to int32
flags = in->ReadInt32();
flags = (SpriteTransformFlags)in->ReadInt32();
sound = in->ReadInt32();
in->ReadInt32(); // reserved 1
in->ReadInt32(); // reserved 1
Expand Down
17 changes: 8 additions & 9 deletions Common/ac/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@
#define __AC_VIEW_H

#include <vector>
#include "gfx/gfx_def.h"

namespace AGS { namespace Common { class Stream; } }
using namespace AGS; // FIXME later

#define VFLG_FLIPSPRITE 1

struct ViewFrame {
int pic;
short xoffs, yoffs;
short speed;
int flags; // VFLG_* flags
int sound; // play sound when this frame comes round
int reserved_for_future[2]; // kept only for plugin api
ViewFrame();
int pic = 0;
short xoffs = 0, yoffs = 0;
short speed = 0;
Common::SpriteTransformFlags flags = Common::kSprTf_None;
int sound = -1; // play sound when this frame comes round
int reserved_for_future[2] = { 0 }; // kept only for plugin api // CLNUP: may remove in ags4?
ViewFrame() = default;

void ReadFromFile(Common::Stream *in);
void WriteToFile(Common::Stream *out);
Expand Down
42 changes: 38 additions & 4 deletions Common/gfx/gfx_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ namespace AGS
namespace Common
{

// GraphicFlip tells how to flip (mirror) a sprite
enum GraphicFlip
{
kFlip_None,
kFlip_Horizontal, // this means - mirror over horizontal middle line
kFlip_Vertical, // this means - mirror over vertical middle line
kFlip_Both // mirror over diagonal (horizontal and vertical)
kFlip_None = 0x0,
kFlip_Horizontal = 0x1, // this means - mirror over horizontal middle line
kFlip_Vertical = 0x2, // this means - mirror over vertical middle line
kFlip_Both = (kFlip_Horizontal | kFlip_Vertical) // mirror over diagonal
};

// Blend modes for object sprites
Expand All @@ -54,6 +55,16 @@ enum BlendMode
kNumBlendModes
};

// SpriteTransformFlags combine graphic effect options that do not have a value.
// These may be used both to store these options in memory and in serialization.
enum SpriteTransformFlags
{
kSprTf_None = 0x0000,
kSprTf_FlipX = 0x0001,
kSprTf_FlipY = 0x0002,
kSprTf_FlipXY = (kSprTf_FlipX | kSprTf_FlipY),
};

// GraphicResolution struct determines image size and color depth
struct GraphicResolution : Size
{
Expand Down Expand Up @@ -124,6 +135,29 @@ class GraphicSpace

namespace GfxDef
{
inline bool FlagsHaveFlip(SpriteTransformFlags flags)
{
return (flags & kSprTf_FlipXY) != 0;
}

inline GraphicFlip GetFlipFromFlags(SpriteTransformFlags flags)
{
switch (flags & kSprTf_FlipXY)
{
case kSprTf_FlipX: return kFlip_Horizontal;
case kSprTf_FlipY: return kFlip_Vertical;
case kSprTf_FlipXY: return kFlip_Both;
default: return kFlip_None;
}
}

inline SpriteTransformFlags GetFlagsFromFlip(GraphicFlip flip)
{
return (SpriteTransformFlags)(
kSprTf_FlipX * ((flip & kFlip_Horizontal) != 0)
| kSprTf_FlipY * ((flip & kFlip_Vertical) != 0));
}

// Converts value from range of 100 to range of 250 (sic!);
// uses formula that reduces precision loss and supports flawless forth &
// reverse conversion for multiplies of 10%
Expand Down
17 changes: 8 additions & 9 deletions Common/gui/guibutton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ GUIButton::GUIButton()
_image = -1;
_mouseOverImage = -1;
_pushedImage = -1;
_imageFlags = 0;
_imageFlags = kSprTf_None;
_currentImage = -1;
_curImageFlags = 0;
_curImageFlags = kSprTf_None;
Font = 0;
TextColor = 0;
TextAlignment = kAlignTopCenter;
Expand Down Expand Up @@ -215,7 +215,7 @@ void GUIButton::SetPushedImage(int32_t image)
UpdateCurrentImage();
}

void GUIButton::SetImages(int32_t normal, int32_t over, int32_t pushed, uint32_t flags)
void GUIButton::SetImages(int32_t normal, int32_t over, int32_t pushed, SpriteTransformFlags flags)
{
_image = normal;
_mouseOverImage = over;
Expand All @@ -229,7 +229,7 @@ int32_t GUIButton::CurrentImage() const
return _currentImage;
}

void GUIButton::SetCurrentImage(int32_t new_image, uint32_t flags)
void GUIButton::SetCurrentImage(int32_t new_image, SpriteTransformFlags flags)
{
if (_currentImage == new_image && _curImageFlags == flags)
return;
Expand Down Expand Up @@ -312,7 +312,7 @@ void GUIButton::OnMouseUp()
void GUIButton::UpdateCurrentImage()
{
int new_image = _currentImage;
uint32_t new_flags = 0;
SpriteTransformFlags new_flags = kSprTf_None;

if (IsPushed && (_pushedImage > 0))
{
Expand Down Expand Up @@ -399,11 +399,11 @@ void GUIButton::ReadFromSavegame(Stream *in, GuiSvgVersion svg_ver)

if (svg_ver >= kGuiSvgVersion_400)
{
_imageFlags = in->ReadInt32();
_imageFlags = (SpriteTransformFlags)in->ReadInt32();
}
else
{
_imageFlags = 0;
_imageFlags = kSprTf_None;
}

// Update current state after reading
Expand All @@ -430,7 +430,6 @@ void GUIButton::WriteToSavegame(Stream *out) const
out->WriteInt32(0);
//since kGuiSvgVersion_3991
out->WriteInt32(_imageFlags);

}

void GUIButton::DrawImageButton(Bitmap *ds, int x, int y, bool draw_disabled)
Expand All @@ -447,7 +446,7 @@ void GUIButton::DrawImageButton(Bitmap *ds, int x, int y, bool draw_disabled)
ds->SetClip(RectWH(x, y, _width, _height));

if (spriteset.DoesSpriteExist(_currentImage))
draw_gui_sprite_flipped(ds, _currentImage, x, y, kBlend_Normal, _curImageFlags & VFLG_FLIPSPRITE);
draw_gui_sprite_flipped(ds, _currentImage, x, y, kBlend_Normal, GfxDef::GetFlipFromFlags(_curImageFlags));

// Draw active inventory item
const int gui_inv_pic = GUI::Context.InventoryPic;
Expand Down
8 changes: 4 additions & 4 deletions Common/gui/guibutton.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@ class GUIButton : public GUIObject
Rect CalcGraphicRect(bool clipped) override;
void Draw(Bitmap *ds, int x = 0, int y = 0) override;
void SetClipImage(bool on);
void SetCurrentImage(int32_t image, uint32_t flags = 0);
void SetCurrentImage(int32_t image, SpriteTransformFlags flags = kSprTf_None);
void SetMouseOverImage(int32_t image);
void SetNormalImage(int32_t image);
void SetPushedImage(int32_t image);
void SetImages(int32_t normal, int32_t over, int32_t pushed, uint32_t flags = 0);
void SetImages(int32_t normal, int32_t over, int32_t pushed, SpriteTransformFlags flags = kSprTf_None);
void SetText(const String &text);
void SetWrapText(bool on);

Expand Down Expand Up @@ -118,10 +118,10 @@ class GUIButton : public GUIObject
int32_t _mouseOverImage;
int32_t _pushedImage;
// TODO: flags for each kind of image?
uint32_t _imageFlags;
SpriteTransformFlags _imageFlags;
// Active displayed image
int32_t _currentImage;
uint32_t _curImageFlags;
SpriteTransformFlags _curImageFlags;
// Text property set by user
String _text;
// type of content placeholder, if any
Expand Down
4 changes: 2 additions & 2 deletions Common/gui/guimain.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,9 +378,9 @@ extern void draw_gui_sprite(AGS::Common::Bitmap *ds, int x, int y,
AGS::Common::Bitmap *image,
AGS::Common::BlendMode blend_mode, int alpha);

extern void draw_gui_sprite_flipped(AGS::Common::Bitmap *ds, int pic, int x, int y, AGS::Common::BlendMode blend_mode, bool is_flipped);
extern void draw_gui_sprite_flipped(AGS::Common::Bitmap *ds, int pic, int x, int y, AGS::Common::BlendMode blend_mode, AGS::Common::GraphicFlip flip);
extern void draw_gui_sprite_flipped(AGS::Common::Bitmap *ds, int x, int y,
AGS::Common::Bitmap *image, AGS::Common::BlendMode blend_mode, int alpha, bool is_flipped);
AGS::Common::Bitmap *image, AGS::Common::BlendMode blend_mode, int alpha, AGS::Common::GraphicFlip flip);

// Those function have distinct implementations in Engine and Editor
extern void wouttext_outline(AGS::Common::Bitmap *ds, int xxp, int yyp, int usingfont, color_t text_color, const char *texx);
Expand Down
3 changes: 2 additions & 1 deletion Editor/AGS.Editor/AGSEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,10 @@ public class AGSEditor : IAGSEditorDirectories
* 4.00.00.10 - Font and FontFile separation;
* Settings.ScriptCompiler as a selection of script compiler IDs,
* ExtendedCompiler is deprecated.
* 4.00.00.12 - ViewFrame.Flip has full flip selection.
*
*/
public const int LATEST_XML_VERSION_INDEX = 4000010;
public const int LATEST_XML_VERSION_INDEX = 4000012;
/// <summary>
/// XML version index on the release of AGS 4.0.0, this constant be used to determine
/// if upgrade of Rooms/Sprites/etc. to new format have been performed.
Expand Down
1 change: 1 addition & 0 deletions Editor/AGS.Editor/AGSEditor.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@
<Compile Include="Utils\ScriptGeneration.cs" />
<Compile Include="Utils\StdConsoleWriter.cs" />
<Compile Include="Utils\Validation.cs" />
<Compile Include="Utils\ViewUtils.cs" />
<EmbeddedResource Include="GUI\AdjustMasksDialog.resx">
<DependentUpon>AdjustMasksDialog.cs</DependentUpon>
</EmbeddedResource>
Expand Down
2 changes: 1 addition & 1 deletion Editor/AGS.Editor/DataFileWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,7 @@ public bool WriteViews(IViewFolder folder, Game game, CompileMessages errors)
writer.Write((short)0); // unused y-offset
writer.Write((short)frame.Delay);
writer.Write((short)0); // struct alignment padding
writer.Write(frame.Flipped ? NativeConstants.VFLG_FLIPSPRITE : 0);
writer.Write((int)frame.Flip);
writer.Write(game.GetAudioArrayIDFromFixedIndex(frame.Sound));
writer.Write(0); // unused reservedForFuture[0]
writer.Write(0); // unused reservedForFuture[1]
Expand Down
1 change: 1 addition & 0 deletions Editor/AGS.Editor/GUI/AssignToView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public bool ContinueIntoNextLoop
get { return _continueIntoNextLoop; }
}

// TODO: support all flip choices?
public bool FlipFrames
{
get { return _flipFrames; }
Expand Down
4 changes: 2 additions & 2 deletions Editor/AGS.Editor/ImportExport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ private static void WriteOldStyleView(BinaryWriter writer, View view)
writer.Write((int)0);
writer.Write((short)frame.Delay);
WriteZeros(writer, 2);
writer.Write((frame.Flipped) ? 1 : 0);
writer.Write((frame.Flip != SpriteFlipStyle.None) ? 1 : 0);
writer.Write(frame.Sound);
WriteZeros(writer, 8);
}
Expand Down Expand Up @@ -917,7 +917,7 @@ private static View ReadOldStyleView(BinaryReader reader, Game game, SpriteFolde
reader.ReadInt32();
frame.Delay = reader.ReadInt16();
reader.ReadBytes(2);
frame.Flipped = (reader.ReadInt32() == 1);
frame.Flip = (reader.ReadInt32() == 1) ? SpriteFlipStyle.Horizontal : SpriteFlipStyle.None;
frame.Sound = reader.ReadInt32();
reader.ReadBytes(8);
if ((i < numLoops) && (j < numFrames[i]))
Expand Down
3 changes: 2 additions & 1 deletion Editor/AGS.Editor/Panes/SpriteSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,9 +1134,10 @@ private void AssignSpritesToView(List<int> spriteNumbers, AssignToView dialog)
ViewFrame newFrame = new ViewFrame();
newFrame.ID = view.Loops[loop].Frames.Count;
newFrame.Image = spriteNum;
// TODO: support all flip choices?
if (dialog.FlipFrames)
{
newFrame.Flipped = true;
newFrame.Flip = SpriteFlipStyle.Horizontal;
}
view.Loops[loop].Frames.Add(newFrame);
}
Expand Down
11 changes: 4 additions & 7 deletions Editor/AGS.Editor/Panes/ViewLoopEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public void FlipSelectedFrames()
foreach (int sel in _selectedFrames)
{
ViewFrame frame = _loop.Frames[sel];
frame.Flipped = !frame.Flipped;
frame.Flip ^= SpriteFlipStyle.Horizontal;
}
this.Invalidate();
}
Expand Down Expand Up @@ -436,10 +436,7 @@ private void onCutLoopClicked(object sender, EventArgs e)

private void pasteLoop(bool flipped)
{
//int loopId = _loop.ID;
//_loop = _copiedLoop.Clone(flipped);
//_loop.ID = loopId;
_copiedLoop.Clone(_loop, flipped);
_copiedLoop.CloneInto(_loop, flipped);
UpdateControlWidth();
this.Invalidate();
}
Expand All @@ -455,8 +452,8 @@ private void onPasteFlippedClicked(object sender, EventArgs e)
}

private void onFlipAllClicked(object sender, EventArgs e)
{
_loop.Frames.ForEach(c => c.Flipped = !c.Flipped);
{
_loop.Frames.ForEach(f => f.Flip ^= SpriteFlipStyle.Horizontal);
this.Invalidate();
}

Expand Down
20 changes: 16 additions & 4 deletions Editor/AGS.Editor/Panes/ViewPreview.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,23 @@ private void previewPanel_Paint(object sender, PaintEventArgs e)

Bitmap bmp = Utilities.GetBitmapForSpriteResizedKeepingAspectRatio(new Sprite(spriteNum, spriteSize.Width, spriteSize.Height), targetWidth, targetHeight, chkCentrePivot.Checked, false, Color.Magenta);

if (thisFrame.Flipped)
if (thisFrame.Flip != SpriteFlipStyle.None)
{
Point urCorner = new Point(x, y);
Point ulCorner = new Point(x + bmp.Width, y);
Point llCorner = new Point(x + bmp.Width, y + bmp.Height);
int left = x, right = x + bmp.Width, top = y, bottom = y + bmp.Height;
if ((thisFrame.Flip & SpriteFlipStyle.Horizontal) != 0)
{
left = x + bmp.Width;
right = x;
}
if ((thisFrame.Flip & SpriteFlipStyle.Vertical) != 0)
{
top = y + bmp.Height;
bottom = y;
}

Point urCorner = new Point(right, top);
Point ulCorner = new Point(left, top);
Point llCorner = new Point(left, bottom);
Point[] destPara = { ulCorner, urCorner, llCorner };
e.Graphics.DrawImage(bmp, destPara);
}
Expand Down
3 changes: 2 additions & 1 deletion Editor/AGS.Editor/Resources/agsdefns.sh
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ enum eVoiceMode {
};
enum eFlipDirection {
eFlipNone = 0,
eFlipLeftToRight = 1,
eFlipUpsideDown = 2,
eFlipBoth = 3
Expand Down Expand Up @@ -725,7 +726,7 @@ builtin managed struct AudioClip;
builtin managed struct ViewFrame {
/// Gets whether this frame is flipped.
readonly import attribute bool Flipped;
readonly import attribute eFlipDirection Flipped;
/// Gets the frame number of this frame.
readonly import attribute int Frame;
/// Gets/sets the sprite that is displayed by this frame.
Expand Down
15 changes: 15 additions & 0 deletions Editor/AGS.Editor/Tasks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,21 @@ private void SetDefaultValuesForNewFeatures(Game game)
AGSEditor.DEFAULT_SCRIPT_COMPILER : AGSEditor.DEFAULT_LEGACY_SCRIPT_COMPILER;
}

// Update viewframes
if (xmlVersionIndex < 4000012)
{
foreach (AGS.Types.View view in game.ViewFlatList)
{
foreach (ViewLoop loop in view.Loops)
{
foreach (ViewFrame frame in loop.Frames)
{
frame.Flip = frame.Flipped ? SpriteFlipStyle.Horizontal : SpriteFlipStyle.None;
}
}
}
}

if (string.IsNullOrEmpty(game.Settings.ScriptCompiler))
{
var compiler = Factory.NativeProxy.GetEmbeddedScriptCompilers().FirstOrDefault();
Expand Down
Loading

0 comments on commit 36d9efb

Please sign in to comment.