コード例 #1
0
sint32 viewport_interaction_left_click(sint32 x, sint32 y)
{
    viewport_interaction_info info;

    switch (viewport_interaction_get_item_left(x, y, &info)) {
    case VIEWPORT_INTERACTION_ITEM_SPRITE:
        switch (info.sprite->unknown.sprite_identifier) {
        case SPRITE_IDENTIFIER_VEHICLE:
        {
            auto intent = Intent(WD_VEHICLE);
            intent.putExtra(INTENT_EXTRA_VEHICLE, info.vehicle);
            context_open_intent(&intent);
            break;
        }
        case SPRITE_IDENTIFIER_PEEP:
        {
            auto intent = Intent(WC_PEEP);
            intent.putExtra(INTENT_EXTRA_PEEP, info.peep);
            context_open_intent(&intent);
            break;
        }
        case SPRITE_IDENTIFIER_MISC:
            if (game_is_not_paused()) {
                switch (info.sprite->unknown.misc_identifier) {
                case SPRITE_MISC_BALLOON:
                    game_do_command(info.sprite->balloon.sprite_index, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_BALLOON_PRESS, 0, 0);
                    break;
                case SPRITE_MISC_DUCK:
                    duck_press(&info.sprite->duck);
                    break;
                }
            }
            break;
        }
        return 1;
    case VIEWPORT_INTERACTION_ITEM_RIDE:
    {
        auto intent = Intent(WD_TRACK);
        intent.putExtra(INTENT_EXTRA_TILE_ELEMENT, info.tileElement);
        context_open_intent(&intent);
        return true;
    }
    case VIEWPORT_INTERACTION_ITEM_PARK:
        context_open_window(WC_PARK_INFORMATION);
        return 1;
    default:
        return 0;
    }
}
コード例 #2
0
void LiveDanmuHandler::parseDataToDanmu(QByteArray data)
{
    if (!data.isNull() && !data.isEmpty())
    {
        QDataStream dataStream(&data, QIODevice::ReadOnly);
        qint64 dataLength = data.length();
        if (dataLength < 16)
        {
            emit actionPrepared(Intent(Intent::ACTION_LOG_ERROR,"接收到的数据异常"));
        }
        else if (dataLength > 16)
        {
            int givenLength;
            dataStream >> givenLength;
            if (dataLength == givenLength)
            {
                short param1, param2;
                int action, param4;
                dataStream >> param1 >> param2 >> action >> param4;
                action -= 1;
//                qDebug() << action;
                if (action == 2)
                {
                    int userCount;
                    dataStream >> userCount;
//                    qDebug() << userCount;
                    emit viewerCountChanged(userCount);
                }
コード例 #3
0
/**
 *
 *  rct2: 0x006CFEAC
 */
static void window_track_place_mouseup(rct_window *w, rct_widgetindex widgetIndex)
{
    switch (widgetIndex) {
    case WIDX_CLOSE:
        window_close(w);
        break;
    case WIDX_ROTATE:
        window_track_place_clear_provisional();
        _currentTrackPieceDirection = (_currentTrackPieceDirection + 1) & 3;
        window_invalidate(w);
        _window_track_place_last_x = -1;
        window_track_place_draw_mini_preview(_trackDesign);
        break;
    case WIDX_MIRROR:
        track_design_mirror(_trackDesign);
        _currentTrackPieceDirection = (0 - _currentTrackPieceDirection) & 3;
        window_invalidate(w);
        _window_track_place_last_x = -1;
        window_track_place_draw_mini_preview(_trackDesign);
        break;
    case WIDX_SELECT_DIFFERENT_DESIGN:
        window_close(w);

        auto intent = Intent(WC_TRACK_DESIGN_LIST);
        intent.putExtra(INTENT_EXTRA_RIDE_TYPE, _window_track_list_item.type);
        intent.putExtra(INTENT_EXTRA_RIDE_ENTRY_INDEX, _window_track_list_item.entry_index);
        context_open_intent(&intent);
        break;
    }
}
コード例 #4
0
    GameActionResult::Ptr Execute() const override
    {
        rct_banner* banner = &gBanners[_bannerIndex];

        utf8 *buffer = gCommonStringFormatBuffer;
        utf8 *dst = buffer;
        dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
        String::Set(dst, sizeof(gCommonStringFormatBuffer) - (dst - buffer), _name.c_str(), _name.size());

        rct_string_id string_id = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
        if (string_id == 0)
        {
            return MakeResult(GA_ERROR::NO_FREE_ELEMENTS, STR_ERR_CANT_SET_BANNER_TEXT);
        }

        rct_string_id prev_string_id = banner->string_idx;
        banner->string_idx = string_id;
        user_string_free(prev_string_id);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, _bannerIndex);
        context_broadcast_intent(&intent);

        return MakeResult();
    }
コード例 #5
0
/**
 *
 *  rct2: 0x006CFF34
 */
static void window_track_place_tooldown(rct_window* w, rct_widgetindex widgetIndex, sint32 x, sint32 y)
{
    sint32 i;
    sint16 mapX, mapY, mapZ;
    money32 cost;
    uint8 rideIndex;

    window_track_place_clear_provisional();
    map_invalidate_map_selection_tiles();
    gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
    gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
    gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;

    sub_68A15E(x, y, &mapX, &mapY, nullptr, nullptr);
    if (mapX == LOCATION_NULL)
        return;

    // Try increasing Z until a feasible placement is found
    mapZ = window_track_place_get_base_z(mapX, mapY);
    for (i = 0; i < 7; i++) {
        gDisableErrorWindowSound = true;
        window_track_place_attempt_placement(_trackDesign, mapX, mapY, mapZ, 1, &cost, &rideIndex);
        gDisableErrorWindowSound = false;

        if (cost != MONEY32_UNDEFINED) {
            window_close_by_class(WC_ERROR);
            audio_play_sound_at_location(SOUND_PLACE_ITEM, mapX, mapY, mapZ);

            _currentRideIndex = rideIndex;
            if (track_design_are_entrance_and_exit_placed()) {
                auto intent = Intent(WC_RIDE);
                intent.putExtra(INTENT_EXTRA_RIDE_ID, rideIndex);
                context_open_intent(&intent);
                window_close(w);
            } else {
                ride_initialise_construction_window(rideIndex);
                w = window_find_by_class(WC_RIDE_CONSTRUCTION);
                window_event_mouse_up_call(w, WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE);
            }
            return;
        }

        // Check if player did not have enough funds
        if (gGameCommandErrorText == STR_NOT_ENOUGH_CASH_REQUIRES)
            break;

        mapZ += 8;
    }

    // Unable to build track
    audio_play_sound_at_location(SOUND_ERROR, mapX, mapY, mapZ);
}
コード例 #6
0
ファイル: Banner.cpp プロジェクト: Gymnasiast/OpenRCT2
static money32 BannerSetColour(sint16 x, sint16 y, uint8 baseHeight, uint8 direction, uint8 colour, uint8 flags)
{
    gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING;
    sint32 z = (baseHeight * 8);
    gCommandPosition.x = x + 16;
    gCommandPosition.y = y + 16;
    gCommandPosition.z = z;

    if (!map_can_build_at(x, y, z - 16))
    {
        return MONEY32_UNDEFINED;
    }


    if (flags & GAME_COMMAND_FLAG_APPLY)
    {
        rct_tile_element* tileElement = map_get_first_element_at(x / 32, y / 32);

        bool found = false;
        do
        {
            if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_BANNER)
                continue;

            if (tileElement->properties.banner.position != direction)
                continue;

            found = true;
            break;
        } while (!tile_element_is_last_for_tile(tileElement++));

        if (!found)
        {
            return MONEY32_UNDEFINED;
        }

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, tileElement->properties.banner.index);
        context_broadcast_intent(&intent);

        gBanners[tileElement->properties.banner.index].colour = colour;
        map_invalidate_tile_zoom1(x, y, z, z + 32);
    }

    return 0;
}
コード例 #7
0
ファイル: TrackDesignSave.cpp プロジェクト: Wirlie/OpenRCT2
/**
 *
 *  rct2: 0x006D2804, 0x006D264D
 */
bool track_design_save(uint8 rideIndex)
{
    Ride* ride = get_ride(rideIndex);

    if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)){
        context_show_error(STR_CANT_SAVE_TRACK_DESIGN, gGameCommandErrorText);
        return false;
    }

    if (!ride_has_ratings(ride)) {
        context_show_error(STR_CANT_SAVE_TRACK_DESIGN, gGameCommandErrorText);
        return false;
    }

    _trackDesign = track_design_save_to_td6(rideIndex);
    if (_trackDesign == nullptr) {
        context_show_error(STR_CANT_SAVE_TRACK_DESIGN, gGameCommandErrorText);
        return false;
    }

    if (gTrackDesignSaveMode) {
        if (!track_design_save_copy_scenery_to_td6(_trackDesign)) {
            free(_trackDesign->track_elements);
            free(_trackDesign->entrance_elements);
            free(_trackDesign);
            return false;
        }
    }

    utf8 track_name[256];
    format_string(track_name, sizeof(track_name), ride->name, &ride->name_arguments);

    auto intent = Intent(WC_LOADSAVE);
    intent.putExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_SAVE | LOADSAVETYPE_TRACK);
    intent.putExtra(INTENT_EXTRA_PATH, std::string{track_name});
    intent.putExtra(INTENT_EXTRA_CALLBACK, (void *) track_design_save_callback);
    context_open_intent(&intent);

    return true;
}
コード例 #8
0
ファイル: Climate.cpp プロジェクト: Gymnasiast/OpenRCT2
/**
 * Weather & climate update iteration.
 * Gradually changes the weather parameters towards their determined next values.
 */
