text:
<link rel="stylesheet" href="../css/tcp_endpoint_info.css" crossorigin="anonymous" />
<link rel="stylesheet" href="../css/alert_fade.css" crossorigin="anonymous" />
<link rel="stylesheet" href="../css/lib/codemirror/codemirror.css" crossorigin="anonymous" />
<link rel="stylesheet" href="../css/lib/codemirror/lint.css" crossorigin="anonymous" />
<link rel="stylesheet" href="../css/lib/codemirror/darcula.css" crossorigin="anonymous" />

                    {{ endpointHeading }}

                    {{ endpointStatusLabel }}

                        <button id="endpoint-status-button" type="button" class="btn btn-{{(endpoint.status == activeStatus)?'success':'default'}} dropdown-toggle" uib-dropdown-toggle ng-disabled="disabled || readOnly">
                            {{ (endpoint.status == activeStatus) ? enabledLabel : disabledLabel }}

                        </button>

                                {{ enabledLabel }}
                                {{ disabledLabel }}

{{alert.msg}}

                    {{ pathLabel }} ({{ actualPathPrefixLabel }} {{ defaultCtxPathPrefix }}{{ endpoint.path }})
                    <input id="path" class="form-control ng-isolate-scope ng-pristine ng-valid" focus="isNew" ng-model="endpoint.path" placeholder="{{ pathPlaceHolderTxt }}" type="text" ng-disabled="readOnly" />

                    {{ methodLabel }}

                        <button id="method-button" type="button" class="btn btn-default" uib-dropdown-toggle ng-disabled="endpoint.mockType.value == mockTypeWebSocket || endpoint.mockType.value == mockTypeProxySse || endpoint.mockType.value == mockTypeRuleWs || endpoint.mockType.value == mockTypeStateful || readOnly">
                            {{ endpoint.method }}
                            {{ selectDropDownLabel }}

                        </button>

                                {{ m }}

                        {{ defaultContentTypeLabel }}
                        <input id="stateful-content-type" class="form-control ng-isolate-scope ng-pristine ng-valid" value="{{ endpoint.contentType }}" type="text" ng-disabled="true" />

                        {{ statefulIdFieldNameLabel }}
                        <input id="stateful-id-field-name" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.statefulIdFieldName" type="text" ng-disabled="readOnly" />

                        {{ statefulIdFieldLocationLabel }}
                        <input id="stateful-id-field-path" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.statefulIdFieldLocation" placeholder="{{ statefulIdFieldLocationPlaceholderLabel }}" type="text" ng-disabled="readOnly" />

                                {{ initialDataStateLabel }}

                                {{ formatJsonLabel }}

                        <textarea id="stateful-response-body" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.responseBody" ng-disabled="readOnly"></textarea>

	                    {{ defaultContentTypeLabel }}
	                    <input id="contentType" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.contentType" placeholder="{{ defaultContentTypePlaceholderTxt }}" type="text" uib-typeahead="ct for ct in contentTypes | filter:$viewValue | limitTo:8" ng-disabled="readOnly" />

	                    {{ defaultHttpStatusCodeLabel }}
	                    <input id="httpStatusCode" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.httpStatusCode" placeholder="{{ defaultHttpStatusCodePlaceholderTxt }}" type="text" ng-disabled="readOnly" />

	                            {{ defaultResponseBodyLabel }}

	                            {{ formatJsonLabel }}
	                            {{ formatXmlLabel }}

	                    <textarea id="default-response-body" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.responseBody" ng-disabled="readOnly"></textarea>

	                    {{ responseHeadersLabel }}

	                                    {{ responseHeaderNameLabel }}
	                                    {{ responseHeaderValueLabel }}

	                                        <input type="text" ng-model="rh.name" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-disabled="readOnly" />

	                                        <input type="text" ng-model="rh.value" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-disabled="readOnly" />

	                                        <button type="button" class="btn btn-warning" ng-click="doRemoveResponseHeaderRow($index)" ng-disabled="readOnly">{{ removeResponseHeaderButtonLabel }}</button>

	                            <button id="add-response-header-row" type="button" class="btn btn-info" ng-click="doAddResponseHeaderRow()" ng-disabled="readOnly"> {{ addResponseHeaderButtonLabel }}</button>

                        <button id="mock-type-button" type="button" class="btn btn-default" uib-dropdown-toggle ng-disabled="readOnly">
                            {{ endpoint.mockType.name }}
                        </button>

                                {{ mt.name }}

                        <button type="button" class="btn btn-primary add-button" ng-click="doOpenAddSequence()" ng-disabled="readOnly"> {{ addSequenceButtonLabel }}</button>

                        {{ noSeqFound }}

 0">

                            {{ orderNoLabel }}
                            {{ statusCodeLabel }}
                            {{ frequencyLabel }}
                            {{ responseBodyLabel }}

                            {{ x.orderNo }}
                            {{ x.httpStatusCode }}
                            {{ x.frequencyCount }}
                            {{ (x.responseBody != null) ? ( x.responseBody | limitTo: responseBodyLimit ) : 'N/A' }}

                                <button type="button" class="btn btn-primary view-seq-button" ng-class="(x.suspend) ? 'suspend-button' : ''" ng-click="doOpenViewSequence(x)" ng-disabled="x.suspend">{{ viewButtonLabel }}</button>

 1">
                        <input id="shuffleSequence" ng-model="endpoint.randomiseDefinitions" type="checkbox" ng-disabled="readOnly" />
                        {{ shuffleSequenceLabel }}

                        <button type="button" class="btn btn-primary add-button" ng-click="doOpenAddRule()" ng-disabled="readOnly"> {{ addRuleButtonLabel }}</button>

                        {{ noRulesFound }}

 0">

                            {{ ruleLabel }}
                            {{ statusCodeLabel }}
                            {{ responseBodyLabel }}

                            {{ x.orderNo }}
                            {{ x.httpStatusCode }}
                            {{ (x.responseBody != null) ? ( x.responseBody | limitTo: responseBodyLimit ) : 'N/A' }}

                                <button type="button" class="btn btn-primary view-rule-button" ng-class="(x.suspend) ? 'suspend-button' : ''" ng-click="doOpenViewRule(x)" ng-disabled="x.suspend">{{ viewButtonLabel }}</button>

                        {{ proxyTimeoutLabel }}
                        <input id="proxyTimeout" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.proxyTimeout" placeholder="{{ proxyTimeoutPlaceholderTxt }}" type="text" ng-disabled="readOnly" />

                    <uib-accordion id="manageProxy" close-others="false" ng-if="!isNew && !readOnly">

                            <uib-accordion-heading>

                                    {{ manageHttpProxyQueueLabel }}

                            </uib-accordion-heading>

{{ option1Label }} - {{ option1Text }}

                            <input class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="proxyPushToQueueEndpoint" readonly="true" ng-disaabled="true" />

{{ option2Label }} - {{ option2Text }}

                                {{ proxyContentTypeLabel }}
                                <input id="proxyContentType" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="proxyEndpoint.contentType" placeholder="{{ defaultContentTypePlaceholderTxt }}" type="text" uib-typeahead="ct for ct in contentTypes | filter:$viewValue | limitTo:8" />

                                {{ proxyHttpStatusCodeLabel }}
                                <input id="proxyHttpStatusCode" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="proxyEndpoint.httpStatusCode" placeholder="{{ defaultHttpStatusCodePlaceholderTxt }}" type="text" />

                                        {{ proxyResponseBodyLabel }}

                                        {{ formatJsonLabel }}
                                        {{ formatXmlLabel }}

                                <textarea id="proxy-default-response-body" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="proxyEndpoint.responseBody"></textarea>

                                <button class="btn btn-warning" type="button" ng-click="doClearProxyFields()" ng-disabled="endpoint.status == inActiveStatus">{{ clearProxyResponseFieldsButtonLabel }}</button>
                                <button class="btn btn-success" type="button" ng-click="doPostProxyResponse()" ng-disabled="endpoint.status == inActiveStatus">{{ postProxyResponseButtonLabel }}</button>

                            <button id="clear-proxy-button" class="btn btn-info" type="button" ng-click="doClearProxyQueue()" ng-disabled="endpoint.status == inActiveStatus || readOnly">{{ clearProxyButtonLabel }}</button>

                    </uib-accordion>

                        {{ webSocketTimeoutLabel }}
                        <input id="websocketTimeout" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.webSocketTimeout" placeholder="{{ webSocketTimeoutPlaceholderTxt }}" type="text" ng-disabled="readOnly" />

                        <input id="wsPushIdOnConnect"  ng-model="endpoint.wsPushIdOnConnect" type="checkbox" ng-disabled="readOnly" />
                        {{ pushIdOnConnectLabel }}

                    <uib-accordion id="manageWsProxy" close-others="false" ng-if="!isNew && !readOnly">

                            <uib-accordion-heading>

                                    {{ activeClientConnectionsLabel }}

                            </uib-accordion-heading>

                                    {{ refreshClientsLinkLabel }}

                                {{ noActiveWsClientsFound }}

 0">

                                            {{ clientIdHeading }}
                                            {{ clientJoinDateHeading }}

                                            {{ ws.id }}
                                            {{ ws.dateJoined | date: "dd/MM/yyyy HH:mm:ss" : "UTC" }}

                                                <button class="btn btn-info" type="button" ng-click="doOpenPushWSMessageView(ws.id)" ng-disabled="endpoint.status == inActiveStatus || readOnly">{{ messageButtonLabel }}</button>

                    </uib-accordion>

                        {{ sseHeartbeatLabel }}
                        <input id="sseHeartbeat" class="form-control ng-isolate-scope ng-pristine ng-valid" ng-model="endpoint.sseHeartbeat" placeholder="{{ sseHeartbeatPlaceholderTxt }}" type="text" ng-disabled="readOnly" />

                        <input id="ssePushIdOnConnect"  ng-model="endpoint.ssePushIdOnConnect" type="checkbox" ng-disabled="readOnly" />
                        {{ pushIdOnConnectLabel }}

                    <uib-accordion id="manageSseProxy" close-others="false" ng-if="!isNew && !readOnly">

                            <uib-accordion-heading>

                                    {{ activeClientConnectionsLabel }}

                            </uib-accordion-heading>

                                    {{ refreshClientsLinkLabel }}

                                {{ noActiveSseClientsFound }}

 0">

                                        {{ clientIdHeading }}
                                        {{ clientJoinDateHeading }}

                                        {{ as.id }}
                                        {{ as.dateJoined | date: "dd/MM/yyyy HH:mm:ss" : "UTC" }}

                                            <button class="btn btn-info" type="button" ng-click="doOpenPushSseMessageView(as.id)" ng-disabled="endpoint.status == inActiveStatus || readOnly">{{ messageButtonLabel }}</button>

                    </uib-accordion>

                                {{ customJsSyntaxLabel }}

                                {{ editCustomJSLabel }}

                        <textarea id="custom-js-syntax" name="custom-js-syntax"></textarea>

                    <button id="clear-data-state-button" class="btn btn-info" type="button" ng-click="doClearDataState()" ng-if="!readOnly">{{ clearStateButtonLabel }}</button>

                <input id="random-response-latency"  ng-model="endpoint.randomiseLatency" type="checkbox" />
                {{ enableRandomLatencyLabel }}

                {{ latencyRangeLabel }}

                        {{ latencyRangeMinLabel }}

                        <input type="text" ng-model="endpoint.randomiseLatencyRangeMinMillis" class="form-control ng-isolate-scope ng-pristine ng-valid" />

                        {{ latencyRangeMaxLabel }}

                        <input type="text" ng-model="endpoint.randomiseLatencyRangeMaxMillis" class="form-control ng-isolate-scope ng-pristine ng-valid" />

            <button class="btn btn-default" type="button" ng-click="doCancel()">{{ cancelButtonLabel }}</button>
            <button class="btn btn-danger" type="button" ng-click="doDelete()" ng-if="!isNew && !readOnly">{{ deleteButtonLabel }}</button>
            <button class="btn btn-primary" type="button" ng-click="doSaveEndpoint()" ng-if="!readOnly">{{ saveButtonLabel }}</button>


text:
<resources>
    <string name="app_name">Quad_Android</string>
</resources>

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<base href="../" />

<link rel="stylesheet" href="assets/searchstyle.css" type="text/css" />

<link rel="stylesheet" href="assets/style.css" type="text/css" />

<title>HTTP/2 Directives - Configure - H2O</title>

H2O

the optimized HTTP/1.x, HTTP/2 server

<form id="searchform">
<input class="search" type="search" name="search" id="search" results="5" value="" placeholder="Search" />

×

Powered by Oktavia

</form>

Top
Install
Configure
FAQ
Blog
Source

Configure >
HTTP/2 Directives

This document describes the configuration directives for controlling the HTTP/2 protocol handler.

"http2-idle-timeout"

Description:

Timeout for idle connections in seconds.

Level:

global

Default:

http2-idle-timeout: 10

"http2-max-concurrent-requests-per-connection"

Description:

Maximum number of requests to be handled concurrently within a single HTTP/2 connection.

The value cannot exceed 256.

Level:

global

Default:

http2-max-concurrent-requests-per-connection: 256

"http2-reprioritize-blocking-assets"

Description:

A boolean flag (ON or OFF) indicating if the server should send CSS and JS files above anything else.

This option has a positive impact on first-paint time on Google Chrome.
For more information please refer to HTTP/2 (and H2O) improves user experience over HTTP/1.1 or SPDY.

Level:

global

Default:

http2-reprioritize-blocking-assets: OFF

Copyright © 2015 DeNA Co., Ltd. et al.


text: Example how to use Phaser, Backbone and Webpack


text:
// Dependencies:
var fs = require('fs'),
    exec = require('child_process').exec,
    request = require('request'),
    flow = require('nue').flow,
    as = require('nue').as,
    config = require('../config'),
    box = require('./box'),
    installUtils = require('./installer/install-utils'),
    logger = require('../logger'),
    removeDir = require('rimraf').sync;

// "Constants":
var UPDATE_URL = config.get('UPDATE_URL'),
    KALASTACK_BASE_URL = config.get('KALASTACK_BASE_URL'),
    KALASTACK_DIR = config.get('KALASTACK_DIR'),
    KALASTACK_VERSION = config.kalastack.get('kalastack_version'),
    KALASTACK_URL = KALASTACK_BASE_URL + 'kalastack-' + KALASTACK_VERSION + '.tar.gz',
    DEPENDENCIES = [
      'terminatur'
    ],
    KEEP_FILES = [
      '.kalabox',
      '.vagrant',
      'config.json'
    ];

// Variables:
var configFileContents = null,
    configuration = {},
    dependenciesUpdate = false,
    kalastackUpdate = false,
    socket;

/**
 * Checks the canonical online source for updates.
 */
exports.checkForUpdates = flow('checkForUpdates')(
  function checkForUpdates0(callback) {
    this.data.callback = callback;
    // Download the updates file.
    request(UPDATE_URL, this.async(as(2)));
  },
  function checkForUpdates1(body) {
    // Parse the updates and read in the current config.
    configFileContents = body;
    configuration = JSON.parse(body);
    var currentConfig = {};
    if (fs.existsSync(KALASTACK_DIR + 'config.json')) {
      currentConfig = JSON.parse(fs.readFileSync(KALASTACK_DIR + 'config.json'));
    }
    // Check the dependencies and Kalastack versions against the latest ones.
    DEPENDENCIES.forEach(function(dependency) {
      if (currentConfig[dependency + '_version'] != configuration[dependency + '_version']) {
        dependenciesUpdate = true;
        return false;
      }
    });
    if (currentConfig['kalastack_version'] != configuration['kalastack_version']) {
      kalastackUpdate = true;
    }
    this.next(dependenciesUpdate || kalastackUpdate);
  },
  function checkForUpdatesEnd(needsUpdate) {
    if (this.err) {
      logger.warn('Updates check failed: ' + this.err.message);
      this.err = null;
      this.data.callback(false);
    }
    else {
      this.data.callback(needsUpdate);
    }
    this.next();
  }
);

/**
 * Updates any out of date dependencies.
 */
exports.update = flow('update')(
  function update0(callback) {
    this.data.callback = callback;
    // Connect to the UI.
    io.sockets.on('connection', this.async(as(0)));
  },
  function update1(newSocket) {
    socket = newSocket;
    sendMessage('You Gone Get Updated!...');
    sendIcon('fa fa-download', 'kalagreen');
    sendProgress(25);
    // Write the new configuration file.
    fs.writeFileSync(KALASTACK_DIR + 'config.json', configFileContents);
    // Halt the box.
    box.stopBox(this.async());
  },
  function update1() {
    // Refresh Kalastack if there's an update.
    sendIcon('fa fa-cog fa-spin', 'kalablue');
    sendProgress(40);
    if (kalastackUpdate) {
      refreshKalastack(this.async());
    }
    else {
      this.next();
    }
  },
  function update2() {
    // Provision and start the box.
    sendProgress(77);
    installUtils.spinupBox(this.async());
  },
  function updateEnd() {
    if (this.err) {
      if (this.data.callback) {
        this.data.callback(this.err);
      }
      this.err = null;
    }
    else if (this.data.callback) {
      this.data.callback();
    }
    sendProgress(100);
    socket.emit('updatesComplete');
    this.next();
  }
);

/**
 * Replaces the Kalastack source code on the host with that of the latest version.
 */
var refreshKalastack = flow('refreshKalastack')(
  function refreshKalastack0(callback) {
    this.data.callback = callback;
    // @todo switch to os.tmpdir() once we upgrade Node past 0.8.
    this.data.temp = process.env['TMPDIR'];
    // Delete the old Kalastack files.
    files = fs.readdirSync(KALASTACK_DIR);
    files.forEach(function(file) {
      if (KEEP_FILES.indexOf(file) !== -1) {
        return true;
      }
      var filePath = KALASTACK_DIR + file,
          fileInfo = fs.statSync(filePath);
      if (fileInfo.isDirectory()) {
        removeDir(filePath);
      }
      else {
        fs.unlinkSync(filePath);
      }
    });
    // Download the new Kalastack files.
    var kalastackRequest = request(KALASTACK_URL);
    kalastackRequest.on('end', this.async());
    kalastackRequest.pipe(fs.createWriteStream(this.data.temp + 'kalastack.tar.gz'));
  },
  function refreshKalastack1() {
    // Extract the new Kalastack files.
    var temp = this.data.temp;
    if (!fs.existsSync(temp + 'kalastack')) {
      fs.mkdirSync(temp + 'kalastack');
    }
    exec('tar zxvf ' + temp + 'kalastack.tar.gz -C ' + temp + 'kalastack --strip-components 1', this.async());
  },
  function refreshKalastack2() {
    // Move the new files into place.
    var temp = this.data.temp,
        newFiles = fs.readdirSync(temp + 'kalastack');
    newFiles.forEach(function(file) {
      var filePath = temp + 'kalastack/' + file;
      fs.renameSync(filePath, KALASTACK_DIR + file);
    });
    this.next();
  },
  function refreshKalastackEnd() {
    if (this.err) {
      this.data.callback(this.err);
      this.err = null;
    }
    else {
      this.data.callback();
    }
    this.next();
  }
);

/* UI Interaction Functions */

function sendMessage(message) {
  socket.emit('installer', { message: message });
}

function sendIcon(icon, kalacolor) {
  socket.emit('installer', { icon: icon, kalacolor: kalacolor});
}

function sendProgress(progress, install) {
  socket.emit('installer', { complete: progress });
}


text:
title: "Select / type"
parent: "@messageformat/parser"
grand_parent: API Reference
nav_exclude: true
---

<!-- Do not edit this file. It is automatically generated by API Documenter. -->

# Select.type property

<b>Signature:</b>

```typescript
type: 'plural' | 'select' | 'selectordinal';
```


text:
package org.apache.beam.sdk.io.kinesis;

import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyListOf;
import static org.mockito.Mockito.when;

import com.amazonaws.services.kinesis.model.ExpiredIteratorException;
import java.io.IOException;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

/** Tests {@link ShardRecordsIterator}. */
@RunWith(MockitoJUnitRunner.class)
public class ShardRecordsIteratorTest {

  private static final String INITIAL_ITERATOR = "INITIAL_ITERATOR";
  private static final String SECOND_ITERATOR = "SECOND_ITERATOR";
  private static final String SECOND_REFRESHED_ITERATOR = "SECOND_REFRESHED_ITERATOR";
  private static final String THIRD_ITERATOR = "THIRD_ITERATOR";
  private static final String STREAM_NAME = "STREAM_NAME";
  private static final String SHARD_ID = "SHARD_ID";

  @Mock private SimplifiedKinesisClient kinesisClient;
  @Mock private ShardCheckpoint firstCheckpoint, aCheckpoint, bCheckpoint, cCheckpoint, dCheckpoint;
  @Mock private GetKinesisRecordsResult firstResult, secondResult, thirdResult;
  @Mock private KinesisRecord a, b, c, d;
  @Mock private RecordFilter recordFilter;

  private ShardRecordsIterator iterator;

  @Before
  public void setUp() throws IOException, TransientKinesisException {
    when(firstCheckpoint.getShardIterator(kinesisClient)).thenReturn(INITIAL_ITERATOR);
    when(firstCheckpoint.getStreamName()).thenReturn(STREAM_NAME);
    when(firstCheckpoint.getShardId()).thenReturn(SHARD_ID);

    when(firstCheckpoint.moveAfter(a)).thenReturn(aCheckpoint);
    when(aCheckpoint.moveAfter(b)).thenReturn(bCheckpoint);
    when(aCheckpoint.getStreamName()).thenReturn(STREAM_NAME);
    when(aCheckpoint.getShardId()).thenReturn(SHARD_ID);
    when(bCheckpoint.moveAfter(c)).thenReturn(cCheckpoint);
    when(bCheckpoint.getStreamName()).thenReturn(STREAM_NAME);
    when(bCheckpoint.getShardId()).thenReturn(SHARD_ID);
    when(cCheckpoint.moveAfter(d)).thenReturn(dCheckpoint);
    when(cCheckpoint.getStreamName()).thenReturn(STREAM_NAME);
    when(cCheckpoint.getShardId()).thenReturn(SHARD_ID);
    when(dCheckpoint.getStreamName()).thenReturn(STREAM_NAME);
    when(dCheckpoint.getShardId()).thenReturn(SHARD_ID);

    when(kinesisClient.getRecords(INITIAL_ITERATOR, STREAM_NAME, SHARD_ID)).thenReturn(firstResult);
    when(kinesisClient.getRecords(SECOND_ITERATOR, STREAM_NAME, SHARD_ID)).thenReturn(secondResult);
    when(kinesisClient.getRecords(THIRD_ITERATOR, STREAM_NAME, SHARD_ID)).thenReturn(thirdResult);

    when(firstResult.getNextShardIterator()).thenReturn(SECOND_ITERATOR);
    when(secondResult.getNextShardIterator()).thenReturn(THIRD_ITERATOR);
    when(thirdResult.getNextShardIterator()).thenReturn(THIRD_ITERATOR);

    when(firstResult.getRecords()).thenReturn(Collections.emptyList());
    when(secondResult.getRecords()).thenReturn(Collections.emptyList());
    when(thirdResult.getRecords()).thenReturn(Collections.emptyList());

    when(recordFilter.apply(anyListOf(KinesisRecord.class), any(ShardCheckpoint.class)))
        .thenAnswer(new IdentityAnswer());

    iterator = new ShardRecordsIterator(firstCheckpoint, kinesisClient, recordFilter);
  }

  @Test
  public void goesThroughAvailableRecords()
      throws IOException, TransientKinesisException, KinesisShardClosedException {
    when(firstResult.getRecords()).thenReturn(asList(a, b, c));
    when(secondResult.getRecords()).thenReturn(singletonList(d));
    when(thirdResult.getRecords()).thenReturn(Collections.emptyList());

    assertThat(iterator.getCheckpoint()).isEqualTo(firstCheckpoint);
    assertThat(iterator.readNextBatch()).isEqualTo(asList(a, b, c));
    assertThat(iterator.readNextBatch()).isEqualTo(singletonList(d));
    assertThat(iterator.readNextBatch()).isEqualTo(Collections.emptyList());
  }

  @Test
  public void conformingRecordsMovesCheckpoint() throws IOException, TransientKinesisException {
    when(firstResult.getRecords()).thenReturn(asList(a, b, c));
    when(secondResult.getRecords()).thenReturn(singletonList(d));
    when(thirdResult.getRecords()).thenReturn(Collections.emptyList());

    iterator.ackRecord(a);
    assertThat(iterator.getCheckpoint()).isEqualTo(aCheckpoint);
    iterator.ackRecord(b);
    assertThat(iterator.getCheckpoint()).isEqualTo(bCheckpoint);
    iterator.ackRecord(c);
    assertThat(iterator.getCheckpoint()).isEqualTo(cCheckpoint);
    iterator.ackRecord(d);
    assertThat(iterator.getCheckpoint()).isEqualTo(dCheckpoint);
  }

  @Test
  public void refreshesExpiredIterator()
      throws IOException, TransientKinesisException, KinesisShardClosedException {
    when(firstResult.getRecords()).thenReturn(singletonList(a));
    when(secondResult.getRecords()).thenReturn(singletonList(b));

    when(kinesisClient.getRecords(SECOND_ITERATOR, STREAM_NAME, SHARD_ID))
        .thenThrow(ExpiredIteratorException.class);
    when(aCheckpoint.getShardIterator(kinesisClient)).thenReturn(SECOND_REFRESHED_ITERATOR);
    when(kinesisClient.getRecords(SECOND_REFRESHED_ITERATOR, STREAM_NAME, SHARD_ID))
        .thenReturn(secondResult);

    assertThat(iterator.readNextBatch()).isEqualTo(singletonList(a));
    iterator.ackRecord(a);
    assertThat(iterator.readNextBatch()).isEqualTo(singletonList(b));
    assertThat(iterator.readNextBatch()).isEqualTo(Collections.emptyList());
  }

  private static class IdentityAnswer implements Answer<Object> {

    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
      return invocation.getArguments()[0];
    }
  }
}


text:
namespace view_manager {

class ConnectionManager;

// Handles dispatching events to the right location as well as updating focus.
class EventDispatcher : public mojo::NativeViewportEventDispatcher {
 public:
  explicit EventDispatcher(ConnectionManager* connection_manager);
  ~EventDispatcher() override;

  void AddAccelerator(mojo::KeyboardCode keyboard_code, mojo::EventFlags flags);
  void RemoveAccelerator(mojo::KeyboardCode keyboard_code,
                         mojo::EventFlags flags);

  // NativeViewportEventDispatcher:
  void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override;

 private:
  struct Accelerator {
    Accelerator(mojo::KeyboardCode keyboard_code, mojo::EventFlags flags)
        : keyboard_code(keyboard_code), flags(flags) {}

    // So we can use this in a set.
    bool operator<(const Accelerator& other) const {
      if (keyboard_code == other.keyboard_code)
        return flags < other.flags;
      return keyboard_code < other.keyboard_code;
    }

    mojo::KeyboardCode keyboard_code;
    mojo::EventFlags flags;
  };

  ConnectionManager* connection_manager_;

  std::set<Accelerator> accelerators_;

  DISALLOW_COPY_AND_ASSIGN(EventDispatcher);
};

}  // namespace view_manager

#endif  // COMPONENTS_VIEW_MANAGER_EVENT_DISPATCHER_H_


text:
CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectImpacts )
CLIENTEFFECT_MATERIAL( "effects/fleck_cement1" )
CLIENTEFFECT_MATERIAL( "effects/fleck_cement2" )
CLIENTEFFECT_MATERIAL( "effects/fleck_antlion1" )
CLIENTEFFECT_MATERIAL( "effects/fleck_antlion2" )
CLIENTEFFECT_MATERIAL( "effects/fleck_wood1" )
CLIENTEFFECT_MATERIAL( "effects/fleck_wood2" )
CLIENTEFFECT_MATERIAL( "effects/blood" )
CLIENTEFFECT_MATERIAL( "effects/blood2" )
CLIENTEFFECT_MATERIAL( "sprites/bloodspray" )
CLIENTEFFECT_MATERIAL( "particle/particle_noisesphere" )
CLIENTEFFECT_REGISTER_END()

// Cached handles to commonly used materials
PMaterialHandle g_Mat_Fleck_Wood[2] = { NULL, NULL };
PMaterialHandle g_Mat_Fleck_Cement[2] = { NULL, NULL };
PMaterialHandle g_Mat_Fleck_Antlion[2] = { NULL, NULL };
PMaterialHandle g_Mat_Fleck_Glass[2] = { NULL, NULL };
PMaterialHandle g_Mat_Fleck_Tile[2] = { NULL, NULL };
PMaterialHandle g_Mat_DustPuff[2] = { NULL, NULL };
PMaterialHandle g_Mat_BloodPuff[2] = { NULL, NULL };
PMaterialHandle g_Mat_SMG_Muzzleflash[4] = { NULL, NULL, NULL, NULL };
PMaterialHandle g_Mat_Combine_Muzzleflash[3] = { NULL, NULL, NULL };

static ConVar fx_drawimpactdebris( "fx_drawimpactdebris", "1", FCVAR_DEVELOPMENTONLY, "Draw impact debris effects." );
static ConVar fx_drawimpactdust( "fx_drawimpactdust", "1", FCVAR_DEVELOPMENTONLY, "Draw impact dust effects." );

void FX_CacheMaterialHandles( void )
{
	g_Mat_Fleck_Wood[0] = ParticleMgr()->GetPMaterial( "effects/fleck_wood1" );
	g_Mat_Fleck_Wood[1] = ParticleMgr()->GetPMaterial( "effects/fleck_wood2" );

	g_Mat_Fleck_Cement[0] = ParticleMgr()->GetPMaterial( "effects/fleck_cement1");
	g_Mat_Fleck_Cement[1] = ParticleMgr()->GetPMaterial( "effects/fleck_cement2" );

	g_Mat_Fleck_Antlion[0] = ParticleMgr()->GetPMaterial( "effects/fleck_antlion1" );
	g_Mat_Fleck_Antlion[1] = ParticleMgr()->GetPMaterial( "effects/fleck_antlion2" );

	g_Mat_Fleck_Glass[0] = ParticleMgr()->GetPMaterial( "effects/fleck_glass1" );
	g_Mat_Fleck_Glass[1] = ParticleMgr()->GetPMaterial( "effects/fleck_glass2" );

	g_Mat_Fleck_Tile[0] = ParticleMgr()->GetPMaterial( "effects/fleck_tile1" );
	g_Mat_Fleck_Tile[1] = ParticleMgr()->GetPMaterial( "effects/fleck_tile2" );

	g_Mat_DustPuff[0] = ParticleMgr()->GetPMaterial( "particle/particle_smokegrenade" );
	g_Mat_DustPuff[1] = ParticleMgr()->GetPMaterial( "particle/particle_noisesphere" );

	g_Mat_BloodPuff[0] = ParticleMgr()->GetPMaterial( "effects/blood" );
	g_Mat_BloodPuff[1] = ParticleMgr()->GetPMaterial( "effects/blood2" );

#ifndef TF_CLIENT_DLL
	g_Mat_SMG_Muzzleflash[0] = ParticleMgr()->GetPMaterial( "effects/muzzleflash1" );
	g_Mat_SMG_Muzzleflash[1] = ParticleMgr()->GetPMaterial( "effects/muzzleflash2" );
	g_Mat_SMG_Muzzleflash[2] = ParticleMgr()->GetPMaterial( "effects/muzzleflash3" );
	g_Mat_SMG_Muzzleflash[3] = ParticleMgr()->GetPMaterial( "effects/muzzleflash4" );
#ifndef CSTRIKE_DLL
	g_Mat_Combine_Muzzleflash[0] = ParticleMgr()->GetPMaterial( "effects/combinemuzzle1" );
	g_Mat_Combine_Muzzleflash[1] = ParticleMgr()->GetPMaterial( "effects/combinemuzzle2" );
	g_Mat_Combine_Muzzleflash[2] = ParticleMgr()->GetPMaterial( "effects/strider_muzzle" );
#endif
#endif
}

extern PMaterialHandle g_Material_Spark;

//-----------------------------------------------------------------------------
// Purpose: Returns the color given trace information
// Input  : *trace - trace to get results for
//			*color - return color, gamma corrected (0.0f to 1.0f)
//-----------------------------------------------------------------------------
void GetColorForSurface( trace_t *trace, Vector *color )
{
	Vector	baseColor, diffuseColor;
	Vector	end = trace->startpos + ( ( Vector )trace->endpos - ( Vector )trace->startpos ) * 1.1f;

	if ( trace->DidHitWorld() )
	{
		if ( trace->hitbox == 0 )
		{
			// If we hit the world, then ask the world for the fleck color
			engine->TraceLineMaterialAndLighting( trace->startpos, end, diffuseColor, baseColor );
		}
		else
		{
			// In this case we hit a static prop.
			staticpropmgr->GetStaticPropMaterialColorAndLighting( trace, trace->hitbox - 1, diffuseColor, baseColor );
		}
	}
	else
	{
		// In this case, we hit an entity. Find out the model associated with it
		C_BaseEntity *pEnt = trace->m_pEnt;
		if ( !pEnt )
		{
			Msg("Couldn't find surface in GetColorForSurface()\n");
			color->x = 255;
			color->y = 255;
			color->z = 255;
			return;
		}

		ICollideable *pCollide = pEnt->GetCollideable();
		int modelIndex = pCollide->GetCollisionModelIndex();
		model_t* pModel = const_cast<model_t*>(modelinfo->GetModel( modelIndex ));

		// Ask the model info about what we need to know
		modelinfo->GetModelMaterialColorAndLighting( pModel, pCollide->GetCollisionOrigin(),
			pCollide->GetCollisionAngles(), trace, diffuseColor, baseColor );
	}

	//Get final light value
	color->x = pow( diffuseColor[0], 1.0f/2.2f ) * baseColor[0];
	color->y = pow( diffuseColor[1], 1.0f/2.2f ) * baseColor[1];
	color->z = pow( diffuseColor[2], 1.0f/2.2f ) * baseColor[2];
}

//-----------------------------------------------------------------------------
// This does the actual debris flecks
//-----------------------------------------------------------------------------
#define	FLECK_MIN_SPEED		64.0f
#define	FLECK_MAX_SPEED		128.0f
#define	FLECK_GRAVITY		800.0f
#define	FLECK_DAMPEN		0.3f
#define	FLECK_ANGULAR_SPRAY	0.6f

#ifndef _XBOX

//
// PC ONLY!
//

static void CreateFleckParticles( const Vector& origin, const Vector &color, trace_t *trace, char materialType, int iScale )
{
	Vector	spawnOffset	= trace->endpos + ( trace->plane.normal * 1.0f );

	CSmartPtr<CFleckParticles> fleckEmitter = CFleckParticles::Create( "FX_DebrisFlecks", spawnOffset, Vector(5,5,5) );

	if ( !fleckEmitter )
		return;

	// Handle increased scale
	float flMaxSpeed = FLECK_MAX_SPEED * iScale;
	float flAngularSpray = MAX( 0.2, FLECK_ANGULAR_SPRAY - ( (float)iScale * 0.2f) ); // More power makes the spray more controlled
	// Setup our collision information
	fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &trace->plane.normal, flAngularSpray, FLECK_MIN_SPEED, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );

	PMaterialHandle	*hMaterial;
	switch ( materialType )
	{
	case CHAR_TEX_WOOD:
		hMaterial = g_Mat_Fleck_Wood;
		break;

	case CHAR_TEX_CONCRETE:
	case CHAR_TEX_TILE:
	default:
		hMaterial = g_Mat_Fleck_Cement;
		break;
	}

	Vector	dir, end;

	float	colorRamp;

	float fScale = g_pParticleSystemMgr->ParticleThrottleScaling() * (float)iScale;
	int	numFlecks = (int)( 0.5f + fScale * (float)( random->RandomInt( 4, 16 ) ) );

	FleckParticle	*pFleckParticle;

	//Dump out flecks
	int i;
	for ( i = 0; i < numFlecks; i++ )
	{
		pFleckParticle = (FleckParticle *) fleckEmitter->AddParticle( sizeof(FleckParticle), hMaterial[random->RandomInt(0,1)], spawnOffset );

		if ( pFleckParticle == NULL )
			break;

		pFleckParticle->m_flLifetime	= 0.0f;
		pFleckParticle->m_flDieTime		= 3.0f;

		dir[0] = trace->plane.normal[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[1] = trace->plane.normal[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[2] = trace->plane.normal[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );

		pFleckParticle->m_uchSize		= random->RandomInt( 1, 2 );

		pFleckParticle->m_vecVelocity	= dir * ( random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed) * ( 3 - pFleckParticle->m_uchSize ) );

		pFleckParticle->m_flRoll		= random->RandomFloat( 0, 360 );
		pFleckParticle->m_flRollDelta	= random->RandomFloat( 0, 360 );

		colorRamp = random->RandomFloat( 0.75f, 1.25f );

		pFleckParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		pFleckParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		pFleckParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
	}
}

#endif // _XBOX

//-----------------------------------------------------------------------------
// Purpose: Debris flecks caused by impacts
// Input  : origin - start
//			*trace - trace information
//			*materialName - material hit
//			materialType - type of material hit
//-----------------------------------------------------------------------------
void FX_DebrisFlecks( const Vector& origin, trace_t *tr, char materialType, int iScale, bool bNoFlecks )
{
	VPROF_BUDGET( "FX_DebrisFlecks", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	if ( !fx_drawimpactdebris.GetBool() )
		return;

#ifdef _XBOX

	//
	// XBox version
	//

	Vector	offset;
	float	spread = 0.2f;

	CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
	pSimple->SetSortOrigin( origin );

	// Lock the bbox
	pSimple->GetBinding().SetBBox( origin - ( Vector( 16, 16, 16 ) * iScale ), origin + ( Vector( 16, 16, 16 ) * iScale ) );

	// Get the color of the surface we've impacted
	Vector	color;
	float	colorRamp;
	GetColorForSurface( tr, &color );

	int i;
	SimpleParticle	*pParticle;
	for ( i = 0; i < 4; i++ )
	{
		if ( i == 3 )
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
		}
		else
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
		}

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * i * 0.5f;

			// scaled
			pParticle->m_vecVelocity *= fForce * iScale;

			// Ramp the color
			colorRamp = random->RandomFloat( 0.5f, 1.25f );
			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

			// scaled
			pParticle->m_uchStartSize	= (iScale*0.5f) * random->RandomInt( 3, 4 ) * (i+1);

			// scaled
			pParticle->m_uchEndSize		= (iScale*0.5f) * pParticle->m_uchStartSize * 4;

			pParticle->m_uchStartAlpha	= random->RandomInt( 200, 255 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -1.0f, 1.0f );
		}
	}

	// Covers the impact spot with flecks
	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff2, origin );

	if ( pParticle != NULL )
	{
		offset = origin;
		offset[0] += random->RandomFloat( -8.0f, 8.0f );
		offset[1] += random->RandomFloat( -8.0f, 8.0f );

		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

		spread = 1.0f;

		pParticle->m_vecVelocity.Init();

		colorRamp = random->RandomFloat( 0.5f, 1.25f );

		pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

		pParticle->m_uchStartSize	= random->RandomInt( 4, 8 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;

		pParticle->m_uchStartAlpha	= random->RandomInt( 64, 128 );
		pParticle->m_uchEndAlpha	= 0;

		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= random->RandomFloat( -0.1f, 0.1f );
	}

#else

	//
	// PC version
	//

	Vector	color;
	GetColorForSurface( tr, &color );

	if ( !bNoFlecks )
	{
		CreateFleckParticles( origin, color, tr, materialType, iScale );
	}

	//
	// Dust trail
	//
	Vector	offset = tr->endpos + ( tr->plane.normal * 2.0f );

	SimpleParticle newParticle;

	int i;
	for ( i = 0; i < 2; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime	= 0.0f;
		newParticle.m_flDieTime	= 1.0f;

		Vector dir;
		dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 2, 4 ) * iScale;
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 8 * iScale;

		newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f )*(i+1);
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 32.0f )*(i+1);

		newParticle.m_uchStartAlpha	= random->RandomInt( 100, 200 );
		newParticle.m_uchEndAlpha	= 0;

		newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -1, 1 );

		float colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
	}

	for ( i = 0; i < 4; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime	= 0.0f;
		newParticle.m_flDieTime	= random->RandomFloat( 0.25f, 0.5f );

		Vector dir;
		dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 1, 4 );
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 4;

		newParticle.m_vecVelocity = dir * random->RandomFloat( 8.0f, 32.0f );
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 8.0f, 64.0f );

		newParticle.m_uchStartAlpha	= 255;
		newParticle.m_uchEndAlpha	= 0;

		newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );

		float colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
	}

	//
	// Bullet hole capper
	//
	newParticle.m_Pos = offset;

	newParticle.m_flLifetime		= 0.0f;
	newParticle.m_flDieTime		= random->RandomFloat( 1.0f, 1.5f );

	Vector dir;
	dir[0] = tr->plane.normal[0] + random->RandomFloat( -0.8f, 0.8f );
	dir[1] = tr->plane.normal[1] + random->RandomFloat( -0.8f, 0.8f );
	dir[2] = tr->plane.normal[2] + random->RandomFloat( -0.8f, 0.8f );

	newParticle.m_uchStartSize	= random->RandomInt( 4, 8 );
	newParticle.m_uchEndSize		= newParticle.m_uchStartSize * 4.0f;

	newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 24.0f );
	newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );

	newParticle.m_uchStartAlpha	= random->RandomInt( 100, 200 );
	newParticle.m_uchEndAlpha	= 0;

	newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
	newParticle.m_flRollDelta	= random->RandomFloat( -2, 2 );

	float colorRamp = random->RandomFloat( 0.5f, 1.25f );

	newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
	newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
	newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

	AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );

#endif
}

#define	GLASS_SHARD_MIN_LIFE	2.5f
#define	GLASS_SHARD_MAX_LIFE	5.0f
#define	GLASS_SHARD_NOISE		0.8
#define	GLASS_SHARD_GRAVITY		800
#define	GLASS_SHARD_DAMPING		0.3
#define	GLASS_SHARD_MIN_SPEED	1
#define	GLASS_SHARD_MAX_SPEED	300

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void FX_GlassImpact( const Vector &pos, const Vector &normal )
{
	VPROF_BUDGET( "FX_GlassImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	CSmartPtr<CSimple3DEmitter> pGlassEmitter = CSimple3DEmitter::Create( "FX_GlassImpact" );
	pGlassEmitter->SetSortOrigin( pos );

	Vector vecColor;
	engine->ComputeLighting( pos, NULL, true, vecColor );

	// HACK: Blend a little toward white to match the materials...
	VectorLerp( vecColor, Vector( 1, 1, 1 ), 0.3, vecColor );

	float flShardSize	= random->RandomFloat( 2.0f, 6.0f );

	unsigned char color[3] = { 200, 200, 210 };

	// ---------------------
	// Create glass shards
	// ----------------------

	int numShards = random->RandomInt( 2, 4 );

	for ( int i = 0; i < numShards; i++ )
	{
		Particle3D *pParticle;

		pParticle = (Particle3D *) pGlassEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Glass[random->RandomInt(0,1)], pos );

		if ( pParticle )
		{
			pParticle->m_flLifeRemaining	= random->RandomFloat(GLASS_SHARD_MIN_LIFE,GLASS_SHARD_MAX_LIFE);

			pParticle->m_vecVelocity[0]		= ( normal[0] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
			pParticle->m_vecVelocity[1]		= ( normal[1] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );
			pParticle->m_vecVelocity[2]		= ( normal[2] + random->RandomFloat( -0.8f, 0.8f ) ) * random->RandomFloat( GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED );

			pParticle->m_uchSize			= flShardSize + random->RandomFloat(-0.5*flShardSize,0.5*flShardSize);
			pParticle->m_vAngles			= RandomAngle( 0, 360 );
			pParticle->m_flAngSpeed			= random->RandomFloat(-800,800);

			pParticle->m_uchFrontColor[0]	= (byte)(color[0] * vecColor.x);
			pParticle->m_uchFrontColor[1]	= (byte)(color[1] * vecColor.y);
			pParticle->m_uchFrontColor[2]	= (byte)(color[2] * vecColor.z);
			pParticle->m_uchBackColor[0]	= (byte)(color[0] * vecColor.x);
			pParticle->m_uchBackColor[1]	= (byte)(color[1] * vecColor.y);
			pParticle->m_uchBackColor[2]	= (byte)(color[2] * vecColor.z);
		}
	}

	pGlassEmitter->m_ParticleCollision.Setup( pos, &normal, GLASS_SHARD_NOISE, GLASS_SHARD_MIN_SPEED, GLASS_SHARD_MAX_SPEED, GLASS_SHARD_GRAVITY, GLASS_SHARD_DAMPING );

	color[0] = 64;
	color[1] = 64;
	color[2] = 92;

	// ---------------------------
	// Dust
	// ---------------------------

	Vector	dir;
	Vector	offset = pos + ( normal * 2.0f );
	float	colorRamp;

	SimpleParticle newParticle;

	for ( int i = 0; i < 4; i++ )
	{
		newParticle.m_Pos = offset;

		newParticle.m_flLifetime= 0.0f;
		newParticle.m_flDieTime	= random->RandomFloat( 0.1f, 0.25f );

		dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );

		newParticle.m_uchStartSize	= random->RandomInt( 1, 4 );
		newParticle.m_uchEndSize	= newParticle.m_uchStartSize * 8;

		newParticle.m_vecVelocity	= dir * random->RandomFloat( 8.0f, 16.0f )*(i+1);
		newParticle.m_vecVelocity[2] -= random->RandomFloat( 16.0f, 32.0f )*(i+1);

		newParticle.m_uchStartAlpha	= random->RandomInt( 128, 255 );
		newParticle.m_uchEndAlpha	= 0;

		newParticle.m_flRoll		= random->RandomFloat( 0, 360 );
		newParticle.m_flRollDelta	= random->RandomFloat( -1, 1 );

		colorRamp = random->RandomFloat( 0.5f, 1.25f );

		newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

		AddSimpleParticle( &newParticle, g_Mat_BloodPuff[0] );
	}

	//
	// Bullet hole capper
	//
	newParticle.m_Pos = offset;

	newParticle.m_flLifetime		= 0.0f;
	newParticle.m_flDieTime		= random->RandomFloat( 1.0f, 1.5f );

	dir[0] = normal[0] + random->RandomFloat( -0.8f, 0.8f );
	dir[1] = normal[1] + random->RandomFloat( -0.8f, 0.8f );
	dir[2] = normal[2] + random->RandomFloat( -0.8f, 0.8f );

	newParticle.m_uchStartSize	= random->RandomInt( 4, 8 );
	newParticle.m_uchEndSize		= newParticle.m_uchStartSize * 4.0f;

	newParticle.m_vecVelocity = dir * random->RandomFloat( 2.0f, 8.0f );
	newParticle.m_vecVelocity[2] = random->RandomFloat( -2.0f, 2.0f );

	newParticle.m_uchStartAlpha	= random->RandomInt( 32, 64 );
	newParticle.m_uchEndAlpha	= 0;

	newParticle.m_flRoll			= random->RandomFloat( 0, 360 );
	newParticle.m_flRollDelta	= random->RandomFloat( -2, 2 );

	colorRamp = random->RandomFloat( 0.5f, 1.25f );

	newParticle.m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
	newParticle.m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
	newParticle.m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;

	AddSimpleParticle( &newParticle, g_Mat_DustPuff[0] );
}

void GlassImpactCallback( const CEffectData &data )
{
	FX_GlassImpact( data.m_vOrigin, data.m_vNormal );
}

DECLARE_CLIENT_EFFECT( "GlassImpact", GlassImpactCallback );

//-----------------------------------------------------------------------------
// Purpose:
// Input  : &pos -
//			*tr -
//-----------------------------------------------------------------------------
void FX_AntlionImpact( const Vector &pos, trace_t *trace )
{
#if defined( _X360 )
	return;
#endif // _X360

	VPROF_BUDGET( "FX_AntlionImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	CSmartPtr<CSimple3DEmitter> fleckEmitter = CSimple3DEmitter::Create( "FX_DebrisFlecks" );
	if ( fleckEmitter == NULL )
		return;

	Vector	shotDir = ( trace->startpos - trace->endpos );
	VectorNormalize( shotDir );

	Vector	spawnOffset	= trace->endpos + ( shotDir * 2.0f );

	Vector vWorldMins, vWorldMaxs;
	if ( trace->m_pEnt )
	{
		float scale = trace->m_pEnt->CollisionProp()->BoundingRadius();
		vWorldMins[0] = spawnOffset[0] - scale;
		vWorldMins[1] = spawnOffset[1] - scale;
		vWorldMins[2] = spawnOffset[2] - scale;
		vWorldMaxs[0] = spawnOffset[0] + scale;
		vWorldMaxs[1] = spawnOffset[1] + scale;
		vWorldMaxs[2] = spawnOffset[2] + scale;
	}
	else
	{
		return;
	}

	fleckEmitter->SetSortOrigin( spawnOffset );
	fleckEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );

	// Handle increased scale
	float flMaxSpeed = 256.0f;
	float flAngularSpray = 1.0f;

	// Setup our collision information
	fleckEmitter->m_ParticleCollision.Setup( spawnOffset, &shotDir, flAngularSpray, 8.0f, flMaxSpeed, FLECK_GRAVITY, FLECK_DAMPEN );

	Vector	dir, end;
	Vector	color = Vector( 1, 0.9, 0.75 );
	float	colorRamp;

	int	numFlecks = random->RandomInt( 8, 16 );

	Particle3D *pFleckParticle;

	// Dump out flecks
	int i;
	for ( i = 0; i < numFlecks; i++ )
	{
		pFleckParticle = (Particle3D *) fleckEmitter->AddParticle( sizeof(Particle3D), g_Mat_Fleck_Antlion[random->RandomInt(0,1)], spawnOffset );
		if ( pFleckParticle == NULL )
			break;

		pFleckParticle->m_flLifeRemaining = 3.0f;

		dir[0] = shotDir[0] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[1] = shotDir[1] + random->RandomFloat( -flAngularSpray, flAngularSpray );
		dir[2] = shotDir[2] + random->RandomFloat( -flAngularSpray, flAngularSpray );

		pFleckParticle->m_uchSize		= random->RandomInt( 1, 6 );

		pFleckParticle->m_vecVelocity	= dir * random->RandomFloat( FLECK_MIN_SPEED, flMaxSpeed);
		pFleckParticle->m_vAngles.Random( 0, 360 );
		pFleckParticle->m_flAngSpeed	= random->RandomFloat(-800,800);

		pFleckParticle->m_uchFrontColor[0] = 255;
		pFleckParticle->m_uchFrontColor[1] = 255;
		pFleckParticle->m_uchFrontColor[2] = 255;

		pFleckParticle->m_uchBackColor[0] = 128;
		pFleckParticle->m_uchBackColor[1] = 128;
		pFleckParticle->m_uchBackColor[2] = 128;
	}

	//
	// Dust trail
	//

	SimpleParticle	*pParticle;

	CSmartPtr<CSimpleEmitter> dustEmitter = CSimpleEmitter::Create( "FX_DebrisFlecks" );
	if ( !dustEmitter )
		return;

	Vector	offset = trace->endpos + ( shotDir * 4.0f );

	dustEmitter->SetSortOrigin( offset );
	dustEmitter->GetBinding().SetBBox( spawnOffset-Vector(32,32,32), spawnOffset+Vector(32,32,32), true );

	for ( i = 0; i < 4; i++ )
	{
		pParticle = (SimpleParticle *) dustEmitter->AddParticle( sizeof(SimpleParticle), g_Mat_DustPuff[0], offset );

		if ( pParticle == NULL )
			break;

		pParticle->m_flLifetime	= 0.0f;
		pParticle->m_flDieTime	= 1.0f;

		dir[0] = shotDir[0] + random->RandomFloat( -0.8f, 0.8f );
		dir[1] = shotDir[1] + random->RandomFloat( -0.8f, 0.8f );
		dir[2] = shotDir[2] + random->RandomFloat( -0.8f, 0.8f );

		pParticle->m_uchStartSize	= random->RandomInt( 8, 16 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4.0f;

		pParticle->m_vecVelocity = dir * random->RandomFloat( 4.0f, 64.0f );

		pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64);
		pParticle->m_uchEndAlpha	= 0;

		pParticle->m_flRoll			= random->RandomFloat( 0, 2.0f*M_PI );
		pParticle->m_flRollDelta	= random->RandomFloat( -0.5f, 0.5f );

		colorRamp = random->RandomFloat( 0.5f, 1.0f );

		pParticle->m_uchColor[0] = MIN( 1.0f, color[0]*colorRamp )*255.0f;
		pParticle->m_uchColor[1] = MIN( 1.0f, color[1]*colorRamp )*255.0f;
		pParticle->m_uchColor[2] = MIN( 1.0f, color[2]*colorRamp )*255.0f;
	}

	CLocalPlayerFilter filter;
	C_BaseEntity::EmitSound( filter, 0, "FX_AntlionImpact.ShellImpact", &trace->endpos );
}

//-----------------------------------------------------------------------------
// Purpose: Spurt out bug blood
// Input  : &pos -
//			&dir -
//-----------------------------------------------------------------------------
#if defined( _XBOX )
#define NUM_BUG_BLOOD	16
#define NUM_BUG_BLOOD2	8
#define NUM_BUG_SPLATS	8
#else
#define NUM_BUG_BLOOD	32
#define NUM_BUG_BLOOD2	16
#define NUM_BUG_SPLATS	16
#endif
void FX_BugBlood( Vector &pos, Vector &dir, Vector &vWorldMins, Vector &vWorldMaxs )
{
	VPROF_BUDGET( "FX_BugBlood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_BugBlood" );
	if ( !pSimple )
		return;

	pSimple->SetSortOrigin( pos );
	pSimple->GetBinding().SetBBox( vWorldMins, vWorldMaxs, true );
	pSimple->GetBinding().SetBBox( pos-Vector(32,32,32), pos+Vector(32,32,32), true );

	Vector	vDir;
	vDir[0] = dir[0] + random->RandomFloat( -2.0f, 2.0f );
	vDir[1] = dir[1] + random->RandomFloat( -2.0f, 2.0f );
	vDir[2] = dir[2] + random->RandomFloat( -2.0f, 2.0f );

	VectorNormalize( vDir );

	int i;
	for ( i = 0; i < NUM_BUG_BLOOD; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );

		if ( sParticle == NULL )
			return;

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= 0.25f;

		float	speed = random->RandomFloat( 32.0f, 150.0f );

		sParticle->m_vecVelocity	= vDir * -speed;
		sParticle->m_vecVelocity[2] -= 32.0f;

		sParticle->m_uchColor[0]	= 255;
		sParticle->m_uchColor[1]	= 200;
		sParticle->m_uchColor[2]	= 32;
		sParticle->m_uchStartAlpha	= 255;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= random->RandomInt( 1, 2 );
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}

	for ( i = 0; i < NUM_BUG_BLOOD2; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );

		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );

		float	speed = random->RandomFloat( 8.0f, 255.0f );

		sParticle->m_vecVelocity	= vDir * -speed;
		sParticle->m_vecVelocity[2] -= 16.0f;

		sParticle->m_uchColor[0]	= 255;
		sParticle->m_uchColor[1]	= 200;
		sParticle->m_uchColor[2]	= 32;
		sParticle->m_uchStartAlpha	= random->RandomInt( 16, 32 );
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= random->RandomInt( 1, 3 );
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*random->RandomInt( 1, 4 );
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}

	Vector	offset;

	for ( i = 0; i < NUM_BUG_SPLATS; i++ )
	{
		offset.Random( -2, 2 );
		offset += pos;

		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], offset );

		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );

		float speed = 75.0f * ((i/(float)NUM_BUG_SPLATS)+1);

		sParticle->m_vecVelocity.Random( -16.0f, 16.0f );

		sParticle->m_vecVelocity	+= vDir * -speed;
		sParticle->m_vecVelocity[2] -= ( 64.0f * ((i/(float)NUM_BUG_SPLATS)+1) );

		sParticle->m_uchColor[0]	= 255;
		sParticle->m_uchColor[1]	= 200;
		sParticle->m_uchColor[2]	= 32;
		sParticle->m_uchStartAlpha	= 255;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= random->RandomInt( 1, 2 );
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*4;
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Blood puff
//-----------------------------------------------------------------------------
void FX_Blood( Vector &pos, Vector &dir, float r, float g, float b, float a )
{
	VPROF_BUDGET( "FX_Blood", VPROF_BUDGETGROUP_PARTICLE_RENDERING );

	// Cloud
	CSmartPtr<CSimpleEmitter> pSimple = CSimpleEmitter::Create( "FX_Blood" );
	if ( !pSimple )
		return;
	pSimple->SetSortOrigin( pos );

	Vector	vDir;

	vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
	vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
	vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );

	VectorNormalize( vDir );

	int i;
	for ( i = 0; i < 2; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], pos );

		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );

		float	speed = random->RandomFloat( 2.0f, 8.0f );

		sParticle->m_vecVelocity	= vDir * (speed*i);
		sParticle->m_vecVelocity[2] += random->RandomFloat( -32.0f, -16.0f );

		sParticle->m_uchColor[0]	= r;
		sParticle->m_uchColor[1]	= g;
		sParticle->m_uchColor[2]	= b;
		sParticle->m_uchStartAlpha	= a;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= 2;
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*4;
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
	}

	for ( i = 0; i < 2; i++ )
	{
		SimpleParticle *sParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[1], pos );

		if ( sParticle == NULL )
		{
			return;
		}

		sParticle->m_flLifetime		= 0.0f;
		sParticle->m_flDieTime		= 0.5f;

		float	speed = random->RandomFloat( 4.0f, 16.0f );

		sParticle->m_vecVelocity	= vDir * (speed*i);

		sParticle->m_uchColor[0]	= r;
		sParticle->m_uchColor[1]	= g;
		sParticle->m_uchColor[2]	= b;
		sParticle->m_uchStartAlpha	= 128;
		sParticle->m_uchEndAlpha	= 0;
		sParticle->m_uchStartSize	= 2;
		sParticle->m_uchEndSize		= sParticle->m_uchStartSize*4;
		sParticle->m_flRoll			= random->RandomInt( 0, 360 );
		sParticle->m_flRollDelta	= random->RandomFloat( -4.0f, 4.0f );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Dust impact
// Input  : &origin - position
//			&tr - trace information
//-----------------------------------------------------------------------------
void FX_DustImpact( const Vector &origin, trace_t *tr, int iScale )
{
	if ( !fx_drawimpactdust.GetBool() )
		return;

#ifdef _XBOX

	//
	// XBox version
	//

	VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	Vector	offset;
	float	spread = 0.2f;

	CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
	pSimple->SetSortOrigin( origin );
	pSimple->GetBinding().SetBBox( origin - ( Vector( 32, 32, 32 ) * iScale ), origin + ( Vector( 32, 32, 32 ) * iScale ) );

	Vector	color;
	float	colorRamp;
	GetColorForSurface( tr, &color );

	int i;
	SimpleParticle *pParticle;
	for ( i = 0; i < 4; i++ )
	{
		// Last puff is gritty (hides end)
		if ( i == 3 )
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );
		}
		else
		{
			pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );
		}

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * i;

			// scaled
			pParticle->m_vecVelocity *= fForce * iScale;

			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

			// scaled
			pParticle->m_uchStartSize	= iScale * random->RandomInt( 3, 4 ) * (i+1);

			// scaled
			pParticle->m_uchEndSize		= iScale * pParticle->m_uchStartSize * 4;

			pParticle->m_uchStartAlpha	= random->RandomInt( 32, 255 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );

			if ( i == 3 )
			{
				pParticle->m_flRollDelta = random->RandomFloat( -0.1f, 0.1f );
				pParticle->m_flDieTime	= 0.5f;
			}
			else
			{
				pParticle->m_flRollDelta = random->RandomFloat( -8.0f, 8.0f );
				pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );
			}
		}
	}

	//Impact hit
	pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_DustPuff, origin );

	if ( pParticle != NULL )
	{
		offset = origin;
		offset[0] += random->RandomFloat( -8.0f, 8.0f );
		offset[1] += random->RandomFloat( -8.0f, 8.0f );

		pParticle->m_flLifetime = 0.0f;
		pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

		pParticle->m_vecVelocity.Init();

		colorRamp = random->RandomFloat( 0.75f, 1.25f );
		pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
		pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

		pParticle->m_uchStartSize	= random->RandomInt( 4, 8 );
		pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;

		pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64 );
		pParticle->m_uchEndAlpha	= 0;

		pParticle->m_flRoll			= random->RandomInt( 0, 360 );
		pParticle->m_flRollDelta	= random->RandomFloat( -1.0f, 1.0f );
	}

#else
	FX_DustImpact( origin, tr, (float)iScale );
#endif // _XBOX
}

void FX_DustImpact( const Vector &origin, trace_t *tr, float flScale )
{
	//
	// PC version
	//

	VPROF_BUDGET( "FX_DustImpact", VPROF_BUDGETGROUP_PARTICLE_RENDERING );
	Vector	offset;
	float	spread = 0.2f;

	CSmartPtr<CDustParticle> pSimple = CDustParticle::Create( "dust" );
	pSimple->SetSortOrigin( origin );

	// Three types of particle, ideally we want 4 of each.
	float fNumParticles = 4.0f * g_pParticleSystemMgr->ParticleThrottleScaling();
	int nParticles1 = (int)( 0.50f + fNumParticles );
	int nParticles2 = (int)( 0.83f + fNumParticles );		// <-- most visible particle type.
	int nParticles3 = (int)( 0.17f + fNumParticles );

	SimpleParticle	*pParticle;

	Vector	color;
	float	colorRamp;

	GetColorForSurface( tr, &color );

	// To get a decent spread even when scaling down the number of particles...
	const static int nParticleIdArray[4] = {3,1,2,0};

	int i;
	for ( i = 0; i < nParticles1; i++ )
	{
		int nId = nParticleIdArray[i];

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * nId;

			// scaled
			pParticle->m_vecVelocity *= fForce * flScale;

			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

			// scaled
			pParticle->m_uchStartSize	= ( unsigned char )( flScale * random->RandomInt( 3, 4 ) * (nId+1) );

			// scaled
			pParticle->m_uchEndSize		= ( unsigned char )( flScale * pParticle->m_uchStartSize * 4 );

			pParticle->m_uchStartAlpha	= random->RandomInt( 32, 255 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -8.0f, 8.0f );
		}
	}

	//Dust specs
	for ( i = 0; i < nParticles2; i++ )
	{
		int nId = nParticleIdArray[i];

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_BloodPuff[0], origin );

		if ( pParticle != NULL )
		{
			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.25f, 0.75f );

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += ( tr->plane.normal * random->RandomFloat( 1.0f, 6.0f ) );

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 250, 500 ) * nId;

			pParticle->m_vecVelocity *= fForce;

			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

			pParticle->m_uchStartSize	= random->RandomInt( 2, 4 ) * (nId+1);
			pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 2;

			pParticle->m_uchStartAlpha	= 255;
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -2.0f, 2.0f );
		}
	}

	//Impact hit
	for ( i = 0; i < nParticles3; i++ )
	{
		//int nId = nParticleIdArray[i];

		pParticle = (SimpleParticle *) pSimple->AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], origin );

		if ( pParticle != NULL )
		{
			offset = origin;
			offset[0] += random->RandomFloat( -8.0f, 8.0f );
			offset[1] += random->RandomFloat( -8.0f, 8.0f );

			pParticle->m_flLifetime = 0.0f;
			pParticle->m_flDieTime	= random->RandomFloat( 0.5f, 1.0f );

			spread = 1.0f;

			pParticle->m_vecVelocity.Random( -spread, spread );
			pParticle->m_vecVelocity += tr->plane.normal;

			VectorNormalize( pParticle->m_vecVelocity );

			float	fForce = random->RandomFloat( 0, 50 );

			pParticle->m_vecVelocity *= fForce;

			colorRamp = random->RandomFloat( 0.75f, 1.25f );

			pParticle->m_uchColor[0]	= MIN( 1.0f, color[0] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[1]	= MIN( 1.0f, color[1] * colorRamp ) * 255.0f;
			pParticle->m_uchColor[2]	= MIN( 1.0f, color[2] * colorRamp ) * 255.0f;

			pParticle->m_uchStartSize	= random->RandomInt( 1, 4 );
			pParticle->m_uchEndSize		= pParticle->m_uchStartSize * 4;

			pParticle->m_uchStartAlpha	= random->RandomInt( 32, 64 );
			pParticle->m_uchEndAlpha	= 0;

			pParticle->m_flRoll			= random->RandomInt( 0, 360 );
			pParticle->m_flRollDelta	= random->RandomFloat( -16.0f, 16.0f );
		}
	}
}

#ifdef _XBOX
extern PMaterialHandle g_Material_Spark;
#endif // _XBOX

//-----------------------------------------------------------------------------
// Purpose:
// Input  : &pos -
//			&dir -
//			type -
//-----------------------------------------------------------------------------
void FX_GaussExplosion( const Vector &pos, const Vector &dir, int type )
{
	Vector	vDir;

	vDir[0] = dir[0] + random->RandomFloat( -1.0f, 1.0f );
	vDir[1] = dir[1] + random->RandomFloat( -1.0f, 1.0f );
	vDir[2] = dir[2] + random->RandomFloat( -1.0f, 1.0f );

	VectorNormalize( vDir );

	int i;

#if defined(_XBOX) || defined(_X360)

	//
	// XBox version
	//
	CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_GaussExplosion" );
	if ( pSparkEmitter == NULL )
	{
		Assert(0);
		return;
	}

	if ( g_Material_Spark == NULL )
	{
		g_Material_Spark = pSparkEmitter->GetPMaterial( "effects/spark" );
	}

	pSparkEmitter->SetSortOrigin( pos );
	pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
	pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN );
	pSparkEmitter->GetBinding().SetBBox( pos - Vector( 32, 32, 32 ), pos + Vector( 32, 32, 32 ) );

	int numSparks = random->RandomInt( 8, 16 );
	TrailParticle	*pParticle;

	// Dump out sparks
	for ( i = 0; i < numSparks; i++ )
	{
		pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), g_Material_Spark, pos );

		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime	= 0.0f;

		vDir.Random( -0.6f, 0.6f );
		vDir += dir;
		VectorNormalize( vDir );

		pParticle->m_flWidth		= random->RandomFloat( 1.0f, 4.0f );
		pParticle->m_flLength		= random->RandomFloat( 0.01f, 0.1f );
		pParticle->m_flDieTime		= random->RandomFloat( 0.25f, 0.5f );

		pParticle->m_vecVelocity	= vDir * random->RandomFloat( 128, 512 );

		Color32Init( pParticle->m_color, 255, 255, 255, 255 );
	}

	// End cap
	SimpleParticle particle;

	particle.m_Pos = pos;
	particle.m_flLifetime = 0.0f;
	particle.m_flDieTime = 0.1f;
	particle.m_vecVelocity.Init();
	particle.m_flRoll = random->RandomInt( 0, 360 );
	particle.m_flRollDelta = 0.0f;
	particle.m_uchColor[0] = 255;
	particle.m_uchColor[1] = 255;
	particle.m_uchColor[2] = 255;
	particle.m_uchStartAlpha = 255;
	particle.m_uchEndAlpha = 255;
	particle.m_uchStartSize = random->RandomInt( 24, 32 );
	particle.m_uchEndSize = 0;

	AddSimpleParticle( &particle, ParticleMgr()->GetPMaterial( "effects/yellowflare" ) );

#else

	//
	// PC version
	//
	CSmartPtr<CTrailParticles> pSparkEmitter = CTrailParticles::Create( "FX_ElectricSpark" );

	if ( !pSparkEmitter )
	{
		Assert(0);
		return;
	}

	PMaterialHandle	hMaterial	= pSparkEmitter->GetPMaterial( "effects/spark" );

	pSparkEmitter->SetSortOrigin( pos );

	pSparkEmitter->m_ParticleCollision.SetGravity( 800.0f );
	pSparkEmitter->SetFlag( bitsPARTICLE_TRAIL_VELOCITY_DAMPEN|bitsPARTICLE_TRAIL_COLLIDE );

	//Setup our collision information
	pSparkEmitter->m_ParticleCollision.Setup( pos, &vDir, 0.8f, 128, 512, 800, 0.3f );

	int numSparks = random->RandomInt( 16, 32 );
	TrailParticle	*pParticle;

	// Dump out sparks
	for ( i = 0; i < numSparks; i++ )
	{
		pParticle = (TrailParticle *) pSparkEmitter->AddParticle( sizeof(TrailParticle), hMaterial, pos );

		if ( pParticle == NULL )
			return;

		pParticle->m_flLifetime	= 0.0f;

		vDir.Random( -0.6f, 0.6f );
		vDir += dir;
		VectorNormalize( vDir );

		pParticle->m_flWidth		= random->RandomFloat( 1.0f, 4.0f );
		pParticle->m_flLength		= random->RandomFloat( 0.01f, 0.1f );
		pParticle->m_flDieTime		= random->RandomFloat( 0.25f, 1.0f );

		pParticle->m_vecVelocity	= vDir * random->RandomFloat( 128, 512 );

		Color32Init( pParticle->m_color, 255, 255, 255, 255 );
	}

	FX_ElectricSpark( pos, 1, 1, &vDir );
#endif
}

class C_TEGaussExplosion : public C_TEParticleSystem
{
public:
	DECLARE_CLASS( C_TEGaussExplosion, C_TEParticleSystem );
	DECLARE_CLIENTCLASS();

				C_TEGaussExplosion();
	virtual		~C_TEGaussExplosion();

public:
	virtual void	PostDataUpdate( DataUpdateType_t updateType );
	virtual	bool	ShouldDraw() { return true; }

public:

	int			m_nType;
	Vector		m_vecDirection;
};

IMPLEMENT_CLIENTCLASS_EVENT_DT( C_TEGaussExplosion, DT_TEGaussExplosion, CTEGaussExplosion )
	RecvPropInt(RECVINFO(m_nType)),
	RecvPropVector(RECVINFO(m_vecDirection)),
END_RECV_TABLE()

//==================================================
// C_TEGaussExplosion
//==================================================

C_TEGaussExplosion::C_TEGaussExplosion()
{
}

C_TEGaussExplosion::~C_TEGaussExplosion()
{
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  : bNewEntity - whether or not to start a new entity
//-----------------------------------------------------------------------------
void C_TEGaussExplosion::PostDataUpdate( DataUpdateType_t updateType )
{
	FX_GaussExplosion( m_vecOrigin, m_vecDirection, m_nType );
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  : filter -
//			delay -
//			&pos -
//			&dir -
//			type -
//-----------------------------------------------------------------------------
void TE_GaussExplosion( IRecipientFilter& filter, float delay, const Vector &pos, const Vector &dir, int type )
{
	FX_GaussExplosion( pos, dir, type );
}


text:
namespace Reaper
{
bool vulkan_process_window_events(ReaperRoot& root, VulkanBackend& backend, IWindow* window)
{
    log_info(root, "window: pump events");

    std::vector<Window::Event> events;
    window->pumpEvents(events);

    for (const auto& event : events)
    {
        if (event.type == Window::EventType::Resize)
        {
            const u32 width = event.message.resize.width;
            const u32 height = event.message.resize.height;
            log_debug(root, "window: resize event, width = {}, height = {}", width, height);

            Assert(width > 0);
            Assert(height > 0);

            // FIXME Do not set for duplicate events
            backend.new_swapchain_extent = {width, height};
            backend.mustTransitionSwapchain = true;
        }
        else if (event.type == Window::EventType::KeyPress)
        {
            log_warning(root, "window: key press detected: now exiting...");
            return true;
        }
        else
        {
            log_warning(root, "window: an unknown event has been caught and will not be handled");
        }
    }

    return false;
}

void resize_swapchain(ReaperRoot& root, VulkanBackend& backend)
{
    // Resize swapchain if necessary
    if (backend.new_swapchain_extent.width != 0)
    {
        vkQueueWaitIdle(backend.deviceInfo.presentQueue); // FIXME

        Assert(backend.new_swapchain_extent.height > 0);
        resize_vulkan_wm_swapchain(root, backend, backend.presentInfo, backend.new_swapchain_extent);

        const glm::uvec2 new_swapchain_extent(backend.presentInfo.surfaceExtent.width,
                                              backend.presentInfo.surfaceExtent.height);

        backend.new_swapchain_extent.width = 0;
        backend.new_swapchain_extent.height = 0;
    }
}

void backend_execute_frame(ReaperRoot& root, VulkanBackend& backend, CommandBuffer& cmdBuffer,
                           const PreparedData& prepared, BackendResources& resources)
{
    VkResult acquireResult;
    u64      acquireTimeoutUs = 1000000000;
    uint32_t current_swapchain_index = 0;

    constexpr u32 MaxAcquireTryCount = 10;

    for (u32 acquireTryCount = 0; acquireTryCount < MaxAcquireTryCount; acquireTryCount++)
    {
        log_debug(root, "vulkan: acquiring frame try #{}", acquireTryCount);
        acquireResult = vkAcquireNextImageKHR(backend.device, backend.presentInfo.swapchain, acquireTimeoutUs,
                                              backend.presentInfo.imageAvailableSemaphore, VK_NULL_HANDLE,
                                              &current_swapchain_index);

        if (acquireResult != VK_NOT_READY)
            break;
    }

    switch (acquireResult)
    {
    case VK_NOT_READY: // Should be good after X tries
        log_debug(root, "vulkan: vkAcquireNextImageKHR not ready");
        break;
    case VK_SUBOPTIMAL_KHR:
        log_debug(root, "vulkan: vkAcquireNextImageKHR suboptimal");
        break;
    case VK_ERROR_OUT_OF_DATE_KHR:
        log_warning(root, "vulkan: vkAcquireNextImageKHR out of date");
        return;
    default:
        Assert(acquireResult == VK_SUCCESS);
        break;
    }

    log_debug(root, "vulkan: swapchain image index = {}", current_swapchain_index);

    {
        VkFence drawFence = resources.frame_sync_resources.drawFence;

        log_debug(root, "vulkan: wait for fence");
        VkResult waitResult;
        {
            REAPER_PROFILE_SCOPE("Wait", MP_BLUE);
            const u64 waitTimeoutUs = 300000000;
            waitResult = vkWaitForFences(backend.device, 1, &drawFence, VK_TRUE, waitTimeoutUs);
        }

        if (waitResult != VK_SUCCESS)
            log_debug(root, "- return result {}", GetResultToString(waitResult));

        // TODO Handle timeout correctly
        Assert(waitResult == VK_SUCCESS);

        Assert(vkGetFenceStatus(backend.device, drawFence) == VK_SUCCESS);

        log_debug(root, "vulkan: reset fence");
        Assert(vkResetFences(backend.device, 1, &drawFence) == VK_SUCCESS);
    }

    const VkExtent2D backbufferExtent = backend.presentInfo.surfaceExtent;

    FrameData frame_data = {};
    frame_data.backbufferExtent = backbufferExtent;

    // FIXME Recreate the swapchain pipeline every frame
    reload_swapchain_pipeline(root, backend, resources.swapchain_pass_resources);

    prepare_shadow_map_objects(root, backend, prepared, resources.shadow_map_resources);

    upload_culling_resources(backend, prepared, resources.cull_resources);
    upload_shadow_map_resources(backend, prepared, resources.shadow_map_resources);
    upload_main_pass_frame_resources(backend, prepared, resources.main_pass_resources);
    upload_histogram_frame_resources(backend, resources.histogram_pass_resources, backbufferExtent);
    upload_swapchain_frame_resources(backend, prepared, resources.swapchain_pass_resources);
    upload_audio_frame_resources(backend, prepared, resources.audio_resources);

    FrameGraph::FrameGraph frame_graph;

    using namespace FrameGraph;

    FrameGraphBuilder builder(frame_graph);

    // Main
    const RenderPassHandle main_pass_handle = builder.create_render_pass("Main Pass");
    const RenderPassHandle gui_pass_handle = builder.create_render_pass("GUI Pass");

    GPUTextureProperties scene_hdr_properties =
        DefaultGPUTextureProperties(backbufferExtent.width, backbufferExtent.height, MainHDRColorFormat);
    scene_hdr_properties.usageFlags = GPUTextureUsage::ColorAttachment | GPUTextureUsage::Sampled; // FIXME deduced?

    GPUTextureProperties scene_depth_properties =
        DefaultGPUTextureProperties(backbufferExtent.width, backbufferExtent.height, MainDepthFormat);
    scene_depth_properties.usageFlags = GPUTextureUsage::DepthStencilAttachment; // FIXME deduced?

    GPUTextureProperties gui_properties =
        DefaultGPUTextureProperties(backbufferExtent.width, backbufferExtent.height, GUIFormat);
    gui_properties.usageFlags = GPUTextureUsage::ColorAttachment | GPUTextureUsage::Sampled;

    const GPUTextureAccess scene_hdr_access_main_pass = {VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
                                                         VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
                                                         VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED};

    TGPUTextureUsage scene_hdr_texture_usage = {};
    scene_hdr_texture_usage.LoadOp = ELoadOp::DontCare;
    scene_hdr_texture_usage.access = scene_hdr_access_main_pass;
    scene_hdr_texture_usage.view = DefaultGPUTextureView(scene_hdr_properties);

    TGPUTextureUsage scene_depth_texture_usage = {};
    scene_depth_texture_usage.LoadOp = ELoadOp::DontCare;
    scene_depth_texture_usage.access =
        GPUTextureAccess{VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
                         VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED};
    scene_depth_texture_usage.view = DefaultGPUTextureView(scene_depth_properties);

    TGPUTextureUsage gui_texture_usage = {};
    gui_texture_usage.LoadOp = ELoadOp::Clear;
    gui_texture_usage.access =
        GPUTextureAccess{VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
                         VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED};
    gui_texture_usage.view = DefaultGPUTextureView(gui_properties);

    const ResourceUsageHandle main_hdr_usage_handle =
        builder.create_texture(main_pass_handle, "Scene HDR", scene_hdr_properties, scene_hdr_texture_usage);

    const ResourceUsageHandle main_depth_create_usage_handle =
        builder.create_texture(main_pass_handle, "Scene Depth", scene_depth_properties, scene_depth_texture_usage);

    const ResourceUsageHandle gui_create_usage_handle =
        builder.create_texture(gui_pass_handle, "GUI SDR", gui_properties, gui_texture_usage);

    // Swapchain
    const RenderPassHandle swapchain_pass_handle = builder.create_render_pass("Swapchain Pass", true);

    TGPUTextureUsage swapchain_hdr_usage = {};
    swapchain_hdr_usage.LoadOp = ELoadOp::Load;
    swapchain_hdr_usage.access = GPUTextureAccess{VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT,
                                                  VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, VK_QUEUE_FAMILY_IGNORED};
    swapchain_hdr_usage.view = DefaultGPUTextureView(scene_hdr_properties);

    TGPUTextureUsage swapchain_gui_usage = {};
    swapchain_gui_usage.LoadOp = ELoadOp::Load;
    swapchain_gui_usage.access = GPUTextureAccess{VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_READ_BIT,
                                                  VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, VK_QUEUE_FAMILY_IGNORED};
    swapchain_gui_usage.view = DefaultGPUTextureView(gui_properties);

    const ResourceUsageHandle swapchain_hdr_usage_handle =
        builder.read_texture(swapchain_pass_handle, main_hdr_usage_handle, swapchain_hdr_usage);
    const ResourceUsageHandle swapchain_gui_usage_handle =
        builder.read_texture(swapchain_pass_handle, gui_create_usage_handle, swapchain_gui_usage);
    builder.build();

    allocate_framegraph_volatile_resources(root, backend, resources.framegraph_resources, frame_graph);

    const ResourceUsage& main_hdr_usage = GetResourceUsage(frame_graph, main_hdr_usage_handle);
    const ResourceHandle main_hdr_resource_handle = main_hdr_usage.Resource;

    const ResourceUsage& main_depth_usage = GetResourceUsage(frame_graph, main_depth_create_usage_handle);
    const ResourceHandle main_depth_resource_handle = main_depth_usage.Resource;

    const ResourceUsage& gui_usage = GetResourceUsage(frame_graph, gui_create_usage_handle);
    const ResourceHandle gui_resource_handle = gui_usage.Resource;

    ImageInfo& hdrBuffer = get_frame_graph_texture(resources.framegraph_resources, main_hdr_resource_handle);
    ImageInfo& depthBuffer = get_frame_graph_texture(resources.framegraph_resources, main_depth_resource_handle);
    ImageInfo& guiBuffer = get_frame_graph_texture(resources.framegraph_resources, gui_resource_handle);

    const GPUTextureAccess src_undefined = {VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_ACCESS_2_NONE,
                                            VK_IMAGE_LAYOUT_UNDEFINED, VK_QUEUE_FAMILY_IGNORED};

    const GPUTextureAccess shadow_access_main_pass = {VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,
                                                      VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL,
                                                      VK_QUEUE_FAMILY_IGNORED};
    const GPUTextureAccess shadow_access_shadow_pass = {VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT,
                                                        VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
                                                        VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED};

    update_culling_pass_descriptor_sets(backend, prepared, resources.cull_resources, resources.mesh_cache);
    update_shadow_map_pass_descriptor_sets(backend, prepared, resources.shadow_map_resources);
    update_main_pass_descriptor_sets(backend, resources.main_pass_resources, resources.material_resources,
                                     resources.shadow_map_resources.shadowMapView);
    // update_histogram_pass_descriptor_set(backend, resources.histogram_pass_resources, hdrBufferView);
    update_swapchain_pass_descriptor_set(
        backend, resources.swapchain_pass_resources,
        get_frame_graph_texture_view(resources.framegraph_resources, swapchain_hdr_usage_handle),
        get_frame_graph_texture_view(resources.framegraph_resources, swapchain_gui_usage_handle));
    update_audio_pass_descriptor_set(backend, resources.audio_resources);

    log_debug(root, "vulkan: record command buffer");
    Assert(vkResetCommandBuffer(cmdBuffer.handle, 0) == VK_SUCCESS);

    VkCommandBufferBeginInfo cmdBufferBeginInfo = {
        VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
        0,      // Not caring yet
        nullptr // No inheritance yet
    };

    Assert(vkBeginCommandBuffer(cmdBuffer.handle, &cmdBufferBeginInfo) == VK_SUCCESS);

#if defined(REAPER_USE_MICROPROFILE)
    cmdBuffer.mlog = MicroProfileThreadLogGpuAlloc();
    MICROPROFILE_GPU_BEGIN(cmdBuffer.handle, cmdBuffer.mlog);
#endif

    record_material_upload_command_buffer(resources.material_resources.staging, cmdBuffer);

    {
        // FIXME Right now we recreate shadow maps every frame
        REAPER_PROFILE_SCOPE_GPU(cmdBuffer.mlog, "Barrier", MP_RED);

        std::vector<VkImageMemoryBarrier2> imageBarriers;

        for (ImageInfo& shadow_map : resources.shadow_map_resources.shadowMap)
        {
            imageBarriers.emplace_back(get_vk_image_barrier(shadow_map.handle,
                                                            DefaultGPUTextureView(shadow_map.properties), src_undefined,
                                                            shadow_access_main_pass));
        }

        imageBarriers.emplace_back(get_vk_image_barrier(hdrBuffer.handle, swapchain_hdr_usage.view, src_undefined,
                                                        swapchain_hdr_usage.access));
        imageBarriers.emplace_back(get_vk_image_barrier(depthBuffer.handle, scene_depth_texture_usage.view,
                                                        src_undefined, scene_depth_texture_usage.access));
        imageBarriers.emplace_back(get_vk_image_barrier(guiBuffer.handle, swapchain_gui_usage.view, src_undefined,
                                                        swapchain_gui_usage.access));

        const VkDependencyInfo dependencies =
            get_vk_image_barrier_depency_info(static_cast<u32>(imageBarriers.size()), imageBarriers.data());

        vkCmdSetEvent2(cmdBuffer.handle, resources.event, &dependencies);
        vkCmdWaitEvents2(cmdBuffer.handle, 1, &resources.event, &dependencies);
    }

    if (backend.mustTransitionSwapchain)
    {
        REAPER_PROFILE_SCOPE_GPU(cmdBuffer.mlog, "Barrier", MP_RED);

        std::vector<VkImageMemoryBarrier2> imageBarriers;

        for (u32 swapchainImageIndex = 0; swapchainImageIndex < static_cast<u32>(backend.presentInfo.images.size());
             swapchainImageIndex++)
        {
            const GPUTextureAccess dst = {VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, VK_ACCESS_2_MEMORY_READ_BIT,
                                          VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_QUEUE_FAMILY_IGNORED};

            GPUTextureView view = {};
            // view.format;
            view.aspect = ViewAspect::Color;
            view.mipCount = 1;
            view.layerCount = 1;

            imageBarriers.emplace_back(
                get_vk_image_barrier(backend.presentInfo.images[swapchainImageIndex], view, src_undefined, dst));
        }

        const VkDependencyInfo dependencies =
            get_vk_image_barrier_depency_info(static_cast<u32>(imageBarriers.size()), imageBarriers.data());

        vkCmdSetEvent2(cmdBuffer.handle, resources.event, &dependencies);
        vkCmdWaitEvents2(cmdBuffer.handle, 1, &resources.event, &dependencies);

        backend.mustTransitionSwapchain = false;
    }

    record_culling_command_buffer(backend.options.freeze_culling, cmdBuffer, prepared, resources.cull_resources);

    {
        REAPER_PROFILE_SCOPE_GPU(cmdBuffer.mlog, "Barrier", MP_RED);

        std::vector<VkImageMemoryBarrier2> imageBarriers;

        for (ImageInfo& shadow_map : resources.shadow_map_resources.shadowMap)
        {
            imageBarriers.emplace_back(get_vk_image_barrier(shadow_map.handle,
                                                            DefaultGPUTextureView(shadow_map.properties),
                                                            shadow_access_main_pass, shadow_access_shadow_pass));
        }

        const VkDependencyInfo dependencies =
            get_vk_image_barrier_depency_info(static_cast<u32>(imageBarriers.size()), imageBarriers.data());

        vkCmdSetEvent2(cmdBuffer.handle, resources.event, &dependencies);
        vkCmdWaitEvents2(cmdBuffer.handle, 1, &resources.event, &dependencies);
    }

    record_shadow_map_command_buffer(cmdBuffer, backend, prepared, resources.shadow_map_resources,
                                     resources.cull_resources, resources.mesh_cache.vertexBufferPosition.buffer);

    {
        REAPER_PROFILE_SCOPE_GPU(cmdBuffer.mlog, "Barrier", MP_RED);

        std::vector<VkImageMemoryBarrier2> imageBarriers;

        for (ImageInfo& shadow_map : resources.shadow_map_resources.shadowMap)
        {
            imageBarriers.emplace_back(get_vk_image_barrier(shadow_map.handle,
                                                            DefaultGPUTextureView(shadow_map.properties),
                                                            shadow_access_shadow_pass, shadow_access_main_pass));
        }

        imageBarriers.emplace_back(get_vk_image_barrier(hdrBuffer.handle, scene_hdr_texture_usage.view,
                                                        swapchain_hdr_usage.access, scene_hdr_texture_usage.access));

        const VkDependencyInfo dependencies =
            get_vk_image_barrier_depency_info(static_cast<u32>(imageBarriers.size()), imageBarriers.data());

        vkCmdSetEvent2(cmdBuffer.handle, resources.event, &dependencies);
        vkCmdWaitEvents2(cmdBuffer.handle, 1, &resources.event, &dependencies);
    }

    record_main_pass_command_buffer(
        cmdBuffer, backend, prepared, resources.main_pass_resources, resources.cull_resources, resources.mesh_cache,
        backbufferExtent, get_frame_graph_texture_view(resources.framegraph_resources, main_hdr_usage_handle),
        get_frame_graph_texture_view(resources.framegraph_resources, main_depth_create_usage_handle));

    {
        std::vector<VkImageMemoryBarrier2> imageBarriers;
        imageBarriers.emplace_back(get_vk_image_barrier(guiBuffer.handle, gui_texture_usage.view,
                                                        swapchain_gui_usage.access, gui_texture_usage.access));

        const VkDependencyInfo dependencies =
            get_vk_image_barrier_depency_info(static_cast<u32>(imageBarriers.size()), imageBarriers.data());

        vkCmdSetEvent2(cmdBuffer.handle, resources.event, &dependencies);
        vkCmdWaitEvents2(cmdBuffer.handle, 1, &resources.event, &dependencies);
    }

    record_gui_command_buffer(cmdBuffer, resources.gui_pass_resources, backbufferExtent,
                              get_frame_graph_texture_view(resources.framegraph_resources, gui_create_usage_handle));

    {
        REAPER_PROFILE_SCOPE_GPU(cmdBuffer.mlog, "Barrier", MP_RED);

        std::vector<VkImageMemoryBarrier2> imageBarriers;

        imageBarriers.emplace_back(get_vk_image_barrier(hdrBuffer.handle, swapchain_hdr_usage.view,
                                                        scene_hdr_texture_usage.access, swapchain_hdr_usage.access));
        imageBarriers.emplace_back(get_vk_image_barrier(guiBuffer.handle, swapchain_gui_usage.view,
                                                        gui_texture_usage.access, swapchain_gui_usage.access));

        const VkDependencyInfo dependencies =
            get_vk_image_barrier_depency_info(static_cast<u32>(imageBarriers.size()), imageBarriers.data());

        vkCmdSetEvent2(cmdBuffer.handle, resources.event, &dependencies);
        vkCmdWaitEvents2(cmdBuffer.handle, 1, &resources.event, &dependencies);
    }

    // record_histogram_command_buffer(cmdBuffer, frame_data, resources.histogram_pass_resources);

    record_swapchain_command_buffer(cmdBuffer, frame_data, resources.swapchain_pass_resources,
                                    backend.presentInfo.imageViews[current_swapchain_index]);

    record_audio_command_buffer(cmdBuffer, prepared, resources.audio_resources);

#if defined(REAPER_USE_MICROPROFILE)
    const u64 microprofile_data = MicroProfileGpuEnd(cmdBuffer.mlog);
    MicroProfileThreadLogGpuFree(cmdBuffer.mlog);

    MICROPROFILE_GPU_SUBMIT(MicroProfileGetGlobalGpuQueue(), microprofile_data);
    MicroProfileFlip(cmdBuffer.handle);
#endif

    // Stop recording
    Assert(vkEndCommandBuffer(cmdBuffer.handle) == VK_SUCCESS);

    VkPipelineStageFlags blitWaitDstMask = VK_PIPELINE_STAGE_TRANSFER_BIT;

    std::array<VkSemaphore, 1> semaphores_to_signal = {backend.presentInfo.renderingFinishedSemaphore};

    VkSubmitInfo blitSubmitInfo = {VK_STRUCTURE_TYPE_SUBMIT_INFO,
                                   nullptr,
                                   1,
                                   &backend.presentInfo.imageAvailableSemaphore,
                                   &blitWaitDstMask,
                                   1,
                                   &cmdBuffer.handle,
                                   semaphores_to_signal.size(),
                                   semaphores_to_signal.data()};

    log_debug(root, "vulkan: submit drawing commands");
    Assert(vkQueueSubmit(backend.deviceInfo.graphicsQueue, 1, &blitSubmitInfo, resources.frame_sync_resources.drawFence)
           == VK_SUCCESS);

    log_debug(root, "vulkan: present");

    VkPresentInfoKHR presentInfo = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
                                    nullptr,
                                    1,
                                    &backend.presentInfo.renderingFinishedSemaphore,
                                    1,
                                    &backend.presentInfo.swapchain,
                                    &current_swapchain_index,
                                    nullptr};

    VkResult presentResult = vkQueuePresentKHR(backend.deviceInfo.presentQueue, &presentInfo);
    // NOTE: window can change state between event handling and presenting, so it's normal to get OOD events.
    Assert(presentResult == VK_SUCCESS || presentResult == VK_ERROR_OUT_OF_DATE_KHR);

    read_gpu_audio_data(backend, resources.audio_resources);
}
} // namespace Reaper


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.wouto</groupId>
    <artifactId>ModelSyncMongoDB</artifactId>
    <version>1.1.4</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    <name>ModelSyncMongoDB</name>
    <description>A simple mongo library that adds Query builders and Object syncing</description>
    <licenses>
        <license>
            <name>MIT License</name>
            <url>http://www.opensource.org/licenses/mit-license.php</url>
        </license>
    </licenses>
    <dependencies>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>
</project>


text:
<?php

namespace Phlexible\Component\MediaCache;

/**
 * Media cache events.
 *
 * @author Stephan Wentz <sw@brainbits.net>
 */
class MediaCacheEvents
{
    /**
     * Fired before a media cache item is saved.
     */
    const BEFORE_SAVE_CACHE_ITEM = 'phlexible_media_cache.before_save_cache_item';

    /**
     * Fired after a media cache item is saved.
     */
    const SAVE_CACHE_ITEM = 'phlexible_media_cache.save_cache_item';
}


text:
@protocol JFStoryboardObserver <NSObject>

@optional

- (void)	jf_storyboard:(NSStoryboard*)storyboard didInstantiateController:(id)controller withIdentifier:(NSString*)identifier;
- (void)	jf_storyboard:(NSStoryboard*)storyboard didInstantiateInitialController:(id)controller;
- (void)	jf_storyboard:(NSStoryboard*)storyboard didPerformSegue:(NSStoryboardSegue*)segue;
- (void)	jf_storyboard:(NSStoryboard*)storyboard willPerformSegue:(NSStoryboardSegue*)segue;

@end

#pragma mark

@interface NSStoryboard (JFFramework)

#pragma mark Properties

// Relationships
@property (strong, nonatomic, readonly)	NSMutableSet<id<JFStoryboardObserver>>*	jf_observers;

@end