Initial commit
This commit is contained in:
286
engines/ags/shared/game/room_struct.cpp
Normal file
286
engines/ags/shared/game/room_struct.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ags/shared/ac/common.h" // quit
|
||||
#include "ags/shared/game/room_file.h"
|
||||
#include "ags/shared/game/room_struct.h"
|
||||
#include "ags/shared/gfx/bitmap.h"
|
||||
|
||||
namespace AGS3 {
|
||||
namespace AGS {
|
||||
namespace Shared {
|
||||
|
||||
RoomOptions::RoomOptions()
|
||||
: StartupMusic(0)
|
||||
, SaveLoadDisabled(false)
|
||||
, PlayerCharOff(false)
|
||||
, PlayerView(0)
|
||||
, MusicVolume(kRoomVolumeNormal)
|
||||
, Flags(0) {
|
||||
}
|
||||
|
||||
RoomBgFrame::RoomBgFrame()
|
||||
: IsPaletteShared(false) {
|
||||
memset(Palette, 0, sizeof(Palette));
|
||||
}
|
||||
|
||||
RoomEdges::RoomEdges()
|
||||
: Left(0)
|
||||
, Right(0)
|
||||
, Top(0)
|
||||
, Bottom(0) {
|
||||
}
|
||||
|
||||
RoomEdges::RoomEdges(int l, int r, int t, int b)
|
||||
: Left(l)
|
||||
, Right(r)
|
||||
, Top(t)
|
||||
, Bottom(b) {
|
||||
}
|
||||
|
||||
RoomObjectInfo::RoomObjectInfo()
|
||||
: Sprite(0)
|
||||
, X(0)
|
||||
, Y(0)
|
||||
, Room(-1)
|
||||
, IsOn(false)
|
||||
, Baseline(0xFF)
|
||||
, Flags(0) {
|
||||
}
|
||||
|
||||
RoomRegion::RoomRegion()
|
||||
: Light(0)
|
||||
, Tint(0) {
|
||||
}
|
||||
|
||||
WalkArea::WalkArea()
|
||||
: CharacterView(0)
|
||||
, ScalingFar(0)
|
||||
, ScalingNear(NOT_VECTOR_SCALED)
|
||||
, PlayerView(0)
|
||||
, Top(-1)
|
||||
, Bottom(-1) {
|
||||
}
|
||||
|
||||
WalkBehind::WalkBehind()
|
||||
: Baseline(0) {
|
||||
}
|
||||
|
||||
MessageInfo::MessageInfo()
|
||||
: DisplayAs(0)
|
||||
, Flags(0) {
|
||||
}
|
||||
|
||||
RoomStruct::RoomStruct() {
|
||||
InitDefaults();
|
||||
}
|
||||
|
||||
RoomStruct::~RoomStruct() {
|
||||
Free();
|
||||
}
|
||||
|
||||
void RoomStruct::Free() {
|
||||
for (size_t i = 0; i < (size_t)MAX_ROOM_BGFRAMES; ++i)
|
||||
BgFrames[i].Graphic.reset();
|
||||
HotspotMask.reset();
|
||||
RegionMask.reset();
|
||||
WalkAreaMask.reset();
|
||||
WalkBehindMask.reset();
|
||||
|
||||
LocalVariables.clear();
|
||||
Interaction.reset();
|
||||
Properties.clear();
|
||||
for (size_t i = 0; i < (size_t)MAX_ROOM_HOTSPOTS; ++i) {
|
||||
Hotspots[i].Interaction.reset();
|
||||
Hotspots[i].Properties.clear();
|
||||
}
|
||||
Objects.clear();
|
||||
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i) {
|
||||
Regions[i].Interaction.reset();
|
||||
Regions[i].Properties.clear();
|
||||
}
|
||||
|
||||
FreeMessages();
|
||||
FreeScripts();
|
||||
}
|
||||
|
||||
void RoomStruct::FreeMessages() {
|
||||
for (size_t i = 0; i < MessageCount; ++i) {
|
||||
Messages[i].Free();
|
||||
MessageInfos[i] = MessageInfo();
|
||||
}
|
||||
MessageCount = 0;
|
||||
}
|
||||
|
||||
void RoomStruct::FreeScripts() {
|
||||
CompiledScript.reset();
|
||||
|
||||
EventHandlers.reset();
|
||||
for (size_t i = 0; i < HotspotCount; ++i)
|
||||
Hotspots[i].EventHandlers.reset();
|
||||
for (auto &obj : Objects)
|
||||
obj.EventHandlers.reset();
|
||||
for (size_t i = 0; i < RegionCount; ++i)
|
||||
Regions[i].EventHandlers.reset();
|
||||
}
|
||||
|
||||
void RoomStruct::InitDefaults() {
|
||||
DataVersion = kRoomVersion_Current;
|
||||
GameID = NO_GAME_ID_IN_ROOM_FILE;
|
||||
|
||||
_resolution = kRoomRealRes;
|
||||
MaskResolution = 1;
|
||||
Width = 320;
|
||||
Height = 200;
|
||||
|
||||
Options = RoomOptions();
|
||||
Edges = RoomEdges(0, 317, 40, 199);
|
||||
|
||||
BgFrameCount = 1;
|
||||
HotspotCount = 0;
|
||||
RegionCount = 0;
|
||||
WalkAreaCount = 0;
|
||||
WalkBehindCount = 0;
|
||||
MessageCount = 0;
|
||||
|
||||
for (size_t i = 0; i < (size_t)MAX_ROOM_HOTSPOTS; ++i)
|
||||
Hotspots[i] = RoomHotspot();
|
||||
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i)
|
||||
Regions[i] = RoomRegion();
|
||||
for (size_t i = 0; i < (size_t)MAX_WALK_AREAS; ++i)
|
||||
WalkAreas[i] = WalkArea();
|
||||
for (size_t i = 0; i < (size_t)MAX_WALK_BEHINDS; ++i)
|
||||
WalkBehinds[i] = WalkBehind();
|
||||
|
||||
BackgroundBPP = 1;
|
||||
BgAnimSpeed = 5;
|
||||
|
||||
memset(Palette, 0, sizeof(Palette));
|
||||
}
|
||||
|
||||
void RoomStruct::SetResolution(RoomResolutionType type) {
|
||||
_resolution = type;
|
||||
}
|
||||
|
||||
Bitmap *RoomStruct::GetMask(RoomAreaMask mask) const {
|
||||
switch (mask) {
|
||||
case kRoomAreaHotspot: return HotspotMask.get();
|
||||
case kRoomAreaWalkBehind: return WalkBehindMask.get();
|
||||
case kRoomAreaWalkable: return WalkAreaMask.get();
|
||||
case kRoomAreaRegion: return RegionMask.get();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
float RoomStruct::GetMaskScale(RoomAreaMask mask) const {
|
||||
switch (mask) {
|
||||
case kRoomAreaWalkBehind: return 1.f; // walk-behinds always 1:1 with room size
|
||||
case kRoomAreaHotspot:
|
||||
case kRoomAreaWalkable:
|
||||
case kRoomAreaRegion:
|
||||
return 1.f / MaskResolution;
|
||||
default:
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
bool RoomStruct::HasRegionLightLevel(int id) const {
|
||||
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
||||
return Regions[id].Tint == 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RoomStruct::HasRegionTint(int id) const {
|
||||
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
||||
return Regions[id].Tint != 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int RoomStruct::GetRegionLightLevel(int id) const {
|
||||
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
||||
return HasRegionLightLevel(id) ? Regions[id].Light : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RoomStruct::GetRegionTintLuminance(int id) const {
|
||||
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
||||
return HasRegionTint(id) ? (Regions[id].Light * 10) / 25 : 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void load_room(const String &filename, RoomStruct *room, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos) {
|
||||
room->Free();
|
||||
room->InitDefaults();
|
||||
|
||||
RoomDataSource src;
|
||||
HRoomFileError err = OpenRoomFileFromAsset(filename, src);
|
||||
if (err) {
|
||||
err = ReadRoomData(room, src.InputStream.get(), src.DataVersion);
|
||||
if (err)
|
||||
err = UpdateRoomData(room, src.DataVersion, game_is_hires, sprinfos);
|
||||
}
|
||||
if (!err)
|
||||
quitprintf("Unable to load the room file '%s'.\n%s.", filename.GetCStr(), err->FullMessage().GetCStr());
|
||||
}
|
||||
|
||||
PBitmap FixBitmap(PBitmap bmp, int width, int height) {
|
||||
Bitmap *new_bmp = BitmapHelper::AdjustBitmapSize(bmp.get(), width, height);
|
||||
if (new_bmp != bmp.get())
|
||||
return PBitmap(new_bmp);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
void UpscaleRoomBackground(RoomStruct *room, bool game_is_hires) {
|
||||
if (room->DataVersion >= kRoomVersion_303b || !game_is_hires)
|
||||
return;
|
||||
for (size_t i = 0; i < room->BgFrameCount; ++i)
|
||||
room->BgFrames[i].Graphic = FixBitmap(room->BgFrames[i].Graphic, room->Width, room->Height);
|
||||
FixRoomMasks(room);
|
||||
}
|
||||
|
||||
void FixRoomMasks(RoomStruct *room) {
|
||||
if (room->MaskResolution <= 0)
|
||||
return;
|
||||
Bitmap *bkg = room->BgFrames[0].Graphic.get();
|
||||
if (bkg == nullptr)
|
||||
return;
|
||||
// TODO: this issue is somewhat complicated. Original code was relying on
|
||||
// room->Width and Height properties. But in the engine these are saved
|
||||
// already converted to data resolution which may be "low-res". Since this
|
||||
// function is shared between engine and editor we do not know if we need
|
||||
// to upscale them.
|
||||
// For now room width/height is always equal to background bitmap.
|
||||
int base_width = bkg->GetWidth();
|
||||
int base_height = bkg->GetHeight();
|
||||
int low_width = base_width / room->MaskResolution;
|
||||
int low_height = base_height / room->MaskResolution;
|
||||
|
||||
// Walk-behinds are always 1:1 of the primary background.
|
||||
// Other masks are 1:x where X is MaskResolution.
|
||||
room->WalkBehindMask = FixBitmap(room->WalkBehindMask, base_width, base_height);
|
||||
room->HotspotMask = FixBitmap(room->HotspotMask, low_width, low_height);
|
||||
room->RegionMask = FixBitmap(room->RegionMask, low_width, low_height);
|
||||
room->WalkAreaMask = FixBitmap(room->WalkAreaMask, low_width, low_height);
|
||||
}
|
||||
|
||||
} // namespace Shared
|
||||
} // namespace AGS
|
||||
} // namespace AGS3
|
||||
Reference in New Issue
Block a user