28
28
#include "Systems/Base/GraphicsSystem.hpp"
30
31
#include <algorithm>
31
32
#include <boost/algorithm/string.hpp>
32
33
#include <boost/archive/text_iarchive.hpp>
33
34
#include <boost/archive/text_oarchive.hpp>
35
#include <boost/bind.hpp>
34
36
#include <boost/lexical_cast.hpp>
35
37
#include <boost/serialization/deque.hpp>
36
38
#include <boost/serialization/scoped_ptr.hpp>
37
39
#include <boost/serialization/vector.hpp>
40
#include <boost/tuple/tuple.hpp>
41
#include <boost/tuple/tuple_comparison.hpp>
39
43
#include <iterator>
45
50
#include "base/notification_service.h"
51
56
#include "Modules/Module_Grp.hpp"
52
57
#include "Systems/Base/AnmGraphicsObjectData.hpp"
53
58
#include "Systems/Base/CGMTable.hpp"
59
#include "Systems/Base/EventSystem.hpp"
54
60
#include "Systems/Base/GraphicsObject.hpp"
55
61
#include "Systems/Base/GraphicsObjectData.hpp"
56
62
#include "Systems/Base/GraphicsObjectOfFile.hpp"
57
63
#include "Systems/Base/GraphicsStackFrame.hpp"
64
#include "Systems/Base/HIKRenderer.hpp"
58
65
#include "Systems/Base/HIKScript.hpp"
59
66
#include "Systems/Base/MouseCursor.hpp"
67
#include "Systems/Base/ObjectMutator.hpp"
60
68
#include "Systems/Base/ObjectSettings.hpp"
61
69
#include "Systems/Base/Surface.hpp"
62
70
#include "Systems/Base/System.hpp"
217
230
: screen_update_mode_(SCREENUPDATEMODE_AUTOMATIC),
218
231
background_type_(BACKGROUND_DC0),
219
232
screen_needs_refresh_(false),
233
object_state_dirty_(false),
220
234
is_responsible_for_update_(true),
221
235
display_subtitle_(gameexe("SUBTITLE").to_int(0)),
222
236
hide_interface_(false),
223
237
globals_(gameexe),
238
time_at_last_queue_change_(0),
224
239
graphics_object_settings_(new GraphicsObjectSettings(gameexe)),
225
240
graphics_object_impl_(new GraphicsObjectImpl(
226
241
graphics_object_settings_->objects_in_a_layer)),
227
242
use_custom_mouse_cursor_(gameexe("MOUSE_CURSOR").exists()),
228
243
show_cursor_from_bytecode_(true),
229
244
cursor_(gameexe("MOUSE_CURSOR").to_int(0)),
246
preloaded_hik_scripts_(32),
232
250
// -----------------------------------------------------------------------
282
300
// -----------------------------------------------------------------------
302
void GraphicsSystem::QueueShakeSpec(int spec) {
303
Gameexe& gameexe = system().gameexe();
305
if (gameexe("SHAKE", spec).exists()) {
306
vector<int> spec_vector = gameexe("SHAKE", spec).to_intVector();
309
vector<int>::const_iterator it = spec_vector.begin();
310
while (it != spec_vector.end()) {
312
if (it != spec_vector.end()) {
314
if (it != spec_vector.end()) {
316
screen_shake_queue_.push(std::make_pair(Point(x, y), time));
322
time_at_last_queue_change_ = system().event().getTicks();
326
// -----------------------------------------------------------------------
328
Point GraphicsSystem::GetScreenOrigin() {
329
if (screen_shake_queue_.empty()) {
332
return screen_shake_queue_.front().first;
336
// -----------------------------------------------------------------------
338
bool GraphicsSystem::IsShaking() const {
339
return !screen_shake_queue_.empty();
342
// -----------------------------------------------------------------------
344
int GraphicsSystem::CurrentShakingFrameTime() const {
345
if (screen_shake_queue_.empty()) {
348
return screen_shake_queue_.front().second;
353
// -----------------------------------------------------------------------
284
355
int GraphicsSystem::useCustomCursor() {
285
356
return use_custom_mouse_cursor_ &&
286
357
system().gameexe()("MOUSE_CURSOR", cursor_, "NAME").to_string("") != "";
491
556
system().text().render(tree);
559
// -----------------------------------------------------------------------
494
561
void GraphicsSystem::executeGraphicsSystem(RLMachine& machine) {
495
if (hik_script_ && background_type_ == BACKGROUND_HIK)
496
hik_script_->execute(machine);
562
// Check to see if any of the graphics objects are reporting that
563
// they want to force a redraw
564
for_each(foregroundObjects().allocated_begin(),
565
foregroundObjects().allocated_end(),
566
bind(&GraphicsObject::execute, _1, boost::ref(machine)));
569
mouse_cursor_->execute(system());
571
if (hik_renderer_ && background_type_ == BACKGROUND_HIK)
572
hik_renderer_->execute(machine);
574
// Possibly update the screen shaking state
575
if (!screen_shake_queue_.empty()) {
576
unsigned int now = system().event().getTicks();
577
unsigned int accumulated_ticks = now - time_at_last_queue_change_;
578
while (!screen_shake_queue_.empty() &&
579
accumulated_ticks > screen_shake_queue_.front().second) {
580
int frame_ticks = screen_shake_queue_.front().second;
581
accumulated_ticks -= frame_ticks;
582
time_at_last_queue_change_ += frame_ticks;
583
screen_shake_queue_.pop();
499
589
// -----------------------------------------------------------------------
518
610
hide_interface_ = false;
613
boost::shared_ptr<const Surface> GraphicsSystem::GetEmojiSurface() {
614
GameexeFilteringIterator it = system().gameexe().filtering_begin("E_MOJI.");
615
GameexeFilteringIterator end = system().gameexe().filtering_end();
616
for (; it != end; ++it) {
617
// Try to interpret each key as a filename.
618
std::string file_name = it->to_string("");
619
boost::shared_ptr<const Surface> surface = getSurfaceNamed(file_name);
624
return boost::shared_ptr<const Surface>();
627
void GraphicsSystem::PreloadHIKScript(
630
const std::string& name,
631
const boost::filesystem::path& file_path) {
632
HIKScript* script = new HIKScript(system, file_path);
633
script->EnsureUploaded();
635
preloaded_hik_scripts_[slot] = std::make_pair(
636
name, boost::shared_ptr<HIKScript>(script));
639
void GraphicsSystem::ClearPreloadedHIKScript(int slot) {
640
preloaded_hik_scripts_[slot] =
641
std::make_pair("", boost::shared_ptr<HIKScript>());
644
void GraphicsSystem::ClearAllPreloadedHIKScripts() {
645
preloaded_hik_scripts_.clear();
648
boost::shared_ptr<HIKScript> GraphicsSystem::GetHIKScript(
650
const std::string& name,
651
const boost::filesystem::path& file_path) {
652
AllocatedLazyArrayIterator<HIKArrayItem> it =
653
preloaded_hik_scripts_.allocated_begin();
654
AllocatedLazyArrayIterator<HIKArrayItem> end =
655
preloaded_hik_scripts_.allocated_end();
656
for (; it != end; ++it) {
657
if (it->first == name)
661
return boost::shared_ptr<HIKScript>(new HIKScript(system, file_path));
664
void GraphicsSystem::PreloadG00(int slot, const std::string& name) {
665
// We first check our implicit cache just in case so we don't load it twice.
666
boost::shared_ptr<const Surface> surface = image_cache_.fetch(name);
668
surface = loadSurfaceFromFile(name);
671
surface->EnsureUploaded();
673
preloaded_g00_[slot] = std::make_pair(name, surface);
676
void GraphicsSystem::ClearPreloadedG00(int slot) {
677
preloaded_g00_[slot] =
678
std::make_pair("", boost::shared_ptr<const Surface>());
681
void GraphicsSystem::ClearAllPreloadedG00() {
682
preloaded_g00_.clear();
685
boost::shared_ptr<const Surface> GraphicsSystem::GetPreloadedG00(
686
const std::string& name) {
687
AllocatedLazyArrayIterator<G00ArrayItem> it =
688
preloaded_g00_.allocated_begin();
689
AllocatedLazyArrayIterator<G00ArrayItem> end =
690
preloaded_g00_.allocated_end();
691
for (; it != end; ++it) {
692
if (it->first == name)
696
return boost::shared_ptr<const Surface>();
521
699
// -----------------------------------------------------------------------
523
boost::shared_ptr<Surface> GraphicsSystem::loadSurfaceFromFile(
701
boost::shared_ptr<const Surface> GraphicsSystem::getSurfaceNamedAndMarkViewed(
524
702
RLMachine& machine, const std::string& short_filename) {
525
703
// Record that we viewed this CG.
526
704
cgTable().setViewed(machine, short_filename);
528
return loadNonCGSurfaceFromFile(short_filename);
706
return getSurfaceNamed(short_filename);
709
// -----------------------------------------------------------------------
711
boost::shared_ptr<const Surface> GraphicsSystem::getSurfaceNamed(
712
const std::string& short_filename) {
713
// Check if this is in the script controlled cache.
714
boost::shared_ptr<const Surface> cached_surface =
715
GetPreloadedG00(short_filename);
717
return cached_surface;
719
// First check to see if this surface is already in our internal cache
720
cached_surface = image_cache_.fetch(short_filename);
722
return cached_surface;
724
boost::shared_ptr<const Surface> surface_to_ret =
725
loadSurfaceFromFile(short_filename);
726
image_cache_.insert(short_filename, surface_to_ret);
727
return surface_to_ret;
531
730
// -----------------------------------------------------------------------
655
861
// -----------------------------------------------------------------------
657
863
void GraphicsSystem::renderObjects(std::ostream* tree) {
658
// Render all visible foreground objects
864
// The tuple is order, layer, depth, objid, GraphicsObject. Tuples are easy
866
typedef std::vector<boost::tuple<int, int, int, int, GraphicsObject*> >
868
ToRenderVec to_render;
870
// Collate all objects that we might want to render.
659
871
AllocatedLazyArrayIterator<GraphicsObject> it =
660
872
graphics_object_impl_->foreground_objects.allocated_begin();
661
873
AllocatedLazyArrayIterator<GraphicsObject> end =
671
883
else if (settings.space_key && interfaceHidden())
674
it->render(it.pos(), tree);
886
to_render.push_back(boost::make_tuple(
887
it->zOrder(), it->zLayer(), it->zDepth(), it.pos(), &*it));
890
// Sort by all the ordering values.
891
std::sort(to_render.begin(), to_render.end());
893
for (ToRenderVec::iterator it = to_render.begin(); it != to_render.end();
895
it->get<4>()->render(it->get<3>(), NULL, tree);
686
907
if (it != cursor_cache_.end()) {
687
908
mouse_cursor_ = it->second;
689
boost::shared_ptr<Surface> cursor_surface;
690
GameexeInterpretObject cursor_key =
691
system().gameexe()("MOUSE_CURSOR", cursor_, "NAME");
693
if (cursor_key.exists()) {
694
cursor_surface = loadNonCGSurfaceFromFile(cursor_key);
695
mouse_cursor_.reset(new MouseCursor(cursor_surface));
910
boost::shared_ptr<const Surface> cursor_surface;
911
GameexeInterpretObject cursor =
912
system().gameexe()("MOUSE_CURSOR", cursor_);
913
GameexeInterpretObject name_key = cursor("NAME");
915
if (name_key.exists()) {
916
int count = cursor("CONT").to_int(1);
917
int speed = cursor("SPEED").to_int(800);
919
cursor_surface = getSurfaceNamed(name_key);
921
new MouseCursor(system(), cursor_surface, count, speed));
696
922
cursor_cache_[cursor_] = mouse_cursor_;
698
924
mouse_cursor_.reset();