Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/ags4' into ags4
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-mogilko committed Aug 12, 2024
2 parents c0a4618 + 5320b6f commit ee2a31f
Show file tree
Hide file tree
Showing 44 changed files with 816 additions and 160 deletions.
2 changes: 1 addition & 1 deletion Common/ac/dialogtopic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void DialogTopic::ReadFromFile(Stream *in)
topicFlags = in->ReadInt32();
}

void DialogTopic::ReadFromSavegame(Common::Stream *in)
void DialogTopic::ReadFromSavegame(Common::Stream *in, DialogSvgVersion /*svg_ver*/)
{
in->ReadArrayOfInt32(optionflags, MAXTOPICOPTIONS);
}
Expand Down
12 changes: 11 additions & 1 deletion Common/ac/dialogtopic.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ using namespace AGS; // FIXME later
#define DTFLG_SHOWPARSER 1 // show parser in this topic
#define DCHAR_NARRATOR 999
#define DCHAR_PLAYER 998

// RoomStatus runtime save format
// TODO: move to the engine code
enum DialogSvgVersion
{
kDialogSvgVersion_Initial = 0,
kDialogSvgVersion_40008 = 4000008, // custom properties
};


struct DialogTopic {
char optionnames[MAXTOPICOPTIONS][150];
int optionflags[MAXTOPICOPTIONS];
Expand All @@ -40,7 +50,7 @@ struct DialogTopic {

void ReadFromFile(Common::Stream *in);

void ReadFromSavegame(Common::Stream *in);
void ReadFromSavegame(Common::Stream *in, DialogSvgVersion svg_ver);
void WriteToSavegame(Common::Stream *out) const;
};

Expand Down
11 changes: 7 additions & 4 deletions Common/ac/gamesetupstruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ void GameSetupStruct::Free()
audioClips.clear();
audioClipTypes.clear();

audioclipProps.clear();
charProps.clear();
guiProps.clear();
dialogProps.clear();
viewNames.clear();
}

Expand Down Expand Up @@ -206,11 +209,11 @@ HGameFileError GameSetupStruct::read_customprops(Common::Stream *in, GameDataVer
errors += Properties::ReadValues(invProps[i], in);
}

if (errors > 0)
return new MainGameFileError(kMGFErr_InvalidPropertyValues);
if (errors > 0)
return new MainGameFileError(kMGFErr_InvalidPropertyValues);

for (int i = 0; i < numviews; ++i)
viewNames[i] = String::FromStream(in);
for (int i = 0; i < numviews; ++i)
viewNames[i] = String::FromStream(in);