void climate_update()
{
    // Only do climate logic if playing (not in scenario editor or title screen)
    if (gScreenFlags & (~SCREEN_FLAGS_PLAYING)) return;

    if (!gCheatsFreezeClimate)
    {
        if (gClimateUpdateTimer)
        {
            if (gClimateUpdateTimer == 960)
            {
                auto intent = Intent(INTENT_ACTION_UPDATE_CLIMATE);
                context_broadcast_intent(&intent);
            }
            gClimateUpdateTimer--;
        }
        else if (!(gCurrentTicks & 0x7F))
        {
            if (gClimateCurrent.Temperature == gClimateNext.Temperature)
            {
                if (gClimateCurrent.WeatherGloom == gClimateNext.WeatherGloom)
                {
                    gClimateCurrent.WeatherEffect = gClimateNext.WeatherEffect;
                    _thunderTimer = 0;
                    _lightningTimer = 0;

                    if (gClimateCurrent.RainLevel == gClimateNext.RainLevel)
                    {
                        gClimateCurrent.Weather = gClimateNext.Weather;
                        climate_determine_future_weather(scenario_rand());
                        auto intent = Intent(INTENT_ACTION_UPDATE_CLIMATE);
                        context_broadcast_intent(&intent);
                    }
                    else if (gClimateNext.RainLevel <= RAIN_LEVEL_HEAVY)
                    {
                        gClimateCurrent.RainLevel = climate_step_weather_level(gClimateCurrent.RainLevel, gClimateNext.RainLevel);
                    }
                }
                else
                {
                    gClimateCurrent.WeatherGloom = climate_step_weather_level(gClimateCurrent.WeatherGloom, gClimateNext.WeatherGloom);
                    gfx_invalidate_screen();
                }
            }
            else
            {
                gClimateCurrent.Temperature = climate_step_weather_level(gClimateCurrent.Temperature, gClimateNext.Temperature);
                auto intent = Intent(INTENT_ACTION_UPDATE_CLIMATE);
                context_broadcast_intent(&intent);
            }
        }

    }

    if (_thunderTimer != 0)
    {
        climate_update_lightning();
        climate_update_thunder();
    }
    else if (gClimateCurrent.WeatherEffect == WEATHER_EFFECT_STORM)
    {
        // Create new thunder and lightning
        uint32 randomNumber = util_rand();
        if ((randomNumber & 0xFFFF) <= 0x1B4)
        {
            randomNumber >>= 16;
            _thunderTimer = 43 + (randomNumber % 64);
            _lightningTimer = randomNumber % 32;
        }
コード例 #9
0
ファイル: Banner.cpp プロジェクト: Gymnasiast/OpenRCT2
static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags)
{
    if (bannerIndex >= MAX_BANNERS)
    {
        gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS;
        return MONEY32_UNDEFINED;
    }

    rct_banner* banner = &gBanners[bannerIndex];

    rct_tile_element* tileElement = banner_get_tile_element(bannerIndex);

    if (tileElement == nullptr)
    {
        return MONEY32_UNDEFINED;
    }

    if (!(flags & GAME_COMMAND_FLAG_APPLY))
    {
        return 0;
    }

    banner->colour = colour;
    banner->text_colour = textColour;
    banner->flags = bannerFlags;

    tileElement->properties.banner.flags = 0xFF;
    if (banner->flags & BANNER_FLAG_NO_ENTRY)
    {
        tileElement->properties.banner.flags &= ~(1 << tileElement->properties.banner.position);
    }

    sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;

    utf8 buffer[256];
    format_string(buffer, 256, banner->string_idx, nullptr);
    sint32 firstCodepoint = utf8_get_next(buffer, nullptr);
    if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END)
    {
        utf8_write_codepoint(buffer, colourCodepoint);
    }
    else
    {
        utf8_insert_codepoint(buffer, colourCodepoint);
    }

    rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
    if (stringId != 0)
    {
        rct_string_id prevStringId = banner->string_idx;
        banner->string_idx = stringId;
        user_string_free(prevStringId);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex);
        context_broadcast_intent(&intent);
    }
    else
    {
        gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
        return MONEY32_UNDEFINED;
    }

    return 0;
}
コード例 #10
0
ファイル: Banner.cpp プロジェクト: Gymnasiast/OpenRCT2
static money32 BannerSetName(uint8 bannerIndex,
    uint16 nameChunkIndex,
    uint32 nameChunk1,
    uint32 nameChunk2,
    uint32 nameChunk3,
    uint8 flags)
{
    static char newName[128];

    if (bannerIndex >= MAX_BANNERS)
    {
        log_warning("Invalid game command for setting banner name, banner id = %d", bannerIndex);
        return MONEY32_UNDEFINED;
    }
    rct_banner* banner = &gBanners[bannerIndex];

    gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS;
    size_t indexToOffset[3] = { 24, 0, 12 };

    if (nameChunkIndex > Util::CountOf(indexToOffset))
    {
        log_warning("Invalid chunk index for setting banner name, banner id = %d, index = %d", bannerIndex, nameChunkIndex);
        return MONEY32_UNDEFINED;
    }

    size_t nameChunkOffset = std::min<size_t>(indexToOffset[nameChunkIndex], Util::CountOf(newName) - 12);
    std::memcpy(&newName[0 + nameChunkOffset], &nameChunk1, sizeof(uint32));
    std::memcpy(&newName[4 + nameChunkOffset], &nameChunk2, sizeof(uint32));
    std::memcpy(&newName[8 + nameChunkOffset], &nameChunk3, sizeof(uint32));

    if (nameChunkIndex != 0)
    {
        return 0;
    }

    if (!(flags & GAME_COMMAND_FLAG_APPLY))
    {
        return 0;
    }

    utf8 *buffer = gCommonStringFormatBuffer;
    utf8 *dst = buffer;
    dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
    String::Set(dst, 256, newName, 32);

    rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
    if (stringId != 0)
    {
        rct_string_id prevStringId = banner->string_idx;
        banner->string_idx = stringId;
        user_string_free(prevStringId);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex);
        context_broadcast_intent(&intent);
    }
    else
    {
        gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
        return MONEY32_UNDEFINED;
    }

    return 0;
}
コード例 #11
0
ファイル: TitleEditor.cpp プロジェクト: Wirlie/OpenRCT2
static void window_title_editor_mouseup(rct_window * w, rct_widgetindex widgetIndex)
{
    bool commandEditorOpen = (window_find_by_class(WC_TITLE_COMMAND_EDITOR) != nullptr);
    switch (widgetIndex)
    {
    case WIDX_TITLE_EDITOR_CLOSE:
        window_close(w);
        break;

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Presets tab
    //////////////////////////////////////////////////////////////////////////////////////////////////////
    case WIDX_TITLE_EDITOR_NEW_BUTTON:
        if (!commandEditorOpen)
        {
            // TODO: This should probably be 'NEW'
            window_text_input_open(w, widgetIndex, STR_TITLE_EDITOR_ACTION_DUPLICATE, STR_TITLE_EDITOR_ENTER_NAME_FOR_SEQUENCE, STR_NONE, 0, 64);
        }
        break;
    case WIDX_TITLE_EDITOR_DUPLICATE_BUTTON:
        if (!commandEditorOpen && _editingTitleSequence != nullptr)
        {
            window_text_input_open(w, widgetIndex, STR_TITLE_EDITOR_ACTION_DUPLICATE, STR_TITLE_EDITOR_ENTER_NAME_FOR_SEQUENCE, STR_STRING, (uintptr_t)_sequenceName, 64);
        }
        break;
    case WIDX_TITLE_EDITOR_DELETE_BUTTON:
        if (window_title_editor_check_can_edit())
        {
            title_sequence_manager_delete(_selectedTitleSequence);
            window_title_editor_load_sequence(0);
        }
        break;
    case WIDX_TITLE_EDITOR_RENAME_BUTTON:
        if (window_title_editor_check_can_edit() && _editingTitleSequence != nullptr)
        {
            window_text_input_open(w, widgetIndex, STR_TRACK_MANAGE_RENAME, STR_TITLE_EDITOR_ENTER_NAME_FOR_SEQUENCE, STR_STRING, (uintptr_t)_sequenceName, 64);
        }
        break;

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Editor tab
    //////////////////////////////////////////////////////////////////////////////////////////////////////
    case WIDX_TITLE_EDITOR_ADD_SAVE:
        if (!_isSequenceReadOnly && !title_is_previewing_sequence() && !commandEditorOpen)
        {
            auto intent = Intent(WC_LOADSAVE);
            intent.putExtra(INTENT_EXTRA_LOADSAVE_TYPE, LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME);
            intent.putExtra(INTENT_EXTRA_CALLBACK, (void *) window_title_editor_add_park_callback);
            context_open_intent(&intent);
        }
        break;
    case WIDX_TITLE_EDITOR_REMOVE_SAVE:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item != -1)
            {
                TitleSequenceRemovePark(_editingTitleSequence, w->selected_list_item);
                if (w->selected_list_item >= (sint16)_editingTitleSequence->NumSaves)
                {
                    w->selected_list_item--;
                }
            }
        }
        break;
    case WIDX_TITLE_EDITOR_RENAME_SAVE:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item != -1)
            {
                window_text_input_open(w, widgetIndex, STR_FILEBROWSER_RENAME_SAVE_TITLE, STR_TITLE_EDITOR_ENTER_NAME_FOR_SAVE, STR_STRING, (uintptr_t)_editingTitleSequence->Saves[w->selected_list_item], 52 - 1);
            }
        }
        break;
    case WIDX_TITLE_EDITOR_LOAD_SAVE:
        if (w->selected_list_item >= 0 && w->selected_list_item < (sint16)_editingTitleSequence->NumSaves)
        {
            auto handle = TitleSequenceGetParkHandle(_editingTitleSequence, w->selected_list_item);
            auto stream = (IStream *)handle->Stream;
            auto hintPath = String::ToStd(handle->HintPath);

            bool isScenario = ParkImporter::ExtensionIsScenario(hintPath);
            auto objectMgr = OpenRCT2::GetContext()->GetObjectManager();
            auto parkImporter = std::unique_ptr<IParkImporter>(ParkImporter::Create(hintPath));
            auto result = parkImporter->LoadFromStream(stream, isScenario);
            objectMgr->LoadObjects(result.RequiredObjects.data(), result.RequiredObjects.size());
            parkImporter->Import();

            if (isScenario)
                scenario_begin();
            else
                game_load_init();

            TitleSequenceCloseParkHandle(handle);
            window_title_editor_open(WINDOW_TITLE_EDITOR_TAB_SAVES);
        }
        break;

    //////////////////////////////////////////////////////////////////////////////////////////////////////
    // Commands tab
    //////////////////////////////////////////////////////////////////////////////////////////////////////
    case WIDX_TITLE_EDITOR_INSERT:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item != -1)
                window_title_command_editor_open(_editingTitleSequence, w->selected_list_item + 1, true);
            else
                window_title_command_editor_open(_editingTitleSequence, (sint32)_editingTitleSequence->NumCommands, true);
        }
        break;
    case WIDX_TITLE_EDITOR_EDIT:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_editingTitleSequence->NumCommands)
            {
                window_title_command_editor_open(_editingTitleSequence, w->selected_list_item, false);
            }
        }
        break;
    case WIDX_TITLE_EDITOR_DELETE:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_editingTitleSequence->NumCommands)
            {
                for (sint32 i = w->selected_list_item; i < (sint16)_editingTitleSequence->NumCommands - 1; i++)
                {
                    _editingTitleSequence->Commands[i] = _editingTitleSequence->Commands[i + 1];
                }
                _editingTitleSequence->NumCommands--;
                if (w->selected_list_item >= (sint16)_editingTitleSequence->NumCommands)
                {
                    w->selected_list_item--;
                }
                TitleSequenceSave(_editingTitleSequence);
            }
        }
        break;
    case WIDX_TITLE_EDITOR_SKIP_TO:
    {
        sint32 position = w->selected_list_item;
        if (title_is_previewing_sequence() && position != -1 && position < (sint32)_editingTitleSequence->NumCommands)
        {
            ITitleSequencePlayer * player = window_title_editor_get_player();
            title_sequence_player_seek(player, position);
            title_sequence_player_update(player);
        }
        break;
    }
    case WIDX_TITLE_EDITOR_MOVE_DOWN:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item != -1 && w->selected_list_item < (sint16)_editingTitleSequence->NumCommands - 1)
            {
                TitleCommand * a = &_editingTitleSequence->Commands[w->selected_list_item];
                TitleCommand * b = &_editingTitleSequence->Commands[w->selected_list_item + 1];
                TitleCommand tmp = *a;
                *a = *b;
                *b = tmp;
                w->selected_list_item++;
                TitleSequenceSave(_editingTitleSequence);
            }
        }
        break;
    case WIDX_TITLE_EDITOR_MOVE_UP:
        if (window_title_editor_check_can_edit())
        {
            if (w->selected_list_item > 0 && w->selected_list_item < (sint16)_editingTitleSequence->NumCommands)
            {
                TitleCommand * a = &_editingTitleSequence->Commands[w->selected_list_item - 1];
                TitleCommand * b = &_editingTitleSequence->Commands[w->selected_list_item];
                TitleCommand tmp = *b;
                *b = *a;
                *a = tmp;
                w->selected_list_item--;
                TitleSequenceSave(_editingTitleSequence);
            }
        }
        break;
    case WIDX_TITLE_EDITOR_REPLAY:
        if (title_is_previewing_sequence())
        {
            ITitleSequencePlayer * player = window_title_editor_get_player();
            title_sequence_player_reset(player);
            title_sequence_player_update(player);
        }
        break;
    case WIDX_TITLE_EDITOR_STOP:
        if (title_is_previewing_sequence())
        {
            title_stop_previewing_sequence();
        }
        break;
    case WIDX_TITLE_EDITOR_PLAY:
        if (!title_is_previewing_sequence() || _selectedTitleSequence != title_get_current_sequence())
        {
            if (!title_preview_sequence(_selectedTitleSequence))
            {
                context_show_error(STR_ERR_FAILED_TO_LOAD_TITLE_SEQUENCE, STR_NONE);
            }
            else if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO))
            {
                gPreviewingTitleSequenceInGame = true;
            }
        }
        break;
    case WIDX_TITLE_EDITOR_SKIP:
        if (title_is_previewing_sequence())
        {
            ITitleSequencePlayer * player = window_title_editor_get_player();
            sint32 position = title_sequence_player_get_current_position(player) + 1;
            if (position >= (sint32)_editingTitleSequence->NumCommands)
            {
                position = 0;
            }
            title_sequence_player_seek(player, position);
            title_sequence_player_update(player);
        }
        break;
    }
}