for (int i = 0; i < numinvitems; ++i)
invScriptNames[i] = String::FromStream(in);
Expand Down
3 changes: 3 additions & 0 deletions Common/ac/gamesetupstruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ struct GameSetupStruct : public GameSetupStructBase
AGS::Common::PropertySchema propSchema;
std::vector<AGS::Common::StringIMap> charProps;
AGS::Common::StringIMap invProps[MAX_INV];
std::vector<AGS::Common::StringIMap> audioclipProps;
std::vector<AGS::Common::StringIMap> dialogProps;
std::vector<AGS::Common::StringIMap> guiProps;
// NOTE: although the view names are stored in game data, they are never
// used, nor registered as script exports; numeric IDs are used to
// reference views instead.
Expand Down
33 changes: 33 additions & 0 deletions Common/game/main_game_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,39 @@ HError GameDataExtReader::ReadBlock(Stream *in, int /*block_id*/, const String &
// reserve few more 32-bit values (for a total of 10)
_in->Seek(sizeof(int32_t) * 9);
}
else if (ext_id.CompareNoCase("v400_customprops") == 0)
{
auto &game = _ents.Game;
int errors = 0;
game.audioclipProps.resize(game.audioClips.size());
game.dialogProps.resize(game.numdialog);
game.guiProps.resize(game.numgui);

size_t num_clips = in->ReadInt32();
if (num_clips != game.audioClips.size())
return new Error(String::FromFormat("Mismatching number of audio clips: read %zu expected %zu", num_clips, _ents.Game.audioClips.size()));
for (size_t i = 0; i < game.audioClips.size(); ++i)
{
errors += Properties::ReadValues(game.audioclipProps[i], in);
}
size_t num_dialogs = in->ReadInt32();
if (num_dialogs != game.numdialog)
return new Error(String::FromFormat("Mismatching number of dialogs: read %zu expected %zu", num_dialogs, game.numdialog));
for (size_t i = 0; i < game.numdialog; ++i)
{
errors += Properties::ReadValues(game.dialogProps[i], in);
}
size_t num_gui = in->ReadInt32();
if (num_gui != game.numgui)
return new Error(String::FromFormat("Mismatching number of gui: read %zu expected %zu", num_gui, game.numgui));
for (size_t i = 0; i < game.numgui; ++i)
{
errors += Properties::ReadValues(game.guiProps[i], in);
}

if (errors > 0)
return new MainGameFileError(kMGFErr_InvalidPropertyValues);
}
else
{
return new MainGameFileError(kMGFErr_ExtUnknown, String::FromFormat("Type: %s", ext_id.GetCStr()));
Expand Down
45 changes: 45 additions & 0 deletions Common/game/room_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,31 @@ HError ReadExt_400_WalkOpts(RoomStruct *room, Stream *in, RoomFileVersion data_v
return HError::None();
}

HError ReadExt_400_CustomProps(RoomStruct *room, Stream *in, RoomFileVersion data_ver)
{
size_t region_count = in->ReadInt32();
if (region_count != room->RegionCount)
return new Error(String::FromFormat("Mismatching number of regions: read %zu expected %zu", region_count, room->RegionCount));
int errors = 0;
for (size_t i = 0; i < room->RegionCount; ++i)
{
errors += Properties::ReadValues(room->Regions[i].Properties, in);
}
if (errors > 0)
return new RoomFileError(kRoomFileErr_InvalidPropertyValues);

size_t wa_count = in->ReadInt32();
if (wa_count != room->WalkAreaCount)
return new Error(String::FromFormat("Mismatching number of walkable areas: read %zu expected %zu", wa_count, room->WalkAreaCount));
for (size_t i = 0; i < room->WalkAreaCount; ++i)
{
Properties::ReadValues(room->WalkAreas[i].Properties, in);
}
if (errors > 0)
return new RoomFileError(kRoomFileErr_InvalidPropertyValues);
return HError::None();
}

HError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block, const String &ext_id,
soff_t block_len, RoomFileVersion data_ver)
{
Expand Down Expand Up @@ -404,6 +429,10 @@ HError ReadRoomBlock(RoomStruct *room, Stream *in, RoomFileBlock block, const St
{
return ReadExt_400_WalkOpts(room, in, data_ver);
}
else if (ext_id.CompareNoCase("v400_customprops") == 0)
{
return ReadExt_400_CustomProps(room, in, data_ver);
}

return new RoomFileError(kRoomFileErr_UnknownBlockType,
String::FromFormat("Type: %s", ext_id.GetCStr()));
Expand Down Expand Up @@ -686,6 +715,21 @@ void WriteExt_400_WalkareaOpts(const RoomStruct *room, Stream *out)
}
}

void WriteExt_400_CustomProps(const RoomStruct *room, Stream *out)
{
out->WriteInt32(room->RegionCount);
for (size_t i = 0; i < room->RegionCount; ++i)
{
Properties::WriteValues(room->Regions[i].Properties, out);
}

out->WriteInt32(room->WalkAreaCount);
for (size_t i = 0; i < room->WalkAreaCount; ++i)
{
Properties::WriteValues(room->WalkAreas[i].Properties, out);
}
}

HRoomFileError WriteRoomData(const RoomStruct *room, Stream *out, RoomFileVersion data_ver)
{
if (data_ver < kRoomVersion_Current)
Expand Down Expand Up @@ -716,6 +760,7 @@ HRoomFileError WriteRoomData(const RoomStruct *room, Stream *out, RoomFileVersio
// Early development version of "ags4"
WriteRoomBlock(room, "ext_ags399", WriteExt399, out);
WriteRoomBlock(room, "v400_walkopts", WriteExt_400_WalkareaOpts, out);
WriteRoomBlock(room, "v400_customprops", WriteExt_400_CustomProps, out);

// Write end of room file
out->WriteByte(kRoomFile_EOF);
Expand Down
2 changes: 2 additions & 0 deletions Common/game/roomstruct.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ struct WalkArea
// Top and bottom Y of the area
int32_t Top;
int32_t Bottom;
// Custom properties
StringIMap Properties;

WalkArea();
};
Expand Down
3 changes: 2 additions & 1 deletion Common/gui/guidefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ enum GuiSvgVersion
kGuiSvgVersion_36020,
kGuiSvgVersion_36023,
kGuiSvgVersion_36025,
kGuiSvgVersion_400 = 4000000
kGuiSvgVersion_400 = 4000000,
kGuiSvgVersion_40008 = 4000008, // custom properties
};

// Style of GUI drawing in disabled state
Expand Down
2 changes: 1 addition & 1 deletion Common/util/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void String::Write(Stream *out) const
void String::WriteCount(Stream *out, size_t count) const
{
assert(out);
size_t str_out_len = std::min(count - 1, _len);
size_t str_out_len = std::min(count, _len);
if (str_out_len > 0)
out->Write(_cstr, str_out_len);
size_t null_out_len = count - str_out_len;
Expand Down
4 changes: 2 additions & 2 deletions Common/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ class String
void ReadCount(Stream *in, size_t count);
// Write() puts the null-terminated string into the stream.
void Write(Stream *out) const;
// WriteCount() writes N characters to stream, filling the remaining
// space with null-terminators when needed.
// WriteCount() writes up to N first string's characters to stream,
// filling any of the remaining space with zeroes.
void WriteCount(Stream *out, size_t count) const;

//-------------------------------------------------------------------------
Expand Down
7 changes: 5 additions & 2 deletions Editor/AGS.Editor.Tests/Types/RoomRegionTests.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
using System;
using System.Xml;
using NSubstitute;
using NUnit.Framework;

namespace AGS.Types
{
[TestFixture]
public class RoomRegionTests
{
private IChangeNotification _changeNotification;
private RoomRegion _roomRegion;

[SetUp]
public void SetUp()
{
_roomRegion = new RoomRegion();
_changeNotification = Substitute.For<IChangeNotification>();
_roomRegion = new RoomRegion(_changeNotification);
}

[TestCase(0)]
Expand Down Expand Up @@ -117,7 +120,7 @@ public void DeserializesFromXml(bool useColourTint, int lightLevel, int redTint,
</RoomRegion>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
_roomRegion = new RoomRegion(doc.SelectSingleNode("RoomRegion"));
_roomRegion = new RoomRegion(_changeNotification, doc.SelectSingleNode("RoomRegion"));

Assert.That(_roomRegion.UseColourTint, Is.EqualTo(useColourTint));
Assert.That(_roomRegion.LightLevel, Is.EqualTo(lightLevel));
Expand Down
11 changes: 7 additions & 4 deletions Editor/AGS.Editor.Tests/Types/RoomWalkableAreaTests.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
using NUnit.Framework;
using System.Xml;
using System.Xml;
using NSubstitute;
using NUnit.Framework;

namespace AGS.Types
{
[TestFixture]
public class RoomWalkableAreaTests
{
private IChangeNotification _changeNotification;
private RoomWalkableArea _roomWalkAbleArea;

[SetUp]
public void SetUp()
{
_roomWalkAbleArea = new RoomWalkableArea();
_changeNotification = Substitute.For<IChangeNotification>();
_roomWalkAbleArea = new RoomWalkableArea(_changeNotification);
}

[TestCase(0)]
Expand Down Expand Up @@ -90,7 +93,7 @@ public void DeserializesFromXml(int areaSpecificView, bool userContinousScaling,
</RoomWalkableArea>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
_roomWalkAbleArea = new RoomWalkableArea(doc.SelectSingleNode("RoomWalkableArea"));
_roomWalkAbleArea = new RoomWalkableArea(_changeNotification, doc.SelectSingleNode("RoomWalkableArea"));

Assert.That(_roomWalkAbleArea.AreaSpecificView, Is.EqualTo(areaSpecificView));
Assert.That(_roomWalkAbleArea.UseContinuousScaling, Is.EqualTo(userContinousScaling));
Expand Down
4 changes: 3 additions & 1 deletion Editor/AGS.Editor/AGSEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,11 @@ public class AGSEditor : IAGSEditorDirectories
* 4.00.00.03 - Distinct Character and Object Enabled and Visible properties;
* - FaceDirectionRatio
* 4.00.00.07 - Sprite.ImportColorDepth
* 4.00.00.08 - Custom properties supported by AudioClips, Dialogs, GUI,
* Regions, Walkable Areas
*
*/
public const int LATEST_XML_VERSION_INDEX = 4000007;
public const int LATEST_XML_VERSION_INDEX = 4000008;
/// <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
23 changes: 23 additions & 0 deletions Editor/AGS.Editor/DataFileWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1725,6 +1725,7 @@ public static bool SaveThisGameToFile(string fileName, Game game, CompileMessage
WriteExtension("v361_objnames", WriteExt_361ObjNames, writer, game, errors);
WriteExtension("ext_ags399", WriteExt_Ags399, writer, game, errors);
WriteExtension("v400_gameopts", WriteExt_400GameOpts, writer, game, errors);
WriteExtension("v400_customprops", WriteExt_400CustomProps, writer, game, errors);

// End of extensions list
writer.Write((byte)0xff);
Expand Down Expand Up @@ -1831,6 +1832,28 @@ private static void WriteExt_400GameOpts(BinaryWriter writer, Game game, Compile
writer.Write((int)0);
}

private static void WriteExt_400CustomProps(BinaryWriter writer, Game game, CompileMessages errors)
{
// Audio clip properties
writer.Write((int)game.AudioClips.Count);
for (int i = 0; i < game.AudioClips.Count; ++i)
{
CustomPropertiesWriter.Write(writer, game.AudioClips[i].Properties);
}
// Dialog properties
writer.Write((int)game.Dialogs.Count);
for (int i = 0; i < game.Dialogs.Count; ++i)
{
CustomPropertiesWriter.Write(writer, game.Dialogs[i].Properties);
}
// GUI properties
writer.Write((int)game.GUIs.Count);
for (int i = 0; i < game.GUIs.Count; ++i)
{
CustomPropertiesWriter.Write(writer, game.GUIs[i].Properties);
}
}

private delegate void WriteExtensionProc(BinaryWriter writer, Game game, CompileMessages errors);

private static void WriteExtension(string ext_id, WriteExtensionProc proc, BinaryWriter writer, Game game, CompileMessages errors)
Expand Down
6 changes: 1 addition & 5 deletions Editor/AGS.Editor/GUI/CustomPropertyBag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,7 @@ public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
List<PropertyDescriptor> descriptors = new List<PropertyDescriptor>();
foreach (CustomPropertySchemaItem item in _schema.PropertyDefinitions)
{
if (((_showPropertiesThatApplyTo == CustomPropertyAppliesTo.Characters) && (item.AppliesToCharacters)) ||
((_showPropertiesThatApplyTo == CustomPropertyAppliesTo.Hotspots) && (item.AppliesToHotspots)) ||
((_showPropertiesThatApplyTo == CustomPropertyAppliesTo.InventoryItems) && (item.AppliesToInvItems)) ||
((_showPropertiesThatApplyTo == CustomPropertyAppliesTo.Objects) && (item.AppliesToObjects)) ||
((_showPropertiesThatApplyTo == CustomPropertyAppliesTo.Rooms) && (item.AppliesToRooms)))
if ((_showPropertiesThatApplyTo & item.AppliesTo) != 0)
{
PropertyDescriptor descriptor = new CustomPropertyDescriptor(item, _properties);
descriptors.Add(descriptor);
Expand Down
Loading

0 comments on commit ee2a31f

Please sign in to comment.