2020-12-26 17:44:24 -05:00
/ * !
2021-04-14 19:36:35 -04:00
* matter - js 0.17 . 1 by @ liabru
2020-12-26 17:44:24 -05:00
* http : //brm.io/matter-js/
* License MIT
*
2014-02-19 09:15:05 -05:00
* The MIT License ( MIT )
*
2017-07-06 18:47:04 -04:00
* Copyright ( c ) Liam Brummitt and contributors .
2014-02-19 09:15:05 -05:00
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the "Software" ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
* /
2020-12-26 17:44:24 -05:00
( function webpackUniversalModuleDefinition ( root , factory ) {
if ( typeof exports === 'object' && typeof module === 'object' )
2021-04-11 12:49:36 -04:00
module . exports = factory ( ) ;
2020-12-26 17:44:24 -05:00
else if ( typeof define === 'function' && define . amd )
2021-04-11 12:49:36 -04:00
define ( "Matter" , [ ] , factory ) ;
2020-12-26 17:44:24 -05:00
else if ( typeof exports === 'object' )
2021-04-11 12:49:36 -04:00
exports [ "Matter" ] = factory ( ) ;
2020-12-26 17:44:24 -05:00
else
2021-04-11 12:49:36 -04:00
root [ "Matter" ] = factory ( ) ;
} ) ( this , function ( ) {
2020-12-26 17:44:24 -05:00
return /******/ ( function ( modules ) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = { } ;
/******/
/******/ // The require function
/******/ function _ _webpack _require _ _ ( moduleId ) {
/******/
/******/ // Check if module is in cache
/******/ if ( installedModules [ moduleId ] ) {
/******/ return installedModules [ moduleId ] . exports ;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules [ moduleId ] = {
/******/ i : moduleId ,
/******/ l : false ,
/******/ exports : { }
/******/ } ;
/******/
/******/ // Execute the module function
/******/ modules [ moduleId ] . call ( module . exports , module , module . exports , _ _webpack _require _ _ ) ;
/******/
/******/ // Flag the module as loaded
/******/ module . l = true ;
/******/
/******/ // Return the exports of the module
/******/ return module . exports ;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ _ _webpack _require _ _ . m = modules ;
/******/
/******/ // expose the module cache
/******/ _ _webpack _require _ _ . c = installedModules ;
/******/
/******/ // define getter function for harmony exports
/******/ _ _webpack _require _ _ . d = function ( exports , name , getter ) {
/******/ if ( ! _ _webpack _require _ _ . o ( exports , name ) ) {
/******/ Object . defineProperty ( exports , name , { enumerable : true , get : getter } ) ;
/******/ }
/******/ } ;
/******/
/******/ // define __esModule on exports
/******/ _ _webpack _require _ _ . r = function ( exports ) {
/******/ if ( typeof Symbol !== 'undefined' && Symbol . toStringTag ) {
/******/ Object . defineProperty ( exports , Symbol . toStringTag , { value : 'Module' } ) ;
/******/ }
/******/ Object . defineProperty ( exports , '__esModule' , { value : true } ) ;
/******/ } ;
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ _ _webpack _require _ _ . t = function ( value , mode ) {
/******/ if ( mode & 1 ) value = _ _webpack _require _ _ ( value ) ;
/******/ if ( mode & 8 ) return value ;
/******/ if ( ( mode & 4 ) && typeof value === 'object' && value && value . _ _esModule ) return value ;
/******/ var ns = Object . create ( null ) ;
/******/ _ _webpack _require _ _ . r ( ns ) ;
/******/ Object . defineProperty ( ns , 'default' , { enumerable : true , value : value } ) ;
/******/ if ( mode & 2 && typeof value != 'string' ) for ( var key in value ) _ _webpack _require _ _ . d ( ns , key , function ( key ) { return value [ key ] ; } . bind ( null , key ) ) ;
/******/ return ns ;
/******/ } ;
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ _ _webpack _require _ _ . n = function ( module ) {
/******/ var getter = module && module . _ _esModule ?
/******/ function getDefault ( ) { return module [ 'default' ] ; } :
/******/ function getModuleExports ( ) { return module ; } ;
/******/ _ _webpack _require _ _ . d ( getter , 'a' , getter ) ;
/******/ return getter ;
/******/ } ;
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ _ _webpack _require _ _ . o = function ( object , property ) { return Object . prototype . hasOwnProperty . call ( object , property ) ; } ;
/******/
/******/ // __webpack_public_path__
/******/ _ _webpack _require _ _ . p = "" ;
/******/
/******/
/******/ // Load entry module and return exports
2021-04-11 12:49:36 -04:00
/******/ return _ _webpack _require _ _ ( _ _webpack _require _ _ . s = 22 ) ;
2020-12-26 17:44:24 -05:00
/******/ } )
/************************************************************************/
/******/ ( [
/* 0 */
/***/ ( function ( module , exports ) {
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* The ` Matter.Common ` module contains utility functions that are common to all modules .
2014-06-09 14:40:24 -04:00
*
2020-12-26 17:44:24 -05:00
* @ class Common
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
var Common = { } ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
module . exports = Common ;
2015-08-17 18:50:03 -04:00
2014-02-19 09:15:05 -05:00
( function ( ) {
2020-12-26 17:44:24 -05:00
Common . _nextId = 0 ;
Common . _seed = 0 ;
Common . _nowStartTime = + ( new Date ( ) ) ;
2021-04-11 12:49:36 -04:00
Common . _warnedOnce = { } ;
Common . _decomp = null ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Extends the object in the first argument using the object in the second argument .
* @ method extend
* @ param { } obj
* @ param { boolean } deep
* @ return { } obj extended
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . extend = function ( obj , deep ) {
var argsStart ,
args ,
deepClone ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( typeof deep === 'boolean' ) {
argsStart = 2 ;
deepClone = deep ;
} else {
argsStart = 1 ;
deepClone = true ;
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = argsStart ; i < arguments . length ; i ++ ) {
var source = arguments [ i ] ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( source ) {
for ( var prop in source ) {
if ( deepClone && source [ prop ] && source [ prop ] . constructor === Object ) {
if ( ! obj [ prop ] || obj [ prop ] . constructor === Object ) {
obj [ prop ] = obj [ prop ] || { } ;
Common . extend ( obj [ prop ] , deepClone , source [ prop ] ) ;
} else {
obj [ prop ] = source [ prop ] ;
}
} else {
obj [ prop ] = source [ prop ] ;
}
}
}
}
return obj ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Creates a new clone of the object , if deep is true references will also be cloned .
* @ method clone
* @ param { } obj
* @ param { bool } deep
* @ return { } obj cloned
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . clone = function ( obj , deep ) {
return Common . extend ( { } , deep , obj ) ;
2014-02-19 09:15:05 -05:00
} ;
2015-01-01 18:10:10 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the list of keys for the given object .
* @ method keys
* @ param { } obj
* @ return { string [ ] } keys
2015-01-01 18:10:10 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . keys = function ( obj ) {
if ( Object . keys )
return Object . keys ( obj ) ;
// avoid hasOwnProperty for performance
var keys = [ ] ;
for ( var key in obj )
keys . push ( key ) ;
return keys ;
2015-01-01 18:10:10 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the list of values for the given object .
* @ method values
* @ param { } obj
* @ return { array } Array of the objects property values
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . values = function ( obj ) {
var values = [ ] ;
if ( Object . keys ) {
var keys = Object . keys ( obj ) ;
for ( var i = 0 ; i < keys . length ; i ++ ) {
values . push ( obj [ keys [ i ] ] ) ;
}
return values ;
}
// avoid hasOwnProperty for performance
for ( var key in obj )
values . push ( obj [ key ] ) ;
return values ;
2014-05-01 09:09:06 -04:00
} ;
2014-12-28 13:37:43 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Gets a value from ` base ` relative to the ` path ` string .
* @ method get
* @ param { } obj The base object
* @ param { string } path The path relative to ` base ` , e . g . 'Foo.Bar.baz'
* @ param { number } [ begin ] Path slice begin
* @ param { number } [ end ] Path slice end
* @ return { } The object at the given path
2014-12-28 13:37:43 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . get = function ( obj , path , begin , end ) {
path = path . split ( '.' ) . slice ( begin , end ) ;
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < path . length ; i += 1 ) {
obj = obj [ path [ i ] ] ;
2014-12-28 13:37:43 -05:00
}
2020-12-26 17:44:24 -05:00
return obj ;
} ;
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* Sets a value on ` base ` relative to the given ` path ` string .
* @ method set
* @ param { } obj The base object
* @ param { string } path The path relative to ` base ` , e . g . 'Foo.Bar.baz'
* @ param { } val The value to set
* @ param { number } [ begin ] Path slice begin
* @ param { number } [ end ] Path slice end
* @ return { } Pass through ` val ` for chaining
* /
Common . set = function ( obj , path , val , begin , end ) {
var parts = path . split ( '.' ) . slice ( begin , end ) ;
Common . get ( obj , path , 0 , - 1 ) [ parts [ parts . length - 1 ] ] = val ;
return val ;
} ;
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* Shuffles the given array in - place .
* The function uses a seeded random generator .
* @ method shuffle
* @ param { array } array
* @ return { array } array shuffled randomly
* /
Common . shuffle = function ( array ) {
for ( var i = array . length - 1 ; i > 0 ; i -- ) {
var j = Math . floor ( Common . random ( ) * ( i + 1 ) ) ;
var temp = array [ i ] ;
array [ i ] = array [ j ] ;
array [ j ] = temp ;
2014-12-28 13:37:43 -05:00
}
2020-12-26 17:44:24 -05:00
return array ;
2014-12-28 13:37:43 -05:00
} ;
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Randomly chooses a value from a list with equal probability .
* The function uses a seeded random generator .
* @ method choose
* @ param { array } choices
* @ return { object } A random choice object from the array
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . choose = function ( choices ) {
return choices [ Math . floor ( Common . random ( ) * choices . length ) ] ;
2014-02-19 09:15:05 -05:00
} ;
2014-07-29 11:26:49 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the object is a HTMLElement , otherwise false .
* @ method isElement
* @ param { object } obj
* @ return { boolean } True if the object is a HTMLElement , otherwise false
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . isElement = function ( obj ) {
if ( typeof HTMLElement !== 'undefined' ) {
return obj instanceof HTMLElement ;
}
2017-11-29 19:16:03 -05:00
2020-12-26 17:44:24 -05:00
return ! ! ( obj && obj . nodeType && obj . nodeName ) ;
2014-07-29 11:26:49 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the object is an array .
* @ method isArray
* @ param { object } obj
* @ return { boolean } True if the object is an array , otherwise false
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . isArray = function ( obj ) {
return Object . prototype . toString . call ( obj ) === '[object Array]' ;
2014-07-29 11:26:49 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the object is a function .
* @ method isFunction
* @ param { object } obj
* @ return { boolean } True if the object is a function , otherwise false
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . isFunction = function ( obj ) {
return typeof obj === "function" ;
2014-07-29 11:26:49 -04:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the object is a plain object .
* @ method isPlainObject
* @ param { object } obj
* @ return { boolean } True if the object is a plain object , otherwise false
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . isPlainObject = function ( obj ) {
return typeof obj === 'object' && obj . constructor === Object ;
2014-06-09 14:40:24 -04:00
} ;
2015-05-20 15:38:41 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the object is a string .
* @ method isString
* @ param { object } obj
* @ return { boolean } True if the object is a string , otherwise false
2015-05-20 15:38:41 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . isString = function ( obj ) {
return toString . call ( obj ) === '[object String]' ;
} ;
/ * *
* Returns the given value clamped between a minimum and maximum value .
* @ method clamp
* @ param { number } value
* @ param { number } min
* @ param { number } max
* @ return { number } The value clamped between min and max inclusive
* /
Common . clamp = function ( value , min , max ) {
if ( value < min )
return min ;
if ( value > max )
return max ;
return value ;
} ;
/ * *
* Returns the sign of the given value .
* @ method sign
* @ param { number } value
* @ return { number } - 1 if negative , + 1 if 0 or positive
* /
Common . sign = function ( value ) {
return value < 0 ? - 1 : 1 ;
} ;
/ * *
* Returns the current timestamp since the time origin ( e . g . from page load ) .
2021-04-11 12:49:36 -04:00
* The result is in milliseconds and will use high - resolution timing if available .
2020-12-26 17:44:24 -05:00
* @ method now
2021-04-11 12:49:36 -04:00
* @ return { number } the current timestamp in milliseconds
2020-12-26 17:44:24 -05:00
* /
Common . now = function ( ) {
if ( typeof window !== 'undefined' && window . performance ) {
if ( window . performance . now ) {
return window . performance . now ( ) ;
} else if ( window . performance . webkitNow ) {
return window . performance . webkitNow ( ) ;
2015-05-20 15:38:41 -04:00
}
}
2021-04-11 12:49:36 -04:00
if ( Date . now ) {
return Date . now ( ) ;
}
2020-12-26 17:44:24 -05:00
return ( new Date ( ) ) - Common . _nowStartTime ;
} ;
/ * *
* Returns a random value between a minimum and a maximum value inclusive .
* The function uses a seeded random generator .
* @ method random
* @ param { number } min
* @ param { number } max
* @ return { number } A random number between min and max inclusive
* /
Common . random = function ( min , max ) {
min = ( typeof min !== "undefined" ) ? min : 0 ;
max = ( typeof max !== "undefined" ) ? max : 1 ;
return min + _seededRandom ( ) * ( max - min ) ;
} ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
var _seededRandom = function ( ) {
// https://en.wikipedia.org/wiki/Linear_congruential_generator
Common . _seed = ( Common . _seed * 9301 + 49297 ) % 233280 ;
return Common . _seed / 233280 ;
} ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Converts a CSS hex colour string into an integer .
* @ method colorToNumber
* @ param { string } colorString
* @ return { number } An integer representing the CSS hex string
* /
Common . colorToNumber = function ( colorString ) {
colorString = colorString . replace ( '#' , '' ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
if ( colorString . length == 3 ) {
colorString = colorString . charAt ( 0 ) + colorString . charAt ( 0 )
+ colorString . charAt ( 1 ) + colorString . charAt ( 1 )
+ colorString . charAt ( 2 ) + colorString . charAt ( 2 ) ;
2015-05-20 15:38:41 -04:00
}
2020-12-26 17:44:24 -05:00
return parseInt ( colorString , 16 ) ;
2015-05-20 15:38:41 -04:00
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* The console logging level to use , where each level includes all levels above and excludes the levels below .
* The default level is 'debug' which shows all console messages .
*
* Possible level values are :
* - 0 = None
* - 1 = Debug
* - 2 = Info
* - 3 = Warn
* - 4 = Error
* @ property Common . logLevel
* @ type { Number }
* @ default 1
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . logLevel = 1 ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Shows a ` console.log ` message only if the current ` Common.logLevel ` allows it .
* The message will be prefixed with 'matter-js' to make it easily identifiable .
* @ method log
* @ param ... objs { } The objects to log .
* /
Common . log = function ( ) {
if ( console && Common . logLevel > 0 && Common . logLevel <= 3 ) {
console . log . apply ( console , [ 'matter-js:' ] . concat ( Array . prototype . slice . call ( arguments ) ) ) ;
2015-05-20 15:38:41 -04:00
}
2014-06-09 14:40:24 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Shows a ` console.info ` message only if the current ` Common.logLevel ` allows it .
* The message will be prefixed with 'matter-js' to make it easily identifiable .
* @ method info
* @ param ... objs { } The objects to log .
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . info = function ( ) {
if ( console && Common . logLevel > 0 && Common . logLevel <= 2 ) {
console . info . apply ( console , [ 'matter-js:' ] . concat ( Array . prototype . slice . call ( arguments ) ) ) ;
2015-05-20 15:38:41 -04:00
}
2014-06-09 14:40:24 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Shows a ` console.warn ` message only if the current ` Common.logLevel ` allows it .
* The message will be prefixed with 'matter-js' to make it easily identifiable .
* @ method warn
* @ param ... objs { } The objects to log .
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . warn = function ( ) {
if ( console && Common . logLevel > 0 && Common . logLevel <= 3 ) {
console . warn . apply ( console , [ 'matter-js:' ] . concat ( Array . prototype . slice . call ( arguments ) ) ) ;
}
2014-06-09 14:40:24 -04:00
} ;
2021-04-11 12:49:36 -04:00
/ * *
* Uses ` Common.warn ` to log the given message one time only .
* @ method warnOnce
* @ param ... objs { } The objects to log .
* /
Common . warnOnce = function ( ) {
var message = Array . prototype . slice . call ( arguments ) . join ( ' ' ) ;
if ( ! Common . _warnedOnce [ message ] ) {
Common . warn ( message ) ;
Common . _warnedOnce [ message ] = true ;
}
} ;
/ * *
* Shows a deprecated console warning when the function on the given object is called .
* The target function will be replaced with a new function that first shows the warning
* and then calls the original function .
* @ method deprecated
* @ param { object } obj The object or module
* @ param { string } name The property name of the function on obj
* @ param { string } warning The one - time message to show if the function is called
* /
Common . deprecated = function ( obj , prop , warning ) {
obj [ prop ] = Common . chain ( function ( ) {
Common . warnOnce ( '🔅 deprecated 🔅' , warning ) ;
} , obj [ prop ] ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the next unique sequential ID .
* @ method nextId
* @ return { Number } Unique sequential ID
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . nextId = function ( ) {
return Common . _nextId ++ ;
2014-06-09 14:40:24 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* A cross browser compatible indexOf implementation .
* @ method indexOf
* @ param { array } haystack
* @ param { object } needle
* @ return { number } The position of needle in haystack , otherwise - 1.
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . indexOf = function ( haystack , needle ) {
if ( haystack . indexOf )
return haystack . indexOf ( needle ) ;
for ( var i = 0 ; i < haystack . length ; i ++ ) {
if ( haystack [ i ] === needle )
return i ;
}
return - 1 ;
2014-06-09 14:40:24 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* A cross browser compatible array map implementation .
* @ method map
* @ param { array } list
* @ param { function } func
* @ return { array } Values from list transformed by func .
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . map = function ( list , func ) {
if ( list . map ) {
return list . map ( func ) ;
}
2017-05-03 19:40:04 -04:00
2020-12-26 17:44:24 -05:00
var mapped = [ ] ;
for ( var i = 0 ; i < list . length ; i += 1 ) {
mapped . push ( func ( list [ i ] ) ) ;
2017-05-03 19:40:04 -04:00
}
2020-12-26 17:44:24 -05:00
return mapped ;
2014-06-09 14:40:24 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Takes a directed graph and returns the partially ordered set of vertices in topological order .
* Circular dependencies are allowed .
* @ method topologicalSort
* @ param { object } graph
* @ return { array } Partially ordered set of vertices in topological order .
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . topologicalSort = function ( graph ) {
// https://github.com/mgechev/javascript-algorithms
// Copyright (c) Minko Gechev (MIT license)
// Modifications: tidy formatting and naming
var result = [ ] ,
visited = [ ] ,
temp = [ ] ;
2017-11-29 19:16:03 -05:00
2020-12-26 17:44:24 -05:00
for ( var node in graph ) {
if ( ! visited [ node ] && ! temp [ node ] ) {
Common . _topologicalSort ( node , visited , temp , graph , result ) ;
}
}
2017-11-29 19:16:03 -05:00
2020-12-26 17:44:24 -05:00
return result ;
} ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
Common . _topologicalSort = function ( node , visited , temp , graph , result ) {
var neighbors = graph [ node ] || [ ] ;
temp [ node ] = true ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < neighbors . length ; i += 1 ) {
var neighbor = neighbors [ i ] ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( temp [ neighbor ] ) {
// skip circular dependencies
continue ;
}
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
if ( ! visited [ neighbor ] ) {
Common . _topologicalSort ( neighbor , visited , temp , graph , result ) ;
2015-05-20 15:38:41 -04:00
}
}
2020-12-26 17:44:24 -05:00
temp [ node ] = false ;
visited [ node ] = true ;
2017-11-29 19:16:03 -05:00
2020-12-26 17:44:24 -05:00
result . push ( node ) ;
2014-06-09 14:40:24 -04:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Takes _n _ functions as arguments and returns a new function that calls them in order .
* The arguments applied when calling the new function will also be applied to every function passed .
* The value of ` this ` refers to the last value returned in the chain that was not ` undefined ` .
* Therefore if a passed function does not return a value , the previously returned value is maintained .
* After all passed functions have been called the new function returns the last returned value ( if any ) .
* If any of the passed functions are a chain , then the chain will be flattened .
* @ method chain
* @ param ... funcs { function } The functions to chain .
* @ return { function } A new function that calls the passed functions in order .
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . chain = function ( ) {
var funcs = [ ] ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < arguments . length ; i += 1 ) {
var func = arguments [ i ] ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( func . _chained ) {
// flatten already chained functions
funcs . push . apply ( funcs , func . _chained ) ;
} else {
funcs . push ( func ) ;
}
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var chain = function ( ) {
// https://github.com/GoogleChrome/devtools-docs/issues/53#issuecomment-51941358
var lastResult ,
args = new Array ( arguments . length ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 , l = arguments . length ; i < l ; i ++ ) {
args [ i ] = arguments [ i ] ;
2015-05-20 15:38:41 -04:00
}
2020-12-26 17:44:24 -05:00
for ( i = 0 ; i < funcs . length ; i += 1 ) {
var result = funcs [ i ] . apply ( lastResult , args ) ;
if ( typeof result !== 'undefined' ) {
lastResult = result ;
2015-05-20 15:38:41 -04:00
}
}
2020-12-26 17:44:24 -05:00
return lastResult ;
} ;
chain . _chained = funcs ;
return chain ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Chains a function to excute before the original function on the given ` path ` relative to ` base ` .
* See also docs for ` Common.chain ` .
* @ method chainPathBefore
* @ param { } base The base object
* @ param { string } path The path relative to ` base `
* @ param { function } func The function to chain before the original
* @ return { function } The chained function that replaced the original
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Common . chainPathBefore = function ( base , path , func ) {
return Common . set ( base , path , Common . chain (
func ,
Common . get ( base , path )
) ) ;
2014-02-19 09:15:05 -05:00
} ;
2015-05-20 15:38:41 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Chains a function to excute after the original function on the given ` path ` relative to ` base ` .
* See also docs for ` Common.chain ` .
* @ method chainPathAfter
* @ param { } base The base object
* @ param { string } path The path relative to ` base `
* @ param { function } func The function to chain after the original
* @ return { function } The chained function that replaced the original
2015-05-20 15:38:41 -04:00
* /
2020-12-26 17:44:24 -05:00
Common . chainPathAfter = function ( base , path , func ) {
return Common . set ( base , path , Common . chain (
Common . get ( base , path ) ,
func
) ) ;
} ;
2021-04-11 12:49:36 -04:00
/ * *
* Provide the [ poly - decomp ] ( https : //github.com/schteppe/poly-decomp.js) library module to enable
* concave vertex decomposition support when using ` Bodies.fromVertices ` e . g . ` Common.setDecomp(require('poly-decomp')) ` .
* @ method setDecomp
* @ param { } decomp The [ poly - decomp ] ( https : //github.com/schteppe/poly-decomp.js) library module.
* /
Common . setDecomp = function ( decomp ) {
Common . _decomp = decomp ;
} ;
/ * *
* Returns the [ poly - decomp ] ( https : //github.com/schteppe/poly-decomp.js) library module provided through `Common.setDecomp`,
* otherwise returns the global ` decomp ` if set .
* @ method getDecomp
* @ return { } The [ poly - decomp ] ( https : //github.com/schteppe/poly-decomp.js) library module if provided.
* /
Common . getDecomp = function ( ) {
// get user provided decomp if set
var decomp = Common . _decomp ;
try {
// otherwise from window global
if ( ! decomp && typeof window !== 'undefined' ) {
decomp = window . decomp ;
}
// otherwise from node global
if ( ! decomp && typeof global !== 'undefined' ) {
decomp = global . decomp ;
}
} catch ( e ) {
// decomp not available
decomp = null ;
}
return decomp ;
} ;
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 1 */
/***/ ( function ( module , exports ) {
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* The ` Matter.Bounds ` module contains methods for creating and manipulating axis - aligned bounding boxes ( AABB ) .
*
* @ class Bounds
* /
2015-06-29 15:58:24 -04:00
2020-12-26 17:44:24 -05:00
var Bounds = { } ;
2015-06-29 15:58:24 -04:00
2020-12-26 17:44:24 -05:00
module . exports = Bounds ;
2015-06-29 15:58:24 -04:00
2020-12-26 17:44:24 -05:00
( function ( ) {
2014-06-09 14:40:24 -04:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Creates a new axis - aligned bounding box ( AABB ) for the given vertices .
* @ method create
* @ param { vertices } vertices
* @ return { bounds } A new bounds object
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Bounds . create = function ( vertices ) {
var bounds = {
min : { x : 0 , y : 0 } ,
max : { x : 0 , y : 0 }
} ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( vertices )
Bounds . update ( bounds , vertices ) ;
return bounds ;
} ;
2014-02-19 09:15:05 -05:00
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Updates bounds using the given vertices and extends the bounds given a velocity .
* @ method update
* @ param { bounds } bounds
* @ param { vertices } vertices
* @ param { vector } velocity
2015-05-20 15:38:41 -04:00
* /
2020-12-26 17:44:24 -05:00
Bounds . update = function ( bounds , vertices , velocity ) {
bounds . min . x = Infinity ;
bounds . max . x = - Infinity ;
bounds . min . y = Infinity ;
bounds . max . y = - Infinity ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < vertices . length ; i ++ ) {
var vertex = vertices [ i ] ;
if ( vertex . x > bounds . max . x ) bounds . max . x = vertex . x ;
if ( vertex . x < bounds . min . x ) bounds . min . x = vertex . x ;
if ( vertex . y > bounds . max . y ) bounds . max . y = vertex . y ;
if ( vertex . y < bounds . min . y ) bounds . min . y = vertex . y ;
}
if ( velocity ) {
if ( velocity . x > 0 ) {
bounds . max . x += velocity . x ;
} else {
bounds . min . x += velocity . x ;
}
if ( velocity . y > 0 ) {
bounds . max . y += velocity . y ;
} else {
bounds . min . y += velocity . y ;
}
}
} ;
2017-01-26 18:49:29 -05:00
2015-05-20 15:38:41 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the bounds contains the given point .
* @ method contains
* @ param { bounds } bounds
* @ param { vector } point
* @ return { boolean } True if the bounds contain the point , otherwise false
2015-05-20 15:38:41 -04:00
* /
2020-12-26 17:44:24 -05:00
Bounds . contains = function ( bounds , point ) {
return point . x >= bounds . min . x && point . x <= bounds . max . x
&& point . y >= bounds . min . y && point . y <= bounds . max . y ;
} ;
2015-05-20 15:38:41 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the two bounds intersect .
* @ method overlaps
* @ param { bounds } boundsA
* @ param { bounds } boundsB
* @ return { boolean } True if the bounds overlap , otherwise false
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Bounds . overlaps = function ( boundsA , boundsB ) {
return ( boundsA . min . x <= boundsB . max . x && boundsA . max . x >= boundsB . min . x
&& boundsA . max . y >= boundsB . min . y && boundsA . min . y <= boundsB . max . y ) ;
} ;
2014-05-01 09:09:06 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Translates the bounds by the given vector .
* @ method translate
* @ param { bounds } bounds
* @ param { vector } vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Bounds . translate = function ( bounds , vector ) {
bounds . min . x += vector . x ;
bounds . max . x += vector . x ;
bounds . min . y += vector . y ;
bounds . max . y += vector . y ;
} ;
2014-05-01 09:09:06 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Shifts the bounds to the given position .
* @ method shift
* @ param { bounds } bounds
* @ param { vector } position
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Bounds . shift = function ( bounds , position ) {
var deltaX = bounds . max . x - bounds . min . x ,
deltaY = bounds . max . y - bounds . min . y ;
bounds . min . x = position . x ;
bounds . max . x = position . x + deltaX ;
bounds . min . y = position . y ;
bounds . max . y = position . y + deltaY ;
} ;
} ) ( ) ;
/***/ } ) ,
/* 2 */
/***/ ( function ( module , exports ) {
/ * *
* The ` Matter.Vector ` module contains methods for creating and manipulating vectors .
* Vectors are the basis of all the geometry related operations in the engine .
* A ` Matter.Vector ` object is of the form ` { x: 0, y: 0 } ` .
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Vector
* /
// TODO: consider params for reusing vector objects
var Vector = { } ;
module . exports = Vector ;
( function ( ) {
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Creates a new vector .
* @ method create
* @ param { number } x
* @ param { number } y
* @ return { vector } A new vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . create = function ( x , y ) {
return { x : x || 0 , y : y || 0 } ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns a new vector with ` x ` and ` y ` copied from the given ` vector ` .
* @ method clone
* @ param { vector } vector
* @ return { vector } A new cloned vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . clone = function ( vector ) {
return { x : vector . x , y : vector . y } ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the magnitude ( length ) of a vector .
* @ method magnitude
* @ param { vector } vector
* @ return { number } The magnitude of the vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . magnitude = function ( vector ) {
return Math . sqrt ( ( vector . x * vector . x ) + ( vector . y * vector . y ) ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the magnitude ( length ) of a vector ( therefore saving a ` sqrt ` operation ) .
* @ method magnitudeSquared
* @ param { vector } vector
* @ return { number } The squared magnitude of the vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . magnitudeSquared = function ( vector ) {
return ( vector . x * vector . x ) + ( vector . y * vector . y ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Rotates the vector about ( 0 , 0 ) by specified angle .
* @ method rotate
* @ param { vector } vector
* @ param { number } angle
* @ param { vector } [ output ]
* @ return { vector } The vector rotated about ( 0 , 0 )
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . rotate = function ( vector , angle , output ) {
var cos = Math . cos ( angle ) , sin = Math . sin ( angle ) ;
if ( ! output ) output = { } ;
var x = vector . x * cos - vector . y * sin ;
output . y = vector . x * sin + vector . y * cos ;
output . x = x ;
return output ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Rotates the vector about a specified point by specified angle .
* @ method rotateAbout
* @ param { vector } vector
* @ param { number } angle
* @ param { vector } point
* @ param { vector } [ output ]
* @ return { vector } A new vector rotated about the point
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . rotateAbout = function ( vector , angle , point , output ) {
var cos = Math . cos ( angle ) , sin = Math . sin ( angle ) ;
if ( ! output ) output = { } ;
var x = point . x + ( ( vector . x - point . x ) * cos - ( vector . y - point . y ) * sin ) ;
output . y = point . y + ( ( vector . x - point . x ) * sin + ( vector . y - point . y ) * cos ) ;
output . x = x ;
return output ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Normalises a vector ( such that its magnitude is ` 1 ` ) .
* @ method normalise
* @ param { vector } vector
* @ return { vector } A new vector normalised
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . normalise = function ( vector ) {
var magnitude = Vector . magnitude ( vector ) ;
if ( magnitude === 0 )
return { x : 0 , y : 0 } ;
return { x : vector . x / magnitude , y : vector . y / magnitude } ;
} ;
2014-06-09 14:40:24 -04:00
2016-04-07 15:03:37 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the dot - product of two vectors .
* @ method dot
* @ param { vector } vectorA
* @ param { vector } vectorB
* @ return { number } The dot product of the two vectors
2016-04-07 15:03:37 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . dot = function ( vectorA , vectorB ) {
return ( vectorA . x * vectorB . x ) + ( vectorA . y * vectorB . y ) ;
} ;
2016-04-07 15:03:37 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the cross - product of two vectors .
* @ method cross
* @ param { vector } vectorA
* @ param { vector } vectorB
* @ return { number } The cross product of the two vectors
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . cross = function ( vectorA , vectorB ) {
return ( vectorA . x * vectorB . y ) - ( vectorA . y * vectorB . x ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the cross - product of three vectors .
* @ method cross3
* @ param { vector } vectorA
* @ param { vector } vectorB
* @ param { vector } vectorC
* @ return { number } The cross product of the three vectors
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . cross3 = function ( vectorA , vectorB , vectorC ) {
return ( vectorB . x - vectorA . x ) * ( vectorC . y - vectorA . y ) - ( vectorB . y - vectorA . y ) * ( vectorC . x - vectorA . x ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Adds the two vectors .
* @ method add
* @ param { vector } vectorA
* @ param { vector } vectorB
* @ param { vector } [ output ]
* @ return { vector } A new vector of vectorA and vectorB added
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . add = function ( vectorA , vectorB , output ) {
if ( ! output ) output = { } ;
output . x = vectorA . x + vectorB . x ;
output . y = vectorA . y + vectorB . y ;
return output ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Subtracts the two vectors .
* @ method sub
* @ param { vector } vectorA
* @ param { vector } vectorB
* @ param { vector } [ output ]
* @ return { vector } A new vector of vectorA and vectorB subtracted
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . sub = function ( vectorA , vectorB , output ) {
if ( ! output ) output = { } ;
output . x = vectorA . x - vectorB . x ;
output . y = vectorA . y - vectorB . y ;
return output ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Multiplies a vector and a scalar .
* @ method mult
* @ param { vector } vector
* @ param { number } scalar
* @ return { vector } A new vector multiplied by scalar
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . mult = function ( vector , scalar ) {
return { x : vector . x * scalar , y : vector . y * scalar } ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Divides a vector and a scalar .
* @ method div
* @ param { vector } vector
* @ param { number } scalar
* @ return { vector } A new vector divided by scalar
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . div = function ( vector , scalar ) {
return { x : vector . x / scalar , y : vector . y / scalar } ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the perpendicular vector . Set ` negate ` to true for the perpendicular in the opposite direction .
* @ method perp
* @ param { vector } vector
* @ param { bool } [ negate = false ]
* @ return { vector } The perpendicular vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . perp = function ( vector , negate ) {
negate = negate === true ? - 1 : 1 ;
return { x : negate * - vector . y , y : negate * vector . x } ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Negates both components of a vector such that it points in the opposite direction .
* @ method neg
* @ param { vector } vector
* @ return { vector } The negated vector
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . neg = function ( vector ) {
return { x : - vector . x , y : - vector . y } ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the angle between the vector ` vectorB - vectorA ` and the x - axis in radians .
* @ method angle
* @ param { vector } vectorA
* @ param { vector } vectorB
* @ return { number } The angle in radians
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . angle = function ( vectorA , vectorB ) {
return Math . atan2 ( vectorB . y - vectorA . y , vectorB . x - vectorA . x ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Temporary vector pool ( not thread - safe ) .
* @ property _temp
* @ type { vector [ ] }
* @ private
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vector . _temp = [
Vector . create ( ) , Vector . create ( ) ,
Vector . create ( ) , Vector . create ( ) ,
Vector . create ( ) , Vector . create ( )
] ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 3 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
* The ` Matter.Vertices ` module contains methods for creating and manipulating sets of vertices .
* A set of vertices is an array of ` Matter.Vector ` with additional indexing properties inserted by ` Vertices.create ` .
* A ` Matter.Body ` maintains a set of vertices to represent the shape of the object ( its convex hull ) .
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Vertices
* /
var Vertices = { } ;
module . exports = Vertices ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
( function ( ) {
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Creates a new set of ` Matter.Body ` compatible vertices .
* The ` points ` argument accepts an array of ` Matter.Vector ` points orientated around the origin ` (0, 0) ` , for example :
2014-06-09 14:40:24 -04:00
*
2020-12-26 17:44:24 -05:00
* [ { x : 0 , y : 0 } , { x : 25 , y : 50 } , { x : 50 , y : 0 } ]
2014-07-29 11:26:49 -04:00
*
2020-12-26 17:44:24 -05:00
* The ` Vertices.create ` method returns a new array of vertices , which are similar to Matter . Vector objects ,
* but with some additional references required for efficient collision detection routines .
2014-07-29 11:26:49 -04:00
*
2020-12-26 17:44:24 -05:00
* Vertices must be specified in clockwise order .
2014-07-29 11:26:49 -04:00
*
2020-12-26 17:44:24 -05:00
* Note that the ` body ` argument is not optional , a ` Matter.Body ` reference must be provided .
2014-07-29 11:26:49 -04:00
*
2020-12-26 17:44:24 -05:00
* @ method create
* @ param { vector [ ] } points
* @ param { body } body
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . create = function ( points , body ) {
var vertices = [ ] ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < points . length ; i ++ ) {
var point = points [ i ] ,
vertex = {
x : point . x ,
y : point . y ,
index : i ,
body : body ,
isInternal : false
} ;
vertices . push ( vertex ) ;
}
return vertices ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Parses a string containing ordered x y pairs separated by spaces ( and optionally commas ) ,
* into a ` Matter.Vertices ` object for the given ` Matter.Body ` .
* For parsing SVG paths , see ` Svg.pathToVertices ` .
* @ method fromPath
* @ param { string } path
* @ param { body } body
* @ return { vertices } vertices
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . fromPath = function ( path , body ) {
var pathPattern = /L?\s*([-\d.e]+)[\s,]*([-\d.e]+)*/ig ,
points = [ ] ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
path . replace ( pathPattern , function ( match , x , y ) {
points . push ( { x : parseFloat ( x ) , y : parseFloat ( y ) } ) ;
} ) ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
return Vertices . create ( points , body ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the centre ( centroid ) of the set of vertices .
* @ method centre
* @ param { vertices } vertices
* @ return { vector } The centre point
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . centre = function ( vertices ) {
var area = Vertices . area ( vertices , true ) ,
centre = { x : 0 , y : 0 } ,
cross ,
temp ,
j ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < vertices . length ; i ++ ) {
j = ( i + 1 ) % vertices . length ;
cross = Vector . cross ( vertices [ i ] , vertices [ j ] ) ;
temp = Vector . mult ( Vector . add ( vertices [ i ] , vertices [ j ] ) , cross ) ;
centre = Vector . add ( centre , temp ) ;
}
return Vector . div ( centre , 6 * area ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the average ( mean ) of the set of vertices .
* @ method mean
* @ param { vertices } vertices
* @ return { vector } The average point
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . mean = function ( vertices ) {
var average = { x : 0 , y : 0 } ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < vertices . length ; i ++ ) {
average . x += vertices [ i ] . x ;
average . y += vertices [ i ] . y ;
}
2016-02-07 10:53:07 -05:00
2020-12-26 17:44:24 -05:00
return Vector . div ( average , vertices . length ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the area of the set of vertices .
* @ method area
* @ param { vertices } vertices
* @ param { bool } signed
* @ return { number } The area
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . area = function ( vertices , signed ) {
var area = 0 ,
j = vertices . length - 1 ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < vertices . length ; i ++ ) {
area += ( vertices [ j ] . x - vertices [ i ] . x ) * ( vertices [ j ] . y + vertices [ i ] . y ) ;
j = i ;
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( signed )
return area / 2 ;
2015-12-23 08:08:54 -05:00
2020-12-26 17:44:24 -05:00
return Math . abs ( area ) / 2 ;
} ;
2015-12-23 08:08:54 -05:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the moment of inertia ( second moment of area ) of the set of vertices given the total mass .
* @ method inertia
* @ param { vertices } vertices
* @ param { number } mass
* @ return { number } The polygon ' s moment of inertia
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . inertia = function ( vertices , mass ) {
var numerator = 0 ,
denominator = 0 ,
v = vertices ,
cross ,
j ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
// find the polygon's moment of inertia, using second moment of area
// from equations at http://www.physicsforums.com/showthread.php?t=25293
for ( var n = 0 ; n < v . length ; n ++ ) {
j = ( n + 1 ) % v . length ;
cross = Math . abs ( Vector . cross ( v [ j ] , v [ n ] ) ) ;
numerator += cross * ( Vector . dot ( v [ j ] , v [ j ] ) + Vector . dot ( v [ j ] , v [ n ] ) + Vector . dot ( v [ n ] , v [ n ] ) ) ;
denominator += cross ;
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
return ( mass / 6 ) * ( numerator / denominator ) ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Translates the set of vertices in - place .
* @ method translate
* @ param { vertices } vertices
* @ param { vector } vector
* @ param { number } scalar
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . translate = function ( vertices , vector , scalar ) {
var i ;
if ( scalar ) {
for ( i = 0 ; i < vertices . length ; i ++ ) {
vertices [ i ] . x += vector . x * scalar ;
vertices [ i ] . y += vector . y * scalar ;
}
} else {
for ( i = 0 ; i < vertices . length ; i ++ ) {
vertices [ i ] . x += vector . x ;
vertices [ i ] . y += vector . y ;
}
}
return vertices ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Rotates the set of vertices in - place .
* @ method rotate
* @ param { vertices } vertices
* @ param { number } angle
* @ param { vector } point
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . rotate = function ( vertices , angle , point ) {
if ( angle === 0 )
return ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
var cos = Math . cos ( angle ) ,
sin = Math . sin ( angle ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < vertices . length ; i ++ ) {
var vertice = vertices [ i ] ,
dx = vertice . x - point . x ,
dy = vertice . y - point . y ;
vertice . x = point . x + ( dx * cos - dy * sin ) ;
vertice . y = point . y + ( dx * sin + dy * cos ) ;
}
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
return vertices ;
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns ` true ` if the ` point ` is inside the set of ` vertices ` .
* @ method contains
* @ param { vertices } vertices
* @ param { vector } point
* @ return { boolean } True if the vertices contains point , otherwise false
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Vertices . contains = function ( vertices , point ) {
for ( var i = 0 ; i < vertices . length ; i ++ ) {
var vertice = vertices [ i ] ,
nextVertice = vertices [ ( i + 1 ) % vertices . length ] ;
if ( ( point . x - vertice . x ) * ( nextVertice . y - vertice . y ) + ( point . y - vertice . y ) * ( vertice . x - nextVertice . x ) > 0 ) {
return false ;
}
}
return true ;
2014-03-24 16:11:42 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Scales the vertices from a point ( default is centre ) in - place .
* @ method scale
* @ param { vertices } vertices
* @ param { number } scaleX
* @ param { number } scaleY
* @ param { vector } point
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . scale = function ( vertices , scaleX , scaleY , point ) {
if ( scaleX === 1 && scaleY === 1 )
return vertices ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
point = point || Vertices . centre ( vertices ) ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
var vertex ,
delta ;
for ( var i = 0 ; i < vertices . length ; i ++ ) {
vertex = vertices [ i ] ;
delta = Vector . sub ( vertex , point ) ;
vertices [ i ] . x = point . x + delta . x * scaleX ;
vertices [ i ] . y = point . y + delta . y * scaleY ;
2014-03-24 16:11:42 -04:00
}
2020-12-26 17:44:24 -05:00
return vertices ;
2014-02-19 09:15:05 -05:00
} ;
2014-03-30 14:45:30 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Chamfers a set of vertices by giving them rounded corners , returns a new set of vertices .
* The radius parameter is a single number or an array to specify the radius for each vertex .
* @ method chamfer
* @ param { vertices } vertices
* @ param { number [ ] } radius
* @ param { number } quality
* @ param { number } qualityMin
* @ param { number } qualityMax
2014-03-30 14:45:30 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . chamfer = function ( vertices , radius , quality , qualityMin , qualityMax ) {
if ( typeof radius === 'number' ) {
radius = [ radius ] ;
} else {
radius = radius || [ 8 ] ;
}
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
// quality defaults to -1, which is auto
quality = ( typeof quality !== 'undefined' ) ? quality : - 1 ;
qualityMin = qualityMin || 2 ;
qualityMax = qualityMax || 14 ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
var newVertices = [ ] ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < vertices . length ; i ++ ) {
var prevVertex = vertices [ i - 1 >= 0 ? i - 1 : vertices . length - 1 ] ,
vertex = vertices [ i ] ,
nextVertex = vertices [ ( i + 1 ) % vertices . length ] ,
currentRadius = radius [ i < radius . length ? i : radius . length - 1 ] ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
if ( currentRadius === 0 ) {
newVertices . push ( vertex ) ;
continue ;
2014-03-30 14:45:30 -04:00
}
2020-12-26 17:44:24 -05:00
var prevNormal = Vector . normalise ( {
x : vertex . y - prevVertex . y ,
y : prevVertex . x - vertex . x
} ) ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
var nextNormal = Vector . normalise ( {
x : nextVertex . y - vertex . y ,
y : vertex . x - nextVertex . x
} ) ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
var diagonalRadius = Math . sqrt ( 2 * Math . pow ( currentRadius , 2 ) ) ,
radiusVector = Vector . mult ( Common . clone ( prevNormal ) , currentRadius ) ,
midNormal = Vector . normalise ( Vector . mult ( Vector . add ( prevNormal , nextNormal ) , 0.5 ) ) ,
scaledVertex = Vector . sub ( vertex , Vector . mult ( midNormal , diagonalRadius ) ) ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
var precision = quality ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
if ( quality === - 1 ) {
// automatically decide precision
precision = Math . pow ( currentRadius , 0.32 ) * 1.75 ;
}
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
precision = Common . clamp ( precision , qualityMin , qualityMax ) ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
// use an even value for precision, more likely to reduce axes by using symmetry
if ( precision % 2 === 1 )
precision += 1 ;
var alpha = Math . acos ( Vector . dot ( prevNormal , nextNormal ) ) ,
theta = alpha / precision ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
for ( var j = 0 ; j < precision ; j ++ ) {
newVertices . push ( Vector . add ( Vector . rotate ( radiusVector , theta * j ) , scaledVertex ) ) ;
2014-03-30 14:45:30 -04:00
}
}
2020-12-26 17:44:24 -05:00
return newVertices ;
2014-03-30 14:45:30 -04:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Sorts the input vertices into clockwise order in place .
* @ method clockwiseSort
* @ param { vertices } vertices
* @ return { vertices } vertices
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Vertices . clockwiseSort = function ( vertices ) {
var centre = Vertices . mean ( vertices ) ;
vertices . sort ( function ( vertexA , vertexB ) {
return Vector . angle ( centre , vertexA ) - Vector . angle ( centre , vertexB ) ;
} ) ;
return vertices ;
2014-02-19 09:15:05 -05:00
} ;
2014-03-30 14:45:30 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns true if the vertices form a convex shape ( vertices must be in clockwise order ) .
* @ method isConvex
* @ param { vertices } vertices
* @ return { bool } ` true ` if the ` vertices ` are convex , ` false ` if not ( or ` null ` if not computable ) .
2014-03-30 14:45:30 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . isConvex = function ( vertices ) {
// http://paulbourke.net/geometry/polygonmesh/
// Copyright (c) Paul Bourke (use permitted)
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
var flag = 0 ,
n = vertices . length ,
i ,
j ,
k ,
z ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
if ( n < 3 )
return null ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
for ( i = 0 ; i < n ; i ++ ) {
j = ( i + 1 ) % n ;
k = ( i + 2 ) % n ;
z = ( vertices [ j ] . x - vertices [ i ] . x ) * ( vertices [ k ] . y - vertices [ j ] . y ) ;
z -= ( vertices [ j ] . y - vertices [ i ] . y ) * ( vertices [ k ] . x - vertices [ j ] . x ) ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
if ( z < 0 ) {
flag |= 1 ;
} else if ( z > 0 ) {
flag |= 2 ;
}
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
if ( flag === 3 ) {
return false ;
2014-03-24 16:11:42 -04:00
}
}
2020-12-26 17:44:24 -05:00
if ( flag !== 0 ) {
return true ;
} else {
return null ;
}
2014-03-24 16:11:42 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Returns the convex hull of the input vertices as a new array of points .
* @ method hull
* @ param { vertices } vertices
* @ return [ vertex ] vertices
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Vertices . hull = function ( vertices ) {
// http://geomalgorithms.com/a10-_hull-1.html
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var upper = [ ] ,
lower = [ ] ,
vertex ,
i ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// sort vertices on x-axis (y-axis for ties)
vertices = vertices . slice ( 0 ) ;
vertices . sort ( function ( vertexA , vertexB ) {
var dx = vertexA . x - vertexB . x ;
return dx !== 0 ? dx : vertexA . y - vertexB . y ;
} ) ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
// build lower hull
for ( i = 0 ; i < vertices . length ; i += 1 ) {
vertex = vertices [ i ] ;
while ( lower . length >= 2
&& Vector . cross3 ( lower [ lower . length - 2 ] , lower [ lower . length - 1 ] , vertex ) <= 0 ) {
lower . pop ( ) ;
2014-03-24 16:11:42 -04:00
}
2020-12-26 17:44:24 -05:00
lower . push ( vertex ) ;
}
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
// build upper hull
for ( i = vertices . length - 1 ; i >= 0 ; i -= 1 ) {
vertex = vertices [ i ] ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
while ( upper . length >= 2
&& Vector . cross3 ( upper [ upper . length - 2 ] , upper [ upper . length - 1 ] , vertex ) <= 0 ) {
upper . pop ( ) ;
2014-03-24 16:11:42 -04:00
}
2020-12-26 17:44:24 -05:00
upper . push ( vertex ) ;
2014-03-24 16:11:42 -04:00
}
2020-12-26 17:44:24 -05:00
// concatenation of the lower and upper hulls gives the convex hull
// omit last points because they are repeated at the beginning of the other list
upper . pop ( ) ;
lower . pop ( ) ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
return upper . concat ( lower ) ;
2014-03-24 16:11:42 -04:00
} ;
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 4 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* The ` Matter.Events ` module contains methods to fire and listen to events on other objects .
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Events
* /
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
var Events = { } ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
module . exports = Events ;
var Common = _ _webpack _require _ _ ( 0 ) ;
( function ( ) {
2014-03-24 16:11:42 -04:00
2014-03-30 14:45:30 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Subscribes a callback function to the given object ' s ` eventName ` .
* @ method on
* @ param { } object
* @ param { string } eventNames
* @ param { function } callback
2014-03-30 14:45:30 -04:00
* /
2020-12-26 17:44:24 -05:00
Events . on = function ( object , eventNames , callback ) {
var names = eventNames . split ( ' ' ) ,
name ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < names . length ; i ++ ) {
name = names [ i ] ;
object . events = object . events || { } ;
object . events [ name ] = object . events [ name ] || [ ] ;
object . events [ name ] . push ( callback ) ;
}
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
return callback ;
2014-03-30 14:45:30 -04:00
} ;
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes the given event callback . If no callback , clears all callbacks in ` eventNames ` . If no ` eventNames ` , clears all events .
* @ method off
* @ param { } object
* @ param { string } eventNames
* @ param { function } callback
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Events . off = function ( object , eventNames , callback ) {
if ( ! eventNames ) {
object . events = { } ;
return ;
2014-05-01 09:09:06 -04:00
}
2020-12-26 17:44:24 -05:00
// handle Events.off(object, callback)
if ( typeof eventNames === 'function' ) {
callback = eventNames ;
eventNames = Common . keys ( object . events ) . join ( ' ' ) ;
}
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
var names = eventNames . split ( ' ' ) ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < names . length ; i ++ ) {
var callbacks = object . events [ names [ i ] ] ,
newCallbacks = [ ] ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
if ( callback && callbacks ) {
for ( var j = 0 ; j < callbacks . length ; j ++ ) {
if ( callbacks [ j ] !== callback )
newCallbacks . push ( callbacks [ j ] ) ;
}
}
object . events [ names [ i ] ] = newCallbacks ;
}
2014-05-01 09:09:06 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Fires all the callbacks subscribed to the given object ' s ` eventName ` , in the order they subscribed , if any .
* @ method trigger
* @ param { } object
* @ param { string } eventNames
* @ param { } event
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Events . trigger = function ( object , eventNames , event ) {
var names ,
name ,
callbacks ,
eventClone ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
var events = object . events ;
if ( events && Common . keys ( events ) . length > 0 ) {
if ( ! event )
event = { } ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
names = eventNames . split ( ' ' ) ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < names . length ; i ++ ) {
name = names [ i ] ;
callbacks = events [ name ] ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( callbacks ) {
eventClone = Common . clone ( event , false ) ;
eventClone . name = name ;
eventClone . source = object ;
2014-07-30 12:29:21 -04:00
2020-12-26 17:44:24 -05:00
for ( var j = 0 ; j < callbacks . length ; j ++ ) {
callbacks [ j ] . apply ( object , [ eventClone ] ) ;
}
}
}
2014-07-30 12:29:21 -04:00
}
2020-12-26 17:44:24 -05:00
} ;
2014-07-30 12:29:21 -04:00
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-07-30 12:29:21 -04:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 5 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
2021-04-11 12:49:36 -04:00
* A composite is a collection of ` Matter.Body ` , ` Matter.Constraint ` and other ` Matter.Composite ` objects .
*
* They are a container that can represent complex objects made of multiple parts , even if they are not physically connected .
* A composite could contain anything from a single body all the way up to a whole world .
*
* When making any changes to composites , use the included functions rather than changing their properties directly .
2020-12-26 17:44:24 -05:00
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Composite
* /
var Composite = { } ;
module . exports = Composite ;
var Events = _ _webpack _require _ _ ( 4 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
var Body = _ _webpack _require _ _ ( 6 ) ;
( function ( ) {
/ * *
* Creates a new composite . The options parameter is an object that specifies any properties you wish to override the defaults .
* See the properites section below for detailed information on what you can pass via the ` options ` object .
* @ method create
* @ param { } [ options ]
* @ return { composite } A new composite
* /
Composite . create = function ( options ) {
return Common . extend ( {
id : Common . nextId ( ) ,
type : 'composite' ,
parent : null ,
isModified : false ,
bodies : [ ] ,
constraints : [ ] ,
composites : [ ] ,
label : 'Composite' ,
plugin : { }
} , options ) ;
2014-07-30 12:29:21 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Sets the composite ' s ` isModified ` flag .
* If ` updateParents ` is true , all parents will be set ( default : false ) .
* If ` updateChildren ` is true , all children will be set ( default : false ) .
* @ method setModified
2014-07-30 12:29:21 -04:00
* @ param { composite } composite
2020-12-26 17:44:24 -05:00
* @ param { boolean } isModified
* @ param { boolean } [ updateParents = false ]
* @ param { boolean } [ updateChildren = false ]
2014-07-30 12:29:21 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . setModified = function ( composite , isModified , updateParents , updateChildren ) {
composite . isModified = isModified ;
2014-07-30 12:29:21 -04:00
2020-12-26 17:44:24 -05:00
if ( updateParents && composite . parent ) {
Composite . setModified ( composite . parent , isModified , updateParents , updateChildren ) ;
2014-07-30 12:29:21 -04:00
}
2020-12-26 17:44:24 -05:00
if ( updateChildren ) {
for ( var i = 0 ; i < composite . composites . length ; i ++ ) {
var childComposite = composite . composites [ i ] ;
Composite . setModified ( childComposite , isModified , updateParents , updateChildren ) ;
}
}
2014-07-30 12:29:21 -04:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Generic single or multi - add function . Adds a single or an array of body ( s ) , constraint ( s ) or composite ( s ) to the given composite .
2020-12-26 17:44:24 -05:00
* Triggers ` beforeAdd ` and ` afterAdd ` events on the ` composite ` .
* @ method add
2014-07-30 12:29:21 -04:00
* @ param { composite } composite
2021-04-11 12:49:36 -04:00
* @ param { object | array } object A single or an array of body ( s ) , constraint ( s ) or composite ( s )
2020-12-26 17:44:24 -05:00
* @ return { composite } The original composite with the objects added
2014-07-30 12:29:21 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . add = function ( composite , object ) {
var objects = [ ] . concat ( object ) ;
2014-07-30 12:29:21 -04:00
2020-12-26 17:44:24 -05:00
Events . trigger ( composite , 'beforeAdd' , { object : object } ) ;
2014-07-30 12:29:21 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < objects . length ; i ++ ) {
var obj = objects [ i ] ;
switch ( obj . type ) {
case 'body' :
// skip adding compound parts
if ( obj . parent !== obj ) {
Common . warn ( 'Composite.add: skipped adding a compound body part (you must add its parent instead)' ) ;
break ;
}
Composite . addBody ( composite , obj ) ;
break ;
case 'constraint' :
Composite . addConstraint ( composite , obj ) ;
break ;
case 'composite' :
Composite . addComposite ( composite , obj ) ;
break ;
case 'mouseConstraint' :
Composite . addConstraint ( composite , obj . constraint ) ;
break ;
}
2014-07-30 12:29:21 -04:00
}
2020-12-26 17:44:24 -05:00
Events . trigger ( composite , 'afterAdd' , { object : object } ) ;
2014-07-30 12:29:21 -04:00
return composite ;
} ;
2017-07-06 18:47:04 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Generic remove function . Removes one or many body ( s ) , constraint ( s ) or a composite ( s ) to the given composite .
* Optionally searching its children recursively .
* Triggers ` beforeRemove ` and ` afterRemove ` events on the ` composite ` .
* @ method remove
* @ param { composite } composite
2021-04-11 12:49:36 -04:00
* @ param { object | array } object
2020-12-26 17:44:24 -05:00
* @ param { boolean } [ deep = false ]
* @ return { composite } The original composite with the objects removed
2017-07-06 18:47:04 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . remove = function ( composite , object , deep ) {
var objects = [ ] . concat ( object ) ;
2017-07-06 18:47:04 -04:00
2020-12-26 17:44:24 -05:00
Events . trigger ( composite , 'beforeRemove' , { object : object } ) ;
2017-07-06 18:47:04 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < objects . length ; i ++ ) {
var obj = objects [ i ] ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
switch ( obj . type ) {
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
case 'body' :
Composite . removeBody ( composite , obj , deep ) ;
break ;
case 'constraint' :
Composite . removeConstraint ( composite , obj , deep ) ;
break ;
case 'composite' :
Composite . removeComposite ( composite , obj , deep ) ;
break ;
case 'mouseConstraint' :
Composite . removeConstraint ( composite , obj . constraint ) ;
break ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
}
}
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
Events . trigger ( composite , 'afterRemove' , { object : object } ) ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
return composite ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Adds a composite to the given composite .
* @ private
* @ method addComposite
* @ param { composite } compositeA
* @ param { composite } compositeB
* @ return { composite } The original compositeA with the objects from compositeB added
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . addComposite = function ( compositeA , compositeB ) {
compositeA . composites . push ( compositeB ) ;
compositeB . parent = compositeA ;
Composite . setModified ( compositeA , true , true , false ) ;
return compositeA ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes a composite from the given composite , and optionally searching its children recursively .
* @ private
* @ method removeComposite
* @ param { composite } compositeA
* @ param { composite } compositeB
* @ param { boolean } [ deep = false ]
* @ return { composite } The original compositeA with the composite removed
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . removeComposite = function ( compositeA , compositeB , deep ) {
var position = Common . indexOf ( compositeA . composites , compositeB ) ;
if ( position !== - 1 ) {
Composite . removeCompositeAt ( compositeA , position ) ;
Composite . setModified ( compositeA , true , true , false ) ;
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( deep ) {
for ( var i = 0 ; i < compositeA . composites . length ; i ++ ) {
Composite . removeComposite ( compositeA . composites [ i ] , compositeB , true ) ;
}
}
return compositeA ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes a composite from the given composite .
* @ private
* @ method removeCompositeAt
* @ param { composite } composite
* @ param { number } position
* @ return { composite } The original composite with the composite removed
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . removeCompositeAt = function ( composite , position ) {
composite . composites . splice ( position , 1 ) ;
Composite . setModified ( composite , true , true , false ) ;
return composite ;
} ;
2014-05-01 09:09:06 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Adds a body to the given composite .
* @ private
* @ method addBody
* @ param { composite } composite
* @ param { body } body
* @ return { composite } The original composite with the body added
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . addBody = function ( composite , body ) {
composite . bodies . push ( body ) ;
Composite . setModified ( composite , true , true , false ) ;
return composite ;
} ;
2014-05-01 09:09:06 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes a body from the given composite , and optionally searching its children recursively .
* @ private
* @ method removeBody
* @ param { composite } composite
* @ param { body } body
* @ param { boolean } [ deep = false ]
* @ return { composite } The original composite with the body removed
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . removeBody = function ( composite , body , deep ) {
var position = Common . indexOf ( composite . bodies , body ) ;
if ( position !== - 1 ) {
Composite . removeBodyAt ( composite , position ) ;
Composite . setModified ( composite , true , true , false ) ;
}
if ( deep ) {
for ( var i = 0 ; i < composite . composites . length ; i ++ ) {
Composite . removeBody ( composite . composites [ i ] , body , true ) ;
}
}
return composite ;
} ;
2014-05-01 09:09:06 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes a body from the given composite .
* @ private
* @ method removeBodyAt
* @ param { composite } composite
* @ param { number } position
* @ return { composite } The original composite with the body removed
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . removeBodyAt = function ( composite , position ) {
composite . bodies . splice ( position , 1 ) ;
Composite . setModified ( composite , true , true , false ) ;
return composite ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Adds a constraint to the given composite .
* @ private
* @ method addConstraint
* @ param { composite } composite
* @ param { constraint } constraint
* @ return { composite } The original composite with the constraint added
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . addConstraint = function ( composite , constraint ) {
composite . constraints . push ( constraint ) ;
Composite . setModified ( composite , true , true , false ) ;
return composite ;
} ;
2014-05-01 09:09:06 -04:00
2017-01-26 18:49:29 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes a constraint from the given composite , and optionally searching its children recursively .
* @ private
* @ method removeConstraint
* @ param { composite } composite
* @ param { constraint } constraint
* @ param { boolean } [ deep = false ]
* @ return { composite } The original composite with the constraint removed
2017-01-26 18:49:29 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . removeConstraint = function ( composite , constraint , deep ) {
var position = Common . indexOf ( composite . constraints , constraint ) ;
if ( position !== - 1 ) {
Composite . removeConstraintAt ( composite , position ) ;
}
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
if ( deep ) {
for ( var i = 0 ; i < composite . composites . length ; i ++ ) {
Composite . removeConstraint ( composite . composites [ i ] , constraint , true ) ;
}
}
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
return composite ;
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Removes a body from the given composite .
* @ private
* @ method removeConstraintAt
* @ param { composite } composite
* @ param { number } position
* @ return { composite } The original composite with the constraint removed
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . removeConstraintAt = function ( composite , position ) {
composite . constraints . splice ( position , 1 ) ;
Composite . setModified ( composite , true , true , false ) ;
return composite ;
} ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Removes all bodies , constraints and composites from the given composite .
* Optionally clearing its children recursively .
* @ method clear
* @ param { composite } composite
* @ param { boolean } keepStatic
* @ param { boolean } [ deep = false ]
* /
Composite . clear = function ( composite , keepStatic , deep ) {
if ( deep ) {
for ( var i = 0 ; i < composite . composites . length ; i ++ ) {
Composite . clear ( composite . composites [ i ] , keepStatic , true ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( keepStatic ) {
composite . bodies = composite . bodies . filter ( function ( body ) { return body . isStatic ; } ) ;
} else {
composite . bodies . length = 0 ;
}
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
composite . constraints . length = 0 ;
composite . composites . length = 0 ;
Composite . setModified ( composite , true , true , false ) ;
2016-01-16 17:43:32 -05:00
2020-12-26 17:44:24 -05:00
return composite ;
} ;
2016-01-16 17:43:32 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns all bodies in the given composite , including all bodies in its children , recursively .
* @ method allBodies
* @ param { composite } composite
* @ return { body [ ] } All the bodies
2016-01-16 17:43:32 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . allBodies = function ( composite ) {
var bodies = [ ] . concat ( composite . bodies ) ;
2016-01-16 17:43:32 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < composite . composites . length ; i ++ )
bodies = bodies . concat ( Composite . allBodies ( composite . composites [ i ] ) ) ;
2016-01-16 17:43:32 -05:00
2020-12-26 17:44:24 -05:00
return bodies ;
} ;
2016-01-16 17:43:32 -05:00
2016-04-07 15:03:37 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns all constraints in the given composite , including all constraints in its children , recursively .
* @ method allConstraints
* @ param { composite } composite
* @ return { constraint [ ] } All the constraints
2016-04-07 15:03:37 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . allConstraints = function ( composite ) {
var constraints = [ ] . concat ( composite . constraints ) ;
2016-04-07 15:03:37 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < composite . composites . length ; i ++ )
constraints = constraints . concat ( Composite . allConstraints ( composite . composites [ i ] ) ) ;
2017-11-29 19:16:03 -05:00
2020-12-26 17:44:24 -05:00
return constraints ;
} ;
2017-11-29 19:16:03 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns all composites in the given composite , including all composites in its children , recursively .
* @ method allComposites
* @ param { composite } composite
* @ return { composite [ ] } All the composites
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . allComposites = function ( composite ) {
var composites = [ ] . concat ( composite . composites ) ;
for ( var i = 0 ; i < composite . composites . length ; i ++ )
composites = composites . concat ( Composite . allComposites ( composite . composites [ i ] ) ) ;
return composites ;
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Searches the composite recursively for an object matching the type and id supplied , null if not found .
* @ method get
2014-02-28 20:10:08 -05:00
* @ param { composite } composite
2020-12-26 17:44:24 -05:00
* @ param { number } id
* @ param { string } type
* @ return { object } The requested object , if found
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . get = function ( composite , id , type ) {
var objects ,
object ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
switch ( type ) {
case 'body' :
objects = Composite . allBodies ( composite ) ;
break ;
case 'constraint' :
objects = Composite . allConstraints ( composite ) ;
break ;
case 'composite' :
objects = Composite . allComposites ( composite ) . concat ( composite ) ;
break ;
}
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
if ( ! objects )
return null ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
object = objects . filter ( function ( object ) {
return object . id . toString ( ) === id . toString ( ) ;
} ) ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
return object . length === 0 ? null : object [ 0 ] ;
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Moves the given object ( s ) from compositeA to compositeB ( equal to a remove followed by an add ) .
* @ method move
* @ param { compositeA } compositeA
* @ param { object [ ] } objects
* @ param { compositeB } compositeB
* @ return { composite } Returns compositeA
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . move = function ( compositeA , objects , compositeB ) {
Composite . remove ( compositeA , objects ) ;
Composite . add ( compositeB , objects ) ;
return compositeA ;
2014-02-19 09:15:05 -05:00
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Assigns new ids for all objects in the composite , recursively .
* @ method rebase
* @ param { composite } composite
* @ return { composite } Returns composite
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . rebase = function ( composite ) {
var objects = Composite . allBodies ( composite )
. concat ( Composite . allConstraints ( composite ) )
. concat ( Composite . allComposites ( composite ) ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < objects . length ; i ++ ) {
objects [ i ] . id = Common . nextId ( ) ;
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
Composite . setModified ( composite , true , true , false ) ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
return composite ;
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Translates all children in the composite by a given vector relative to their current positions ,
* without imparting any velocity .
* @ method translate
* @ param { composite } composite
* @ param { vector } translation
* @ param { bool } [ recursive = true ]
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Composite . translate = function ( composite , translation , recursive ) {
var bodies = recursive ? Composite . allBodies ( composite ) : composite . bodies ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
Body . translate ( bodies [ i ] , translation ) ;
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
Composite . setModified ( composite , true , true , false ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
return composite ;
} ;
2015-12-05 11:47:50 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* Rotates all children in the composite by a given angle about the given point , without imparting any angular velocity .
* @ method rotate
* @ param { composite } composite
* @ param { number } rotation
* @ param { vector } point
* @ param { bool } [ recursive = true ]
* /
Composite . rotate = function ( composite , rotation , point , recursive ) {
var cos = Math . cos ( rotation ) ,
sin = Math . sin ( rotation ) ,
bodies = recursive ? Composite . allBodies ( composite ) : composite . bodies ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ,
dx = body . position . x - point . x ,
dy = body . position . y - point . y ;
Body . setPosition ( body , {
x : point . x + ( dx * cos - dy * sin ) ,
y : point . y + ( dx * sin + dy * cos )
} ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
Body . rotate ( body , rotation ) ;
}
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
Composite . setModified ( composite , true , true , false ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
return composite ;
} ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Scales all children in the composite , including updating physical properties ( mass , area , axes , inertia ) , from a world - space point .
* @ method scale
* @ param { composite } composite
* @ param { number } scaleX
* @ param { number } scaleY
* @ param { vector } point
* @ param { bool } [ recursive = true ]
* /
Composite . scale = function ( composite , scaleX , scaleY , point , recursive ) {
var bodies = recursive ? Composite . allBodies ( composite ) : composite . bodies ;
2015-12-05 11:47:50 -05:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ,
dx = body . position . x - point . x ,
dy = body . position . y - point . y ;
Body . setPosition ( body , {
x : point . x + dx * scaleX ,
y : point . y + dy * scaleY
} ) ;
Body . scale ( body , scaleX , scaleY ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
Composite . setModified ( composite , true , true , false ) ;
return composite ;
2014-02-19 09:15:05 -05:00
} ;
2014-07-29 11:26:49 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the union of the bounds of all of the composite ' s bodies .
* @ method bounds
* @ param { composite } composite The composite .
* @ returns { bounds } The composite bounds .
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Composite . bounds = function ( composite ) {
var bodies = Composite . allBodies ( composite ) ,
vertices = [ ] ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < bodies . length ; i += 1 ) {
var body = bodies [ i ] ;
vertices . push ( body . bounds . min , body . bounds . max ) ;
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
return Bounds . create ( vertices ) ;
} ;
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
/ *
*
* Events Documentation
*
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* Fired when a call to ` Composite.add ` is made , before objects have been added .
*
* @ event beforeAdd
* @ param { } event An event object
* @ param { } event . object The object ( s ) to be added ( may be a single body , constraint , composite or a mixed array of these )
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Fired when a call to ` Composite.add ` is made , after objects have been added .
*
* @ event afterAdd
* @ param { } event An event object
* @ param { } event . object The object ( s ) that have been added ( may be a single body , constraint , composite or a mixed array of these )
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Fired when a call to ` Composite.remove ` is made , before objects have been removed .
*
* @ event beforeRemove
* @ param { } event An event object
* @ param { } event . object The object ( s ) to be removed ( may be a single body , constraint , composite or a mixed array of these )
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Fired when a call to ` Composite.remove ` is made , after objects have been removed .
*
* @ event afterRemove
* @ param { } event An event object
* @ param { } event . object The object ( s ) that have been removed ( may be a single body , constraint , composite or a mixed array of these )
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
/ *
*
* Properties Documentation
*
* /
2014-02-19 09:15:05 -05:00
2016-04-07 15:03:37 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* An integer ` Number ` uniquely identifying number generated in ` Composite.create ` by ` Common.nextId ` .
2016-04-07 15:03:37 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property id
2016-04-07 15:03:37 -04:00
* @ type number
* /
/ * *
2020-12-26 17:44:24 -05:00
* A ` String ` denoting the type of object .
2016-04-07 15:03:37 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property type
* @ type string
* @ default "composite"
* @ readOnly
2016-04-07 15:03:37 -04:00
* /
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* An arbitrary ` String ` name to help the user identify and manage composites .
*
* @ property label
* @ type string
* @ default "Composite"
2014-02-28 20:10:08 -05:00
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A flag that specifies whether the composite has been modified during the current step .
* Most ` Matter.Composite ` methods will automatically set this flag to ` true ` to inform the engine of changes to be handled .
* If you need to change it manually , you should use the ` Composite.setModified ` method .
*
* @ property isModified
* @ type boolean
* @ default false
* /
2015-12-05 11:47:50 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* The ` Composite ` that is the parent of this composite . It is automatically managed by the ` Matter.Composite ` methods .
*
* @ property parent
* @ type composite
* @ default null
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An array of ` Body ` that are _direct _ children of this composite .
* To add or remove bodies you should use ` Composite.add ` and ` Composite.remove ` methods rather than directly modifying this property .
* If you wish to recursively find all descendants , you should use the ` Composite.allBodies ` method .
*
* @ property bodies
* @ type body [ ]
* @ default [ ]
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An array of ` Constraint ` that are _direct _ children of this composite .
* To add or remove constraints you should use ` Composite.add ` and ` Composite.remove ` methods rather than directly modifying this property .
* If you wish to recursively find all descendants , you should use the ` Composite.allConstraints ` method .
*
* @ property constraints
* @ type constraint [ ]
* @ default [ ]
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An array of ` Composite ` that are _direct _ children of this composite .
* To add or remove composites you should use ` Composite.add ` and ` Composite.remove ` methods rather than directly modifying this property .
* If you wish to recursively find all descendants , you should use the ` Composite.allComposites ` method .
*
* @ property composites
* @ type composite [ ]
* @ default [ ]
* /
2015-12-05 11:47:50 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An object reserved for storing plugin - specific properties .
*
* @ property plugin
* @ type { }
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 6 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* The ` Matter.Body ` module contains methods for creating and manipulating body models .
* A ` Matter.Body ` is a rigid body that can be simulated by a ` Matter.Engine ` .
* Factories for commonly used body configurations ( such as rectangles , circles and other polygons ) can be found in the module ` Matter.Bodies ` .
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
* @ class Body
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var Body = { } ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
module . exports = Body ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var Vertices = _ _webpack _require _ _ ( 3 ) ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
var Sleeping = _ _webpack _require _ _ ( 7 ) ;
2021-04-11 12:49:36 -04:00
var Render = _ _webpack _require _ _ ( 16 ) ;
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
2021-04-11 12:49:36 -04:00
var Axes = _ _webpack _require _ _ ( 10 ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
( function ( ) {
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
Body . _inertiaScale = 4 ;
Body . _nextCollidingGroupId = 1 ;
Body . _nextNonCollidingGroupId = - 1 ;
Body . _nextCategory = 0x0001 ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Creates a new rigid body model . The options parameter is an object that specifies any properties you wish to override the defaults .
* All properties have default values , and many are pre - calculated automatically based on other properties .
* Vertices must be specified in clockwise order .
* See the properties section below for detailed information on what you can pass via the ` options ` object .
* @ method create
* @ param { } options
* @ return { body } body
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . create = function ( options ) {
var defaults = {
id : Common . nextId ( ) ,
type : 'body' ,
label : 'Body' ,
parts : [ ] ,
plugin : { } ,
angle : 0 ,
vertices : Vertices . fromPath ( 'L 0 0 L 40 0 L 40 40 L 0 40' ) ,
position : { x : 0 , y : 0 } ,
force : { x : 0 , y : 0 } ,
torque : 0 ,
positionImpulse : { x : 0 , y : 0 } ,
constraintImpulse : { x : 0 , y : 0 , angle : 0 } ,
totalContacts : 0 ,
speed : 0 ,
angularSpeed : 0 ,
velocity : { x : 0 , y : 0 } ,
angularVelocity : 0 ,
isSensor : false ,
isStatic : false ,
isSleeping : false ,
motion : 0 ,
sleepThreshold : 60 ,
density : 0.001 ,
restitution : 0 ,
friction : 0.1 ,
frictionStatic : 0.5 ,
frictionAir : 0.01 ,
collisionFilter : {
category : 0x0001 ,
mask : 0xFFFFFFFF ,
group : 0
} ,
slop : 0.05 ,
timeScale : 1 ,
render : {
visible : true ,
opacity : 1 ,
strokeStyle : null ,
fillStyle : null ,
lineWidth : null ,
sprite : {
xScale : 1 ,
yScale : 1 ,
xOffset : 0 ,
yOffset : 0
}
} ,
events : null ,
bounds : null ,
chamfer : null ,
circleRadius : 0 ,
positionPrev : null ,
anglePrev : 0 ,
parent : null ,
axes : null ,
area : 0 ,
mass : 0 ,
inertia : 0 ,
_original : null
} ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var body = Common . extend ( defaults , options ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
_initProperties ( body , options ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
return body ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the next unique group index for which bodies will collide .
* If ` isNonColliding ` is ` true ` , returns the next unique group index for which bodies will _not _ collide .
* See ` body.collisionFilter ` for more information .
* @ method nextGroup
* @ param { bool } [ isNonColliding = false ]
* @ return { Number } Unique group index
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . nextGroup = function ( isNonColliding ) {
if ( isNonColliding )
return Body . _nextNonCollidingGroupId -- ;
return Body . _nextCollidingGroupId ++ ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the next unique category bitfield ( starting after the initial default category ` 0x0001 ` ) .
* There are 32 available . See ` body.collisionFilter ` for more information .
* @ method nextCategory
* @ return { Number } Unique category bitfield
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . nextCategory = function ( ) {
Body . _nextCategory = Body . _nextCategory << 1 ;
return Body . _nextCategory ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Initialises body properties .
* @ method _initProperties
2014-02-28 20:10:08 -05:00
* @ private
2020-12-26 17:44:24 -05:00
* @ param { body } body
* @ param { } [ options ]
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
var _initProperties = function ( body , options ) {
options = options || { } ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// init required properties (order is important)
Body . set ( body , {
bounds : body . bounds || Bounds . create ( body . vertices ) ,
positionPrev : body . positionPrev || Vector . clone ( body . position ) ,
anglePrev : body . anglePrev || body . angle ,
vertices : body . vertices ,
parts : body . parts || [ body ] ,
isStatic : body . isStatic ,
isSleeping : body . isSleeping ,
parent : body . parent || body
} ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
Vertices . rotate ( body . vertices , body . angle , body . position ) ;
Axes . rotate ( body . axes , body . angle ) ;
Bounds . update ( body . bounds , body . vertices , body . velocity ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
// allow options to override the automatically calculated properties
Body . set ( body , {
axes : options . axes || body . axes ,
area : options . area || body . area ,
mass : options . mass || body . mass ,
inertia : options . inertia || body . inertia
} ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// render properties
var defaultFillStyle = ( body . isStatic ? '#14151f' : Common . choose ( [ '#f19648' , '#f5d259' , '#f55a3c' , '#063e7b' , '#ececd1' ] ) ) ,
defaultStrokeStyle = body . isStatic ? '#555' : '#ccc' ,
defaultLineWidth = body . isStatic && body . render . fillStyle === null ? 1 : 0 ;
body . render . fillStyle = body . render . fillStyle || defaultFillStyle ;
body . render . strokeStyle = body . render . strokeStyle || defaultStrokeStyle ;
body . render . lineWidth = body . render . lineWidth || defaultLineWidth ;
body . render . sprite . xOffset += - ( body . bounds . min . x - body . position . x ) / ( body . bounds . max . x - body . bounds . min . x ) ;
body . render . sprite . yOffset += - ( body . bounds . min . y - body . position . y ) / ( body . bounds . max . y - body . bounds . min . y ) ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Given a property and a value ( or map of ) , sets the property ( s ) on the body , using the appropriate setter functions if they exist .
* Prefer to use the actual setter functions in performance critical situations .
* @ method set
* @ param { body } body
* @ param { } settings A property name ( or map of properties and values ) to set on the body .
* @ param { } value The value to set if ` settings ` is a single property name .
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . set = function ( body , settings , value ) {
var property ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( typeof settings === 'string' ) {
property = settings ;
settings = { } ;
settings [ property ] = value ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
for ( property in settings ) {
if ( ! Object . prototype . hasOwnProperty . call ( settings , property ) )
continue ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
value = settings [ property ] ;
switch ( property ) {
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
case 'isStatic' :
Body . setStatic ( body , value ) ;
break ;
case 'isSleeping' :
Sleeping . set ( body , value ) ;
break ;
case 'mass' :
Body . setMass ( body , value ) ;
break ;
case 'density' :
Body . setDensity ( body , value ) ;
break ;
case 'inertia' :
Body . setInertia ( body , value ) ;
break ;
case 'vertices' :
Body . setVertices ( body , value ) ;
break ;
case 'position' :
Body . setPosition ( body , value ) ;
break ;
case 'angle' :
Body . setAngle ( body , value ) ;
break ;
case 'velocity' :
Body . setVelocity ( body , value ) ;
break ;
case 'angularVelocity' :
Body . setAngularVelocity ( body , value ) ;
break ;
case 'parts' :
Body . setParts ( body , value ) ;
break ;
case 'centre' :
Body . setCentre ( body , value ) ;
break ;
default :
body [ property ] = value ;
2014-02-19 09:15:05 -05:00
2014-03-22 13:51:49 -04:00
}
2014-02-19 09:15:05 -05:00
}
} ;
2016-01-16 17:43:32 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* Sets the body as static , including isStatic flag and setting mass and inertia to Infinity .
* @ method setStatic
* @ param { body } body
* @ param { bool } isStatic
* /
Body . setStatic = function ( body , isStatic ) {
for ( var i = 0 ; i < body . parts . length ; i ++ ) {
var part = body . parts [ i ] ;
part . isStatic = isStatic ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
if ( isStatic ) {
part . _original = {
restitution : part . restitution ,
friction : part . friction ,
mass : part . mass ,
inertia : part . inertia ,
density : part . density ,
inverseMass : part . inverseMass ,
inverseInertia : part . inverseInertia
} ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
part . restitution = 0 ;
part . friction = 1 ;
part . mass = part . inertia = part . density = Infinity ;
part . inverseMass = part . inverseInertia = 0 ;
part . positionPrev . x = part . position . x ;
part . positionPrev . y = part . position . y ;
part . anglePrev = part . angle ;
part . angularVelocity = 0 ;
part . speed = 0 ;
part . angularSpeed = 0 ;
part . motion = 0 ;
} else if ( part . _original ) {
part . restitution = part . _original . restitution ;
part . friction = part . _original . friction ;
part . mass = part . _original . mass ;
part . inertia = part . _original . inertia ;
part . density = part . _original . density ;
part . inverseMass = part . _original . inverseMass ;
part . inverseInertia = part . _original . inverseInertia ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
part . _original = null ;
}
}
} ;
2015-08-17 18:50:03 -04:00
2014-03-24 16:11:42 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Sets the mass of the body . Inverse mass , density and inertia are automatically updated to reflect the change .
* @ method setMass
* @ param { body } body
* @ param { number } mass
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . setMass = function ( body , mass ) {
var moment = body . inertia / ( body . mass / 6 ) ;
body . inertia = moment * ( mass / 6 ) ;
body . inverseInertia = 1 / body . inertia ;
2014-03-24 16:11:42 -04:00
2020-12-26 17:44:24 -05:00
body . mass = mass ;
body . inverseMass = 1 / body . mass ;
body . density = body . mass / body . area ;
2014-03-24 16:11:42 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Sets the density of the body . Mass and inertia are automatically updated to reflect the change .
* @ method setDensity
* @ param { body } body
* @ param { number } density
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . setDensity = function ( body , density ) {
Body . setMass ( body , density * body . area ) ;
body . density = density ;
2014-03-24 16:11:42 -04:00
} ;
2020-12-26 17:44:24 -05:00
2014-03-24 16:11:42 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Sets the moment of inertia ( i . e . second moment of area ) of the body .
* Inverse inertia is automatically updated to reflect the change . Mass is not changed .
* @ method setInertia
* @ param { body } body
* @ param { number } inertia
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . setInertia = function ( body , inertia ) {
body . inertia = inertia ;
body . inverseInertia = 1 / body . inertia ;
2014-03-24 16:11:42 -04:00
} ;
/ * *
2020-12-26 17:44:24 -05:00
* Sets the body ' s vertices and updates body properties accordingly , including inertia , area and mass ( with respect to ` body.density ` ) .
* Vertices will be automatically transformed to be orientated around their centre of mass as the origin .
* They are then automatically translated to world space based on ` body.position ` .
*
* The ` vertices ` argument should be passed as an array of ` Matter.Vector ` points ( or a ` Matter.Vertices ` array ) .
* Vertices must form a convex hull , concave hulls are not supported .
*
* @ method setVertices
* @ param { body } body
* @ param { vector [ ] } vertices
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . setVertices = function ( body , vertices ) {
// change vertices
if ( vertices [ 0 ] . body === body ) {
body . vertices = vertices ;
2014-03-24 16:11:42 -04:00
} else {
2020-12-26 17:44:24 -05:00
body . vertices = Vertices . create ( vertices , body ) ;
2014-03-24 16:11:42 -04:00
}
2020-12-26 17:44:24 -05:00
// update properties
body . axes = Axes . fromVertices ( body . vertices ) ;
body . area = Vertices . area ( body . vertices ) ;
Body . setMass ( body , body . density * body . area ) ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
// orient vertices around the centre of mass at origin (0, 0)
var centre = Vertices . centre ( body . vertices ) ;
Vertices . translate ( body . vertices , centre , - 1 ) ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
// update inertia while vertices are at origin (0, 0)
Body . setInertia ( body , Body . _inertiaScale * Vertices . inertia ( body . vertices , body . mass ) ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// update geometry
Vertices . translate ( body . vertices , body . position ) ;
Bounds . update ( body . bounds , body . vertices , body . velocity ) ;
2014-03-24 16:11:42 -04:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Sets the parts of the ` body ` and updates mass , inertia and centroid .
* Each part will have its parent set to ` body ` .
* By default the convex hull will be automatically computed and set on ` body ` , unless ` autoHull ` is set to ` false. `
* Note that this method will ensure that the first part in ` body.parts ` will always be the ` body ` .
* @ method setParts
* @ param { body } body
* @ param [ body ] parts
* @ param { bool } [ autoHull = true ]
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . setParts = function ( body , parts , autoHull ) {
var i ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// add all the parts, ensuring that the first part is always the parent body
parts = parts . slice ( 0 ) ;
body . parts . length = 0 ;
body . parts . push ( body ) ;
body . parent = body ;
2014-03-11 06:29:14 -04:00
2020-12-26 17:44:24 -05:00
for ( i = 0 ; i < parts . length ; i ++ ) {
var part = parts [ i ] ;
if ( part !== body ) {
part . parent = body ;
body . parts . push ( part ) ;
}
}
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
if ( body . parts . length === 1 )
return ;
2014-03-11 06:29:14 -04:00
2020-12-26 17:44:24 -05:00
autoHull = typeof autoHull !== 'undefined' ? autoHull : true ;
2014-03-11 06:29:14 -04:00
2020-12-26 17:44:24 -05:00
// find the convex hull of all parts to set on the parent body
if ( autoHull ) {
var vertices = [ ] ;
for ( i = 0 ; i < parts . length ; i ++ ) {
vertices = vertices . concat ( parts [ i ] . vertices ) ;
2014-03-11 06:29:14 -04:00
}
2020-12-26 17:44:24 -05:00
Vertices . clockwiseSort ( vertices ) ;
var hull = Vertices . hull ( vertices ) ,
hullCentre = Vertices . centre ( hull ) ;
Body . setVertices ( body , hull ) ;
Vertices . translate ( body . vertices , hullCentre ) ;
2014-03-11 06:29:14 -04:00
}
2020-12-26 17:44:24 -05:00
// sum the properties of all compound parts of the parent body
var total = Body . _totalProperties ( body ) ;
body . area = total . area ;
body . parent = body ;
body . position . x = total . centre . x ;
body . position . y = total . centre . y ;
body . positionPrev . x = total . centre . x ;
body . positionPrev . y = total . centre . y ;
Body . setMass ( body , total . mass ) ;
Body . setInertia ( body , total . inertia ) ;
Body . setPosition ( body , total . centre ) ;
} ;
/ * *
* Set the centre of mass of the body .
* The ` centre ` is a vector in world - space unless ` relative ` is set , in which case it is a translation .
* The centre of mass is the point the body rotates about and can be used to simulate non - uniform density .
* This is equal to moving ` body.position ` but not the ` body.vertices ` .
* Invalid if the ` centre ` falls outside the body ' s convex hull .
* @ method setCentre
* @ param { body } body
* @ param { vector } centre
* @ param { bool } relative
* /
Body . setCentre = function ( body , centre , relative ) {
if ( ! relative ) {
body . positionPrev . x = centre . x - ( body . position . x - body . positionPrev . x ) ;
body . positionPrev . y = centre . y - ( body . position . y - body . positionPrev . y ) ;
body . position . x = centre . x ;
body . position . y = centre . y ;
} else {
body . positionPrev . x += centre . x ;
body . positionPrev . y += centre . y ;
body . position . x += centre . x ;
body . position . y += centre . y ;
2014-02-19 09:15:05 -05:00
}
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Sets the position of the body instantly . Velocity , angle , force etc . are unchanged .
* @ method setPosition
* @ param { body } body
* @ param { vector } position
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . setPosition = function ( body , position ) {
var delta = Vector . sub ( position , body . position ) ;
body . positionPrev . x += delta . x ;
body . positionPrev . y += delta . y ;
2014-03-11 06:29:14 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < body . parts . length ; i ++ ) {
var part = body . parts [ i ] ;
part . position . x += delta . x ;
part . position . y += delta . y ;
Vertices . translate ( part . vertices , delta ) ;
Bounds . update ( part . bounds , part . vertices , body . velocity ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
} ;
2014-03-11 06:29:14 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Sets the angle of the body instantly . Angular velocity , position , force etc . are unchanged .
* @ method setAngle
* @ param { body } body
* @ param { number } angle
* /
Body . setAngle = function ( body , angle ) {
var delta = angle - body . angle ;
body . anglePrev += delta ;
for ( var i = 0 ; i < body . parts . length ; i ++ ) {
var part = body . parts [ i ] ;
part . angle += delta ;
Vertices . rotate ( part . vertices , delta , body . position ) ;
Axes . rotate ( part . axes , delta ) ;
Bounds . update ( part . bounds , part . vertices , body . velocity ) ;
if ( i > 0 ) {
Vector . rotateAbout ( part . position , delta , body . position , part . position ) ;
}
2014-03-11 06:29:14 -04:00
}
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Sets the linear velocity of the body instantly . Position , angle , force etc . are unchanged . See also ` Body.applyForce ` .
* @ method setVelocity
* @ param { body } body
* @ param { vector } velocity
2014-03-24 16:11:42 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . setVelocity = function ( body , velocity ) {
body . positionPrev . x = body . position . x - velocity . x ;
body . positionPrev . y = body . position . y - velocity . y ;
body . velocity . x = velocity . x ;
body . velocity . y = velocity . y ;
body . speed = Vector . magnitude ( body . velocity ) ;
2014-02-19 09:15:05 -05:00
} ;
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Sets the angular velocity of the body instantly . Position , angle , force etc . are unchanged . See also ` Body.applyForce ` .
* @ method setAngularVelocity
2017-11-29 19:16:03 -05:00
* @ param { body } body
2020-12-26 17:44:24 -05:00
* @ param { number } velocity
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . setAngularVelocity = function ( body , velocity ) {
body . anglePrev = body . angle - velocity ;
body . angularVelocity = velocity ;
body . angularSpeed = Math . abs ( body . angularVelocity ) ;
2014-05-01 09:09:06 -04:00
} ;
2017-11-29 19:16:03 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Moves a body by a given vector relative to its current position , without imparting any velocity .
* @ method translate
* @ param { body } body
* @ param { vector } translation
2017-11-29 19:16:03 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . translate = function ( body , translation ) {
Body . setPosition ( body , Vector . add ( body . position , translation ) ) ;
2017-11-29 19:16:03 -05:00
} ;
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Rotates a body by a given angle relative to its current angle , without imparting any angular velocity .
* @ method rotate
* @ param { body } body
* @ param { number } rotation
* @ param { vector } [ point ]
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . rotate = function ( body , rotation , point ) {
if ( ! point ) {
Body . setAngle ( body , body . angle + rotation ) ;
} else {
var cos = Math . cos ( rotation ) ,
sin = Math . sin ( rotation ) ,
dx = body . position . x - point . x ,
dy = body . position . y - point . y ;
Body . setPosition ( body , {
x : point . x + ( dx * cos - dy * sin ) ,
y : point . y + ( dx * sin + dy * cos )
} ) ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
Body . setAngle ( body , body . angle + rotation ) ;
2014-05-01 09:09:06 -04:00
}
} ;
2015-05-20 15:38:41 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Scales the body , including updating physical properties ( mass , area , axes , inertia ) , from a world - space point ( default is body centre ) .
* @ method scale
* @ param { body } body
* @ param { number } scaleX
* @ param { number } scaleY
* @ param { vector } [ point ]
2015-05-20 15:38:41 -04:00
* /
2020-12-26 17:44:24 -05:00
Body . scale = function ( body , scaleX , scaleY , point ) {
var totalArea = 0 ,
totalInertia = 0 ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
point = point || body . position ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < body . parts . length ; i ++ ) {
var part = body . parts [ i ] ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
// scale vertices
Vertices . scale ( part . vertices , scaleX , scaleY , point ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
// update properties
part . axes = Axes . fromVertices ( part . vertices ) ;
part . area = Vertices . area ( part . vertices ) ;
Body . setMass ( part , body . density * part . area ) ;
2016-01-16 17:43:32 -05:00
2020-12-26 17:44:24 -05:00
// update inertia (requires vertices to be at origin)
Vertices . translate ( part . vertices , { x : - part . position . x , y : - part . position . y } ) ;
Body . setInertia ( part , Body . _inertiaScale * Vertices . inertia ( part . vertices , part . mass ) ) ;
Vertices . translate ( part . vertices , { x : part . position . x , y : part . position . y } ) ;
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
if ( i > 0 ) {
totalArea += part . area ;
totalInertia += part . inertia ;
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// scale position
part . position . x = point . x + ( part . position . x - point . x ) * scaleX ;
part . position . y = point . y + ( part . position . y - point . y ) * scaleY ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
// update bounds
Bounds . update ( part . bounds , part . vertices , body . velocity ) ;
}
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
// handle parent body
if ( body . parts . length > 1 ) {
body . area = totalArea ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( ! body . isStatic ) {
Body . setMass ( body , body . density * totalArea ) ;
Body . setInertia ( body , totalInertia ) ;
}
}
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
// handle circles
if ( body . circleRadius ) {
if ( scaleX === scaleY ) {
body . circleRadius *= scaleX ;
} else {
// body is no longer a circle
body . circleRadius = null ;
}
2015-05-20 15:38:41 -04:00
}
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Performs a simulation step for the given ` body ` , including updating position and angle using Verlet integration .
* @ method update
* @ param { body } body
* @ param { number } deltaTime
2014-05-01 09:09:06 -04:00
* @ param { number } timeScale
2020-12-26 17:44:24 -05:00
* @ param { number } correction
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . update = function ( body , deltaTime , timeScale , correction ) {
var deltaTimeSquared = Math . pow ( deltaTime * timeScale * body . timeScale , 2 ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// from the previous step
var frictionAir = 1 - body . frictionAir * timeScale * body . timeScale ,
velocityPrevX = body . position . x - body . positionPrev . x ,
velocityPrevY = body . position . y - body . positionPrev . y ;
2016-04-07 15:03:37 -04:00
2020-12-26 17:44:24 -05:00
// update velocity with Verlet integration
body . velocity . x = ( velocityPrevX * frictionAir * correction ) + ( body . force . x / body . mass ) * deltaTimeSquared ;
body . velocity . y = ( velocityPrevY * frictionAir * correction ) + ( body . force . y / body . mass ) * deltaTimeSquared ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
body . positionPrev . x = body . position . x ;
body . positionPrev . y = body . position . y ;
body . position . x += body . velocity . x ;
body . position . y += body . velocity . y ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// update angular velocity with Verlet integration
body . angularVelocity = ( ( body . angle - body . anglePrev ) * frictionAir * correction ) + ( body . torque / body . inertia ) * deltaTimeSquared ;
body . anglePrev = body . angle ;
body . angle += body . angularVelocity ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
// track speed and acceleration
body . speed = Vector . magnitude ( body . velocity ) ;
body . angularSpeed = Math . abs ( body . angularVelocity ) ;
2016-04-07 15:03:37 -04:00
2020-12-26 17:44:24 -05:00
// transform the body geometry
for ( var i = 0 ; i < body . parts . length ; i ++ ) {
var part = body . parts [ i ] ;
Vertices . translate ( part . vertices , body . velocity ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( i > 0 ) {
part . position . x += body . velocity . x ;
part . position . y += body . velocity . y ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
if ( body . angularVelocity !== 0 ) {
Vertices . rotate ( part . vertices , body . angularVelocity , body . position ) ;
Axes . rotate ( part . axes , body . angularVelocity ) ;
if ( i > 0 ) {
Vector . rotateAbout ( part . position , body . angularVelocity , body . position , part . position ) ;
}
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
Bounds . update ( part . bounds , part . vertices , body . velocity ) ;
2014-02-19 09:15:05 -05:00
}
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Applies a force to a body from a given world - space position , including resulting torque .
* @ method applyForce
* @ param { body } body
* @ param { vector } position
* @ param { vector } force
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . applyForce = function ( body , position , force ) {
body . force . x += force . x ;
body . force . y += force . y ;
var offset = { x : position . x - body . position . x , y : position . y - body . position . y } ;
body . torque += offset . x * force . y - offset . y * force . x ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the sums of the properties of all compound parts of the parent body .
* @ method _totalProperties
* @ private
* @ param { body } body
* @ return { }
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Body . _totalProperties = function ( body ) {
// from equations at:
// https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory
// http://output.to/sideway/default.asp?qno=121100087
2016-04-07 15:03:37 -04:00
2020-12-26 17:44:24 -05:00
var properties = {
mass : 0 ,
area : 0 ,
inertia : 0 ,
centre : { x : 0 , y : 0 }
} ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// sum the properties of all compound parts of the parent body
for ( var i = body . parts . length === 1 ? 0 : 1 ; i < body . parts . length ; i ++ ) {
var part = body . parts [ i ] ,
mass = part . mass !== Infinity ? part . mass : 1 ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
properties . mass += mass ;
properties . area += part . area ;
properties . inertia += part . inertia ;
properties . centre = Vector . add ( properties . centre , Vector . mult ( part . position , mass ) ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
properties . centre = Vector . div ( properties . centre , properties . mass ) ;
return properties ;
2014-02-19 09:15:05 -05:00
} ;
2020-12-26 17:44:24 -05:00
/ *
*
* Events Documentation
*
* /
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Fired when a body starts sleeping ( where ` this ` is the body ) .
*
* @ event sleepStart
* @ this { body } The body that has started sleeping
* @ param { } event An event object
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ * *
* Fired when a body ends sleeping ( where ` this ` is the body ) .
*
* @ event sleepEnd
* @ this { body } The body that has ended sleeping
* @ param { } event An event object
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ *
*
* Properties Documentation
*
* /
/ * *
* An integer ` Number ` uniquely identifying number generated in ` Body.create ` by ` Common.nextId ` .
*
* @ property id
* @ type number
2014-02-28 20:10:08 -05:00
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` String ` denoting the type of object .
*
* @ property type
* @ type string
* @ default "body"
* @ readOnly
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An arbitrary ` String ` name to help the user identify and manage bodies .
*
* @ property label
* @ type string
* @ default "Body"
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An array of bodies that make up this body .
* The first body in the array must always be a self reference to the current body instance .
* All bodies in the ` parts ` array together form a single rigid compound body .
* Parts are allowed to overlap , have gaps or holes or even form concave bodies .
* Parts themselves should never be added to a ` World ` , only the parent body should be .
* Use ` Body.setParts ` when setting parts to ensure correct updates of all properties .
*
* @ property parts
* @ type body [ ]
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An object reserved for storing plugin - specific properties .
*
* @ property plugin
* @ type { }
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A self reference if the body is _not _ a part of another body .
* Otherwise this is a reference to the body that this is a part of .
* See ` body.parts ` .
*
* @ property parent
* @ type body
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` specifying the angle of the body , in radians .
*
* @ property angle
* @ type number
* @ default 0
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An array of ` Vector ` objects that specify the convex hull of the rigid body .
* These should be provided about the origin ` (0, 0) ` . E . g .
*
* [ { x : 0 , y : 0 } , { x : 25 , y : 50 } , { x : 50 , y : 0 } ]
*
* When passed via ` Body.create ` , the vertices are translated relative to ` body.position ` ( i . e . world - space , and constantly updated by ` Body.update ` during simulation ) .
* The ` Vector ` objects are also augmented with additional properties required for efficient collision detection .
*
* Other properties such as ` inertia ` and ` bounds ` are automatically calculated from the passed vertices ( unless provided via ` options ` ) .
* Concave hulls are not currently supported . The module ` Matter.Vertices ` contains useful methods for working with vertices .
*
* @ property vertices
* @ type vector [ ]
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Vector ` that specifies the current world - space position of the body .
*
* @ property position
* @ type vector
* @ default { x : 0 , y : 0 }
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Vector ` that specifies the force to apply in the current step . It is zeroed after every ` Body.update ` . See also ` Body.applyForce ` .
*
* @ property force
* @ type vector
* @ default { x : 0 , y : 0 }
* /
2015-12-23 08:08:54 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that specifies the torque ( turning force ) to apply in the current step . It is zeroed after every ` Body.update ` .
*
* @ property torque
* @ type number
* @ default 0
* /
2015-12-23 08:08:54 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that _measures _ the current speed of the body after the last ` Body.update ` . It is read - only and always positive ( it ' s the magnitude of ` body.velocity ` ) .
*
* @ readOnly
* @ property speed
* @ type number
* @ default 0
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that _measures _ the current angular speed of the body after the last ` Body.update ` . It is read - only and always positive ( it ' s the magnitude of ` body.angularVelocity ` ) .
*
* @ readOnly
* @ property angularSpeed
* @ type number
* @ default 0
* /
/ * *
* A ` Vector ` that _measures _ the current velocity of the body after the last ` Body.update ` . It is read - only .
* If you need to modify a body 's velocity directly, you should either apply a force or simply change the body' s ` position ` ( as the engine uses position - Verlet integration ) .
*
* @ readOnly
* @ property velocity
* @ type vector
* @ default { x : 0 , y : 0 }
* /
/ * *
* A ` Number ` that _measures _ the current angular velocity of the body after the last ` Body.update ` . It is read - only .
* If you need to modify a body 's angular velocity directly, you should apply a torque or simply change the body' s ` angle ` ( as the engine uses position - Verlet integration ) .
*
* @ readOnly
* @ property angularVelocity
* @ type number
* @ default 0
* /
/ * *
* A flag that indicates whether a body is considered static . A static body can never change position or angle and is completely fixed .
* If you need to set a body as static after its creation , you should use ` Body.setStatic ` as this requires more than just setting this flag .
*
* @ property isStatic
* @ type boolean
* @ default false
* /
/ * *
* A flag that indicates whether a body is a sensor . Sensor triggers collision events , but doesn ' t react with colliding body physically .
*
* @ property isSensor
* @ type boolean
* @ default false
* /
/ * *
* A flag that indicates whether the body is considered sleeping . A sleeping body acts similar to a static body , except it is only temporary and can be awoken .
* If you need to set a body as sleeping , you should use ` Sleeping.set ` as this requires more than just setting this flag .
*
* @ property isSleeping
* @ type boolean
* @ default false
* /
/ * *
* A ` Number ` that _measures _ the amount of movement a body currently has ( a combination of ` speed ` and ` angularSpeed ` ) . It is read - only and always positive .
* It is used and updated by the ` Matter.Sleeping ` module during simulation to decide if a body has come to rest .
*
* @ readOnly
* @ property motion
* @ type number
* @ default 0
* /
/ * *
* A ` Number ` that defines the number of updates in which this body must have near - zero velocity before it is set as sleeping by the ` Matter.Sleeping ` module ( if sleeping is enabled by the engine ) .
*
* @ property sleepThreshold
* @ type number
* @ default 60
* /
/ * *
* A ` Number ` that defines the density of the body , that is its mass per unit area .
* If you pass the density via ` Body.create ` the ` mass ` property is automatically calculated for you based on the size ( area ) of the object .
* This is generally preferable to simply setting mass and allows for more intuitive definition of materials ( e . g . rock has a higher density than wood ) .
*
* @ property density
* @ type number
* @ default 0.001
* /
/ * *
* A ` Number ` that defines the mass of the body , although it may be more appropriate to specify the ` density ` property instead .
* If you modify this value , you must also modify the ` body.inverseMass ` property ( ` 1 / mass ` ) .
*
* @ property mass
* @ type number
* /
/ * *
* A ` Number ` that defines the inverse mass of the body ( ` 1 / mass ` ) .
* If you modify this value , you must also modify the ` body.mass ` property .
*
* @ property inverseMass
* @ type number
* /
/ * *
* A ` Number ` that defines the moment of inertia ( i . e . second moment of area ) of the body .
* It is automatically calculated from the given convex hull ( ` vertices ` array ) and density in ` Body.create ` .
* If you modify this value , you must also modify the ` body.inverseInertia ` property ( ` 1 / inertia ` ) .
*
* @ property inertia
* @ type number
* /
/ * *
* A ` Number ` that defines the inverse moment of inertia of the body ( ` 1 / inertia ` ) .
* If you modify this value , you must also modify the ` body.inertia ` property .
*
* @ property inverseInertia
* @ type number
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the restitution ( elasticity ) of the body . The value is always positive and is in the range ` (0, 1) ` .
* A value of ` 0 ` means collisions may be perfectly inelastic and no bouncing may occur .
* A value of ` 0.8 ` means the body may bounce back with approximately 80 % of its kinetic energy .
* Note that collision response is based on _pairs _ of bodies , and that ` restitution ` values are _combined _ with the following formula :
*
* Math . max ( bodyA . restitution , bodyB . restitution )
*
* @ property restitution
* @ type number
* @ default 0
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the friction of the body . The value is always positive and is in the range ` (0, 1) ` .
* A value of ` 0 ` means that the body may slide indefinitely .
* A value of ` 1 ` means the body may come to a stop almost instantly after a force is applied .
*
* The effects of the value may be non - linear .
* High values may be unstable depending on the body .
* The engine uses a Coulomb friction model including static and kinetic friction .
* Note that collision response is based on _pairs _ of bodies , and that ` friction ` values are _combined _ with the following formula :
*
* Math . min ( bodyA . friction , bodyB . friction )
*
* @ property friction
* @ type number
* @ default 0.1
* /
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the static friction of the body ( in the Coulomb friction model ) .
* A value of ` 0 ` means the body will never 'stick' when it is nearly stationary and only dynamic ` friction ` is used .
* The higher the value ( e . g . ` 10 ` ) , the more force it will take to initially get the body moving when nearly stationary .
* This value is multiplied with the ` friction ` property to make it easier to change ` friction ` and maintain an appropriate amount of static friction .
*
* @ property frictionStatic
* @ type number
* @ default 0.5
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the air friction of the body ( air resistance ) .
* A value of ` 0 ` means the body will never slow as it moves through space .
* The higher the value , the faster a body slows when moving through space .
* The effects of the value are non - linear .
*
* @ property frictionAir
* @ type number
* @ default 0.01
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An ` Object ` that specifies the collision filtering properties of this body .
*
* Collisions between two bodies will obey the following rules :
* - If the two bodies have the same non - zero value of ` collisionFilter.group ` ,
* they will always collide if the value is positive , and they will never collide
* if the value is negative .
* - If the two bodies have different values of ` collisionFilter.group ` or if one
* ( or both ) of the bodies has a value of 0 , then the category / mask rules apply as follows :
*
* Each body belongs to a collision category , given by ` collisionFilter.category ` . This
* value is used as a bit field and the category should have only one bit set , meaning that
* the value of this property is a power of two in the range [ 1 , 2 ^ 31 ] . Thus , there are 32
* different collision categories available .
*
* Each body also defines a collision bitmask , given by ` collisionFilter.mask ` which specifies
* the categories it collides with ( the value is the bitwise AND value of all these categories ) .
*
* Using the category / mask rules , two bodies ` A ` and ` B ` collide if each includes the other ' s
* category in its mask , i . e . ` (categoryA & maskB) !== 0 ` and ` (categoryB & maskA) !== 0 `
* are both true .
*
* @ property collisionFilter
* @ type object
* /
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* An Integer ` Number ` , that specifies the collision group this body belongs to .
* See ` body.collisionFilter ` for more information .
*
* @ property collisionFilter . group
* @ type object
* @ default 0
* /
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A bit field that specifies the collision category this body belongs to .
* The category value should have only one bit set , for example ` 0x0001 ` .
* This means there are up to 32 unique collision categories available .
* See ` body.collisionFilter ` for more information .
*
* @ property collisionFilter . category
* @ type object
* @ default 1
* /
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* A bit mask that specifies the collision categories this body may collide with .
* See ` body.collisionFilter ` for more information .
*
* @ property collisionFilter . mask
* @ type object
* @ default - 1
2014-02-28 20:10:08 -05:00
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that specifies a tolerance on how far a body is allowed to 'sink' or rotate into other bodies .
* Avoid changing this value unless you understand the purpose of ` slop ` in physics engines .
* The default should generally suffice , although very large bodies may require larger values for stable stacking .
*
* @ property slop
* @ type number
* @ default 0.05
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that allows per - body time scaling , e . g . a force - field where bodies inside are in slow - motion , while others are at full speed .
*
* @ property timeScale
* @ type number
* @ default 1
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An ` Object ` that defines the rendering properties to be consumed by the module ` Matter.Render ` .
*
* @ property render
* @ type object
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A flag that indicates if the body should be rendered .
*
* @ property render . visible
* @ type boolean
* @ default true
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* Sets the opacity to use when rendering .
*
* @ property render . opacity
* @ type number
* @ default 1
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An ` Object ` that defines the sprite properties to use when rendering , if any .
*
* @ property render . sprite
* @ type object
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* An ` String ` that defines the path to the image to use as the sprite texture , if any .
*
* @ property render . sprite . texture
* @ type string
* /
/ * *
* A ` Number ` that defines the scaling in the x - axis for the sprite , if any .
*
* @ property render . sprite . xScale
* @ type number
* @ default 1
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the scaling in the y - axis for the sprite , if any .
*
* @ property render . sprite . yScale
* @ type number
* @ default 1
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the offset in the x - axis for the sprite ( normalised by texture width ) .
*
* @ property render . sprite . xOffset
* @ type number
* @ default 0
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the offset in the y - axis for the sprite ( normalised by texture height ) .
*
* @ property render . sprite . yOffset
* @ type number
* @ default 0
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Number ` that defines the line width to use when rendering the body outline ( if a sprite is not defined ) .
* A value of ` 0 ` means no outline will be rendered .
*
* @ property render . lineWidth
* @ type number
* @ default 0
* /
/ * *
* A ` String ` that defines the fill style to use when rendering the body ( if a sprite is not defined ) .
* It is the same as when using a canvas , so it accepts CSS style property values .
*
* @ property render . fillStyle
* @ type string
* @ default a random colour
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` String ` that defines the stroke style to use when rendering the body outline ( if a sprite is not defined ) .
* It is the same as when using a canvas , so it accepts CSS style property values .
*
* @ property render . strokeStyle
* @ type string
* @ default a random colour
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* An array of unique axis vectors ( edge normals ) used for collision detection .
* These are automatically calculated from the given convex hull ( ` vertices ` array ) in ` Body.create ` .
* They are constantly updated by ` Body.update ` during the simulation .
*
* @ property axes
* @ type vector [ ]
* /
/ * *
* A ` Number ` that _measures _ the area of the body ' s convex hull , calculated at creation by ` Body.create ` .
*
* @ property area
* @ type string
* @ default
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Bounds ` object that defines the AABB region for the body .
* It is automatically calculated from the given convex hull ( ` vertices ` array ) in ` Body.create ` and constantly updated by ` Body.update ` during simulation .
*
* @ property bounds
* @ type bounds
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 7 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* The ` Matter.Sleeping ` module contains methods to manage the sleeping state of bodies .
*
* @ class Sleeping
* /
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
var Sleeping = { } ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
module . exports = Sleeping ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var Events = _ _webpack _require _ _ ( 4 ) ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
( function ( ) {
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
Sleeping . _motionWakeThreshold = 0.18 ;
Sleeping . _motionSleepThreshold = 0.08 ;
Sleeping . _minBias = 0.9 ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Puts bodies to sleep or wakes them up depending on their motion .
* @ method update
* @ param { body [ ] } bodies
* @ param { number } timeScale
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Sleeping . update = function ( bodies , timeScale ) {
var timeFactor = timeScale * timeScale * timeScale ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// update bodies sleeping status
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ,
motion = body . speed * body . speed + body . angularSpeed * body . angularSpeed ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// wake up bodies if they have a force applied
if ( body . force . x !== 0 || body . force . y !== 0 ) {
Sleeping . set ( body , false ) ;
continue ;
2014-03-22 13:51:49 -04:00
}
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var minMotion = Math . min ( body . motion , motion ) ,
maxMotion = Math . max ( body . motion , motion ) ;
// biased average motion estimation between frames
body . motion = Sleeping . _minBias * minMotion + ( 1 - Sleeping . _minBias ) * maxMotion ;
if ( body . sleepThreshold > 0 && body . motion < Sleeping . _motionSleepThreshold * timeFactor ) {
body . sleepCounter += 1 ;
if ( body . sleepCounter >= body . sleepThreshold )
Sleeping . set ( body , true ) ;
} else if ( body . sleepCounter > 0 ) {
body . sleepCounter -= 1 ;
2014-02-19 09:15:05 -05:00
}
}
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Given a set of colliding pairs , wakes the sleeping bodies involved .
* @ method afterCollisions
* @ param { pair [ ] } pairs
* @ param { number } timeScale
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Sleeping . afterCollisions = function ( pairs , timeScale ) {
var timeFactor = timeScale * timeScale * timeScale ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// wake up bodies involved in collisions
for ( var i = 0 ; i < pairs . length ; i ++ ) {
var pair = pairs [ i ] ;
// don't wake inactive pairs
if ( ! pair . isActive )
continue ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var collision = pair . collision ,
bodyA = collision . bodyA . parent ,
bodyB = collision . bodyB . parent ;
// don't wake if at least one body is static
if ( ( bodyA . isSleeping && bodyB . isSleeping ) || bodyA . isStatic || bodyB . isStatic )
continue ;
if ( bodyA . isSleeping || bodyB . isSleeping ) {
var sleepingBody = ( bodyA . isSleeping && ! bodyA . isStatic ) ? bodyA : bodyB ,
movingBody = sleepingBody === bodyA ? bodyB : bodyA ;
if ( ! sleepingBody . isStatic && movingBody . motion > Sleeping . _motionWakeThreshold * timeFactor ) {
Sleeping . set ( sleepingBody , false ) ;
}
2014-02-19 09:15:05 -05:00
}
}
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Set a body as sleeping or awake .
* @ method set
* @ param { body } body
* @ param { boolean } isSleeping
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
Sleeping . set = function ( body , isSleeping ) {
var wasSleeping = body . isSleeping ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( isSleeping ) {
body . isSleeping = true ;
body . sleepCounter = body . sleepThreshold ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
body . positionImpulse . x = 0 ;
body . positionImpulse . y = 0 ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
body . positionPrev . x = body . position . x ;
body . positionPrev . y = body . position . y ;
body . anglePrev = body . angle ;
body . speed = 0 ;
body . angularSpeed = 0 ;
body . motion = 0 ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( ! wasSleeping ) {
Events . trigger ( body , 'sleepStart' ) ;
}
} else {
body . isSleeping = false ;
body . sleepCounter = 0 ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( wasSleeping ) {
Events . trigger ( body , 'sleepEnd' ) ;
}
}
2014-02-19 09:15:05 -05:00
} ;
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 8 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-02-28 20:10:08 -05:00
/ * *
2014-06-09 14:40:24 -04:00
* The ` Matter.Constraint ` module contains methods for creating and manipulating constraints .
* Constraints are used for specifying that a fixed distance must be maintained between two bodies ( or a body and a fixed world - space position ) .
* The stiffness of constraints can be modified to create springs or elastic .
*
2016-01-16 17:43:32 -05:00
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
2014-02-28 20:10:08 -05:00
*
* @ class Constraint
* /
2014-02-19 09:15:05 -05:00
var Constraint = { } ;
2015-08-17 18:50:03 -04:00
module . exports = Constraint ;
2020-12-26 17:44:24 -05:00
var Vertices = _ _webpack _require _ _ ( 3 ) ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
var Sleeping = _ _webpack _require _ _ ( 7 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
2021-04-11 12:49:36 -04:00
var Axes = _ _webpack _require _ _ ( 10 ) ;
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2015-08-17 18:50:03 -04:00
2014-02-19 09:15:05 -05:00
( function ( ) {
2017-05-03 19:40:04 -04:00
Constraint . _warming = 0.4 ;
Constraint . _torqueDampen = 1 ;
Constraint . _minLength = 0.000001 ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2014-06-09 14:40:24 -04:00
* Creates a new constraint .
* All properties have default values , and many are pre - calculated automatically based on other properties .
2017-06-12 14:55:17 -04:00
* To simulate a revolute constraint ( or pin joint ) set ` length: 0 ` and a high ` stiffness ` value ( e . g . ` 0.7 ` or above ) .
* If the constraint is unstable , try lowering the ` stiffness ` value and / or increasing ` engine.constraintIterations ` .
2017-11-29 19:16:03 -05:00
* For compound bodies , constraints must be applied to the parent body ( not one of its parts ) .
2015-06-29 15:58:24 -04:00
* See the properties section below for detailed information on what you can pass via the ` options ` object .
2014-02-28 20:10:08 -05:00
* @ method create
* @ param { } options
* @ return { constraint } constraint
* /
2014-02-19 09:15:05 -05:00
Constraint . create = function ( options ) {
var constraint = options ;
// if bodies defined but no points, use body centre
if ( constraint . bodyA && ! constraint . pointA )
constraint . pointA = { x : 0 , y : 0 } ;
if ( constraint . bodyB && ! constraint . pointB )
constraint . pointB = { x : 0 , y : 0 } ;
// calculate static length using initial world space points
var initialPointA = constraint . bodyA ? Vector . add ( constraint . bodyA . position , constraint . pointA ) : constraint . pointA ,
initialPointB = constraint . bodyB ? Vector . add ( constraint . bodyB . position , constraint . pointB ) : constraint . pointB ,
length = Vector . magnitude ( Vector . sub ( initialPointA , initialPointB ) ) ;
2017-05-03 19:40:04 -04:00
constraint . length = typeof constraint . length !== 'undefined' ? constraint . length : length ;
2014-02-19 09:15:05 -05:00
// option defaults
2014-05-01 09:09:06 -04:00
constraint . id = constraint . id || Common . nextId ( ) ;
constraint . label = constraint . label || 'Constraint' ;
2014-03-30 14:45:30 -04:00
constraint . type = 'constraint' ;
2017-06-12 14:55:17 -04:00
constraint . stiffness = constraint . stiffness || ( constraint . length > 0 ? 1 : 0.7 ) ;
constraint . damping = constraint . damping || 0 ;
2014-02-19 09:15:05 -05:00
constraint . angularStiffness = constraint . angularStiffness || 0 ;
constraint . angleA = constraint . bodyA ? constraint . bodyA . angle : constraint . angleA ;
constraint . angleB = constraint . bodyB ? constraint . bodyB . angle : constraint . angleB ;
2017-01-26 18:49:29 -05:00
constraint . plugin = { } ;
2014-02-19 09:15:05 -05:00
2017-06-26 18:21:22 -04:00
// render
var render = {
visible : true ,
lineWidth : 2 ,
strokeStyle : '#ffffff' ,
type : 'line' ,
anchors : true
} ;
2017-07-06 18:47:04 -04:00
if ( constraint . length === 0 && constraint . stiffness > 0.1 ) {
2017-06-26 18:21:22 -04:00
render . type = 'pin' ;
render . anchors = false ;
} else if ( constraint . stiffness < 0.9 ) {
render . type = 'spring' ;
}
constraint . render = Common . extend ( render , constraint . render ) ;
2020-12-26 17:44:24 -05:00
return constraint ;
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Prepares for solving by constraint warming .
* @ private
* @ method preSolveAll
* @ param { body [ ] } bodies
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Constraint . preSolveAll = function ( bodies ) {
for ( var i = 0 ; i < bodies . length ; i += 1 ) {
var body = bodies [ i ] ,
impulse = body . constraintImpulse ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( body . isStatic || ( impulse . x === 0 && impulse . y === 0 && impulse . angle === 0 ) ) {
continue ;
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
body . position . x += impulse . x ;
body . position . y += impulse . y ;
body . angle += impulse . angle ;
}
} ;
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Solves all constraints in a list of collisions .
* @ private
* @ method solveAll
* @ param { constraint [ ] } constraints
* @ param { number } timeScale
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Constraint . solveAll = function ( constraints , timeScale ) {
// Solve fixed constraints first.
for ( var i = 0 ; i < constraints . length ; i += 1 ) {
var constraint = constraints [ i ] ,
fixedA = ! constraint . bodyA || ( constraint . bodyA && constraint . bodyA . isStatic ) ,
fixedB = ! constraint . bodyB || ( constraint . bodyB && constraint . bodyB . isStatic ) ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( fixedA || fixedB ) {
Constraint . solve ( constraints [ i ] , timeScale ) ;
}
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
// Solve free constraints last.
for ( i = 0 ; i < constraints . length ; i += 1 ) {
constraint = constraints [ i ] ;
fixedA = ! constraint . bodyA || ( constraint . bodyA && constraint . bodyA . isStatic ) ;
fixedB = ! constraint . bodyB || ( constraint . bodyB && constraint . bodyB . isStatic ) ;
2017-06-26 18:21:22 -04:00
2020-12-26 17:44:24 -05:00
if ( ! fixedA && ! fixedB ) {
Constraint . solve ( constraints [ i ] , timeScale ) ;
}
}
} ;
2017-06-26 18:21:22 -04:00
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Solves a distance constraint with Gauss - Siedel method .
* @ private
* @ method solve
* @ param { constraint } constraint
* @ param { number } timeScale
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Constraint . solve = function ( constraint , timeScale ) {
var bodyA = constraint . bodyA ,
bodyB = constraint . bodyB ,
pointA = constraint . pointA ,
pointB = constraint . pointB ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( ! bodyA && ! bodyB )
return ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
// update reference angle
if ( bodyA && ! bodyA . isStatic ) {
Vector . rotate ( pointA , bodyA . angle - constraint . angleA , pointA ) ;
constraint . angleA = bodyA . angle ;
}
// update reference angle
if ( bodyB && ! bodyB . isStatic ) {
Vector . rotate ( pointB , bodyB . angle - constraint . angleB , pointB ) ;
constraint . angleB = bodyB . angle ;
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
var pointAWorld = pointA ,
pointBWorld = pointB ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( bodyA ) pointAWorld = Vector . add ( bodyA . position , pointA ) ;
if ( bodyB ) pointBWorld = Vector . add ( bodyB . position , pointB ) ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( ! pointAWorld || ! pointBWorld )
return ;
2017-06-12 14:55:17 -04:00
2020-12-26 17:44:24 -05:00
var delta = Vector . sub ( pointAWorld , pointBWorld ) ,
currentLength = Vector . magnitude ( delta ) ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
// prevent singularity
if ( currentLength < Constraint . _minLength ) {
currentLength = Constraint . _minLength ;
}
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
// solve distance constraint with Gauss-Siedel method
var difference = ( currentLength - constraint . length ) / currentLength ,
stiffness = constraint . stiffness < 1 ? constraint . stiffness * timeScale : constraint . stiffness ,
force = Vector . mult ( delta , difference * stiffness ) ,
massTotal = ( bodyA ? bodyA . inverseMass : 0 ) + ( bodyB ? bodyB . inverseMass : 0 ) ,
inertiaTotal = ( bodyA ? bodyA . inverseInertia : 0 ) + ( bodyB ? bodyB . inverseInertia : 0 ) ,
resistanceTotal = massTotal + inertiaTotal ,
torque ,
share ,
normal ,
normalVelocity ,
relativeVelocity ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( constraint . damping ) {
var zero = Vector . create ( ) ;
normal = Vector . div ( delta , currentLength ) ;
2014-02-28 20:10:08 -05:00
2020-12-26 17:44:24 -05:00
relativeVelocity = Vector . sub (
bodyB && Vector . sub ( bodyB . position , bodyB . positionPrev ) || zero ,
bodyA && Vector . sub ( bodyA . position , bodyA . positionPrev ) || zero
) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
normalVelocity = Vector . dot ( normal , relativeVelocity ) ;
}
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
if ( bodyA && ! bodyA . isStatic ) {
share = bodyA . inverseMass / massTotal ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
// keep track of applied impulses for post solving
bodyA . constraintImpulse . x -= force . x * share ;
bodyA . constraintImpulse . y -= force . y * share ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// apply forces
bodyA . position . x -= force . x * share ;
bodyA . position . y -= force . y * share ;
2015-01-20 19:15:04 -05:00
2020-12-26 17:44:24 -05:00
// apply damping
if ( constraint . damping ) {
bodyA . positionPrev . x -= constraint . damping * normal . x * normalVelocity * share ;
bodyA . positionPrev . y -= constraint . damping * normal . y * normalVelocity * share ;
2015-12-23 08:50:31 -05:00
}
2020-12-26 17:44:24 -05:00
// apply torque
torque = ( Vector . cross ( pointA , force ) / resistanceTotal ) * Constraint . _torqueDampen * bodyA . inverseInertia * ( 1 - constraint . angularStiffness ) ;
bodyA . constraintImpulse . angle -= torque ;
bodyA . angle -= torque ;
2015-01-20 19:15:04 -05:00
}
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
if ( bodyB && ! bodyB . isStatic ) {
share = bodyB . inverseMass / massTotal ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// keep track of applied impulses for post solving
bodyB . constraintImpulse . x += force . x * share ;
bodyB . constraintImpulse . y += force . y * share ;
// apply forces
bodyB . position . x += force . x * share ;
bodyB . position . y += force . y * share ;
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
// apply damping
if ( constraint . damping ) {
bodyB . positionPrev . x += constraint . damping * normal . x * normalVelocity * share ;
bodyB . positionPrev . y += constraint . damping * normal . y * normalVelocity * share ;
}
2014-03-30 14:45:30 -04:00
2020-12-26 17:44:24 -05:00
// apply torque
torque = ( Vector . cross ( pointB , force ) / resistanceTotal ) * Constraint . _torqueDampen * bodyB . inverseInertia * ( 1 - constraint . angularStiffness ) ;
bodyB . constraintImpulse . angle += torque ;
bodyB . angle += torque ;
}
2014-03-30 14:45:30 -04:00
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Performs body updates required after solving constraints .
2014-06-09 14:40:24 -04:00
* @ private
2020-12-26 17:44:24 -05:00
* @ method postSolveAll
2014-02-28 20:10:08 -05:00
* @ param { body [ ] } bodies
* /
2020-12-26 17:44:24 -05:00
Constraint . postSolveAll = function ( bodies ) {
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ,
impulse = body . constraintImpulse ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
if ( body . isStatic || ( impulse . x === 0 && impulse . y === 0 && impulse . angle === 0 ) ) {
continue ;
}
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
Sleeping . set ( body , false ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
// update geometry and reset
for ( var j = 0 ; j < body . parts . length ; j ++ ) {
var part = body . parts [ j ] ;
Vertices . translate ( part . vertices , impulse ) ;
if ( j > 0 ) {
part . position . x += impulse . x ;
part . position . y += impulse . y ;
}
if ( impulse . angle !== 0 ) {
Vertices . rotate ( part . vertices , impulse . angle , body . position ) ;
Axes . rotate ( part . axes , impulse . angle ) ;
if ( j > 0 ) {
Vector . rotateAbout ( part . position , impulse . angle , body . position , part . position ) ;
2014-02-19 09:15:05 -05:00
}
}
2020-12-26 17:44:24 -05:00
Bounds . update ( part . bounds , part . vertices , body . velocity ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
// dampen the cached impulse for warming next step
impulse . angle *= Constraint . _warming ;
impulse . x *= Constraint . _warming ;
impulse . y *= Constraint . _warming ;
2014-02-19 09:15:05 -05:00
}
} ;
2014-07-29 11:26:49 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Returns the world - space position of ` constraint.pointA ` , accounting for ` constraint.bodyA ` .
* @ method pointAWorld
* @ param { constraint } constraint
* @ returns { vector } the world - space position
2014-07-29 11:26:49 -04:00
* /
2020-12-26 17:44:24 -05:00
Constraint . pointAWorld = function ( constraint ) {
return {
x : ( constraint . bodyA ? constraint . bodyA . position . x : 0 ) + constraint . pointA . x ,
y : ( constraint . bodyA ? constraint . bodyA . position . y : 0 ) + constraint . pointA . y
} ;
} ;
2014-07-29 11:26:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* Returns the world - space position of ` constraint.pointB ` , accounting for ` constraint.bodyB ` .
* @ method pointBWorld
* @ param { constraint } constraint
* @ returns { vector } the world - space position
* /
Constraint . pointBWorld = function ( constraint ) {
return {
x : ( constraint . bodyB ? constraint . bodyB . position . x : 0 ) + constraint . pointB . x ,
y : ( constraint . bodyB ? constraint . bodyB . position . y : 0 ) + constraint . pointB . y
} ;
2014-07-29 11:26:49 -04:00
} ;
/ *
*
2020-12-26 17:44:24 -05:00
* Properties Documentation
2014-07-29 11:26:49 -04:00
*
* /
/ * *
2020-12-26 17:44:24 -05:00
* An integer ` Number ` uniquely identifying number generated in ` Composite.create ` by ` Common.nextId ` .
*
* @ property id
* @ type number
* /
2014-07-29 11:26:49 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* A ` String ` denoting the type of object .
*
* @ property type
* @ type string
* @ default "constraint"
* @ readOnly
* /
2014-07-29 11:26:49 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* An arbitrary ` String ` name to help the user identify and manage bodies .
*
* @ property label
* @ type string
* @ default "Constraint"
* /
2014-07-29 11:26:49 -04:00
2014-12-02 16:40:34 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* An ` Object ` that defines the rendering properties to be consumed by the module ` Matter.Render ` .
*
* @ property render
* @ type object
* /
/ * *
* A flag that indicates if the constraint should be rendered .
*
* @ property render . visible
* @ type boolean
* @ default true
* /
/ * *
* A ` Number ` that defines the line width to use when rendering the constraint outline .
* A value of ` 0 ` means no outline will be rendered .
*
* @ property render . lineWidth
* @ type number
* @ default 2
* /
/ * *
* A ` String ` that defines the stroke style to use when rendering the constraint outline .
* It is the same as when using a canvas , so it accepts CSS style property values .
*
* @ property render . strokeStyle
* @ type string
* @ default a random colour
* /
/ * *
* A ` String ` that defines the constraint rendering type .
* The possible values are 'line' , 'pin' , 'spring' .
* An appropriate render type will be automatically chosen unless one is given in options .
*
* @ property render . type
* @ type string
* @ default 'line'
* /
/ * *
* A ` Boolean ` that defines if the constraint ' s anchor points should be rendered .
*
* @ property render . anchors
* @ type boolean
* @ default true
* /
/ * *
* The first possible ` Body ` that this constraint is attached to .
*
* @ property bodyA
* @ type body
* @ default null
* /
2014-12-02 16:40:34 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* The second possible ` Body ` that this constraint is attached to .
*
* @ property bodyB
* @ type body
* @ default null
* /
2014-12-02 16:40:34 -05:00
2020-12-26 17:44:24 -05:00
/ * *
* A ` Vector ` that specifies the offset of the constraint from center of the ` constraint.bodyA ` if defined , otherwise a world - space position .
*
* @ property pointA
* @ type vector
* @ default { x : 0 , y : 0 }
* /
2014-06-09 14:40:24 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* A ` Vector ` that specifies the offset of the constraint from center of the ` constraint.bodyB ` if defined , otherwise a world - space position .
2014-06-09 14:40:24 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property pointB
* @ type vector
* @ default { x : 0 , y : 0 }
2014-06-09 14:40:24 -04:00
* /
/ * *
2020-12-26 17:44:24 -05:00
* A ` Number ` that specifies the stiffness of the constraint , i . e . the rate at which it returns to its resting ` constraint.length ` .
* A value of ` 1 ` means the constraint should be very stiff .
* A value of ` 0.2 ` means the constraint acts like a soft spring .
2014-06-09 14:40:24 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property stiffness
* @ type number
* @ default 1
2014-06-09 14:40:24 -04:00
* /
/ * *
2020-12-26 17:44:24 -05:00
* A ` Number ` that specifies the damping of the constraint ,
* i . e . the amount of resistance applied to each body based on their velocities to limit the amount of oscillation .
* Damping will only be apparent when the constraint also has a very low ` stiffness ` .
* A value of ` 0.1 ` means the constraint will apply heavy damping , resulting in little to no oscillation .
* A value of ` 0 ` means the constraint will apply no damping .
2014-06-09 14:40:24 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property damping
* @ type number
* @ default 0
2014-06-09 14:40:24 -04:00
* /
/ * *
2020-12-26 17:44:24 -05:00
* A ` Number ` that specifies the target resting length of the constraint .
* It is calculated automatically in ` Constraint.create ` from initial positions of the ` constraint.bodyA ` and ` constraint.bodyB ` .
2014-06-09 14:40:24 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property length
* @ type number
2014-06-09 14:40:24 -04:00
* /
2014-07-29 11:26:49 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* An object reserved for storing plugin - specific properties .
2014-07-29 11:26:49 -04:00
*
2020-12-26 17:44:24 -05:00
* @ property plugin
* @ type { }
2014-07-29 11:26:49 -04:00
* /
2014-02-19 09:15:05 -05:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
/* 9 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* The ` Matter.Pair ` module contains methods for creating and manipulating collision pairs .
2014-02-28 20:10:08 -05:00
*
2020-12-26 17:44:24 -05:00
* @ class Pair
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
var Pair = { } ;
module . exports = Pair ;
2021-04-11 12:49:36 -04:00
var Contact = _ _webpack _require _ _ ( 17 ) ;
2020-12-26 17:44:24 -05:00
( function ( ) {
/ * *
* Creates a pair .
* @ method create
* @ param { collision } collision
* @ param { number } timestamp
* @ return { pair } A new pair
* /
Pair . create = function ( collision , timestamp ) {
var bodyA = collision . bodyA ,
bodyB = collision . bodyB ,
parentA = collision . parentA ,
parentB = collision . parentB ;
var pair = {
id : Pair . id ( bodyA , bodyB ) ,
bodyA : bodyA ,
bodyB : bodyB ,
contacts : { } ,
activeContacts : [ ] ,
separation : 0 ,
isActive : true ,
confirmedActive : true ,
isSensor : bodyA . isSensor || bodyB . isSensor ,
timeCreated : timestamp ,
timeUpdated : timestamp ,
inverseMass : parentA . inverseMass + parentB . inverseMass ,
friction : Math . min ( parentA . friction , parentB . friction ) ,
frictionStatic : Math . max ( parentA . frictionStatic , parentB . frictionStatic ) ,
restitution : Math . max ( parentA . restitution , parentB . restitution ) ,
slop : Math . max ( parentA . slop , parentB . slop )
} ;
Pair . update ( pair , collision , timestamp ) ;
return pair ;
} ;
/ * *
* Updates a pair given a collision .
* @ method update
* @ param { pair } pair
* @ param { collision } collision
* @ param { number } timestamp
* /
Pair . update = function ( pair , collision , timestamp ) {
var contacts = pair . contacts ,
supports = collision . supports ,
activeContacts = pair . activeContacts ,
parentA = collision . parentA ,
parentB = collision . parentB ;
pair . collision = collision ;
pair . inverseMass = parentA . inverseMass + parentB . inverseMass ;
pair . friction = Math . min ( parentA . friction , parentB . friction ) ;
pair . frictionStatic = Math . max ( parentA . frictionStatic , parentB . frictionStatic ) ;
pair . restitution = Math . max ( parentA . restitution , parentB . restitution ) ;
pair . slop = Math . max ( parentA . slop , parentB . slop ) ;
activeContacts . length = 0 ;
if ( collision . collided ) {
for ( var i = 0 ; i < supports . length ; i ++ ) {
var support = supports [ i ] ,
contactId = Contact . id ( support ) ,
contact = contacts [ contactId ] ;
if ( contact ) {
activeContacts . push ( contact ) ;
} else {
activeContacts . push ( contacts [ contactId ] = Contact . create ( support ) ) ;
}
}
pair . separation = collision . depth ;
Pair . setActive ( pair , true , timestamp ) ;
} else {
if ( pair . isActive === true )
Pair . setActive ( pair , false , timestamp ) ;
}
} ;
/ * *
* Set a pair as active or inactive .
* @ method setActive
* @ param { pair } pair
* @ param { bool } isActive
* @ param { number } timestamp
* /
Pair . setActive = function ( pair , isActive , timestamp ) {
if ( isActive ) {
pair . isActive = true ;
pair . timeUpdated = timestamp ;
} else {
pair . isActive = false ;
pair . activeContacts . length = 0 ;
}
} ;
/ * *
* Get the id for the given pair .
* @ method id
* @ param { body } bodyA
* @ param { body } bodyB
* @ return { string } Unique pairId
* /
Pair . id = function ( bodyA , bodyB ) {
if ( bodyA . id < bodyB . id ) {
return 'A' + bodyA . id + 'B' + bodyB . id ;
} else {
return 'A' + bodyB . id + 'B' + bodyA . id ;
}
} ;
} ) ( ) ;
/***/ } ) ,
/* 10 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.Axes ` module contains methods for creating and manipulating sets of axes .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ class Axes
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
var Axes = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
module . exports = Axes ;
2020-12-26 17:44:24 -05:00
var Vector = _ _webpack _require _ _ ( 2 ) ;
2021-04-11 12:49:36 -04:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2020-12-26 17:44:24 -05:00
( function ( ) {
2021-04-11 12:49:36 -04:00
/ * *
* Creates a new set of axes from the given vertices .
* @ method fromVertices
* @ param { vertices } vertices
* @ return { axes } A new axes from the given vertices
* /
Axes . fromVertices = function ( vertices ) {
var axes = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// find the unique axes, using edge normal gradients
for ( var i = 0 ; i < vertices . length ; i ++ ) {
var j = ( i + 1 ) % vertices . length ,
normal = Vector . normalise ( {
x : vertices [ j ] . y - vertices [ i ] . y ,
y : vertices [ i ] . x - vertices [ j ] . x
} ) ,
gradient = ( normal . y === 0 ) ? Infinity : ( normal . x / normal . y ) ;
// limit precision
gradient = gradient . toFixed ( 3 ) . toString ( ) ;
axes [ gradient ] = normal ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return Common . values ( axes ) ;
} ;
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Rotates a set of axes by the given angle .
* @ method rotate
* @ param { axes } axes
* @ param { number } angle
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Axes . rotate = function ( axes , angle ) {
if ( angle === 0 )
return ;
var cos = Math . cos ( angle ) ,
sin = Math . sin ( angle ) ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < axes . length ; i ++ ) {
var axis = axes [ i ] ,
xx ;
xx = axis . x * cos - axis . y * sin ;
axis . y = axis . x * sin + axis . y * cos ;
axis . x = xx ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
} ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
} ) ( ) ;
2014-05-01 09:09:06 -04:00
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
/***/ } ) ,
/* 11 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The ` Matter.Bodies ` module contains factory methods for creating rigid body models
* with commonly used body configurations ( such as rectangles , circles and other polygons ) .
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Bodies
* /
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// TODO: true circle bodies
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
var Bodies = { } ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
module . exports = Bodies ;
var Vertices = _ _webpack _require _ _ ( 3 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
var Body = _ _webpack _require _ _ ( 6 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
( function ( ) {
2014-02-19 09:15:05 -05:00
2016-11-02 20:49:53 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new rigid body model with a rectangle hull .
* The options parameter is an object that specifies any properties you wish to override the defaults .
* See the properties section of the ` Matter.Body ` module for detailed information on what you can pass via the ` options ` object .
* @ method rectangle
* @ param { number } x
* @ param { number } y
* @ param { number } width
* @ param { number } height
* @ param { object } [ options ]
* @ return { body } A new rectangle body
2016-11-02 20:49:53 -04:00
* /
2021-04-11 12:49:36 -04:00
Bodies . rectangle = function ( x , y , width , height , options ) {
options = options || { } ;
2016-11-02 20:49:53 -04:00
2021-04-11 12:49:36 -04:00
var rectangle = {
label : 'Rectangle Body' ,
position : { x : x , y : y } ,
vertices : Vertices . fromPath ( 'L 0 0 L ' + width + ' 0 L ' + width + ' ' + height + ' L 0 ' + height )
} ;
if ( options . chamfer ) {
var chamfer = options . chamfer ;
rectangle . vertices = Vertices . chamfer ( rectangle . vertices , chamfer . radius ,
chamfer . quality , chamfer . qualityMin , chamfer . qualityMax ) ;
delete options . chamfer ;
2016-11-02 20:49:53 -04:00
}
2021-04-11 12:49:36 -04:00
return Body . create ( Common . extend ( { } , rectangle , options ) ) ;
2016-11-02 20:49:53 -04:00
} ;
2021-04-11 12:49:36 -04:00
2016-11-02 20:49:53 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new rigid body model with a trapezoid hull .
* The options parameter is an object that specifies any properties you wish to override the defaults .
* See the properties section of the ` Matter.Body ` module for detailed information on what you can pass via the ` options ` object .
* @ method trapezoid
* @ param { number } x
* @ param { number } y
* @ param { number } width
* @ param { number } height
* @ param { number } slope
* @ param { object } [ options ]
* @ return { body } A new trapezoid body
2016-11-02 20:49:53 -04:00
* /
2021-04-11 12:49:36 -04:00
Bodies . trapezoid = function ( x , y , width , height , slope , options ) {
options = options || { } ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
slope *= 0.5 ;
var roof = ( 1 - ( slope * 2 ) ) * width ;
var x1 = width * slope ,
x2 = x1 + roof ,
x3 = x2 + x1 ,
verticesPath ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( slope < 0.5 ) {
verticesPath = 'L 0 0 L ' + x1 + ' ' + ( - height ) + ' L ' + x2 + ' ' + ( - height ) + ' L ' + x3 + ' 0' ;
2020-12-26 17:44:24 -05:00
} else {
2021-04-11 12:49:36 -04:00
verticesPath = 'L 0 0 L ' + x2 + ' ' + ( - height ) + ' L ' + x3 + ' 0' ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
var trapezoid = {
label : 'Trapezoid Body' ,
position : { x : x , y : y } ,
vertices : Vertices . fromPath ( verticesPath )
} ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( options . chamfer ) {
var chamfer = options . chamfer ;
trapezoid . vertices = Vertices . chamfer ( trapezoid . vertices , chamfer . radius ,
chamfer . quality , chamfer . qualityMin , chamfer . qualityMax ) ;
delete options . chamfer ;
2017-11-29 19:16:03 -05:00
}
2021-04-11 12:49:36 -04:00
return Body . create ( Common . extend ( { } , trapezoid , options ) ) ;
2016-09-19 18:53:35 -04:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new rigid body model with a circle hull .
* The options parameter is an object that specifies any properties you wish to override the defaults .
* See the properties section of the ` Matter.Body ` module for detailed information on what you can pass via the ` options ` object .
* @ method circle
* @ param { number } x
* @ param { number } y
* @ param { number } radius
* @ param { object } [ options ]
* @ param { number } [ maxSides ]
* @ return { body } A new circle body
2016-09-19 18:53:35 -04:00
* /
2021-04-11 12:49:36 -04:00
Bodies . circle = function ( x , y , radius , options , maxSides ) {
options = options || { } ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
var circle = {
label : 'Circle Body' ,
circleRadius : radius
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// approximate circles with polygons until true circles implemented in SAT
maxSides = maxSides || 25 ;
var sides = Math . ceil ( Math . max ( 10 , Math . min ( maxSides , radius ) ) ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// optimisation: always use even number of sides (half the number of unique axes)
if ( sides % 2 === 1 )
sides += 1 ;
return Bodies . polygon ( x , y , sides , radius , Common . extend ( { } , circle , options ) ) ;
2014-02-19 09:15:05 -05:00
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new rigid body model with a regular polygon hull with the given number of sides .
* The options parameter is an object that specifies any properties you wish to override the defaults .
* See the properties section of the ` Matter.Body ` module for detailed information on what you can pass via the ` options ` object .
* @ method polygon
* @ param { number } x
* @ param { number } y
* @ param { number } sides
* @ param { number } radius
* @ param { object } [ options ]
* @ return { body } A new regular polygon body
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Bodies . polygon = function ( x , y , sides , radius , options ) {
options = options || { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( sides < 3 )
return Bodies . circle ( x , y , radius , options ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var theta = 2 * Math . PI / sides ,
path = '' ,
offset = theta * 0.5 ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < sides ; i += 1 ) {
var angle = offset + ( i * theta ) ,
xx = Math . cos ( angle ) * radius ,
yy = Math . sin ( angle ) * radius ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
path += 'L ' + xx . toFixed ( 3 ) + ' ' + yy . toFixed ( 3 ) + ' ' ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var polygon = {
label : 'Polygon Body' ,
position : { x : x , y : y } ,
vertices : Vertices . fromPath ( path )
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( options . chamfer ) {
var chamfer = options . chamfer ;
polygon . vertices = Vertices . chamfer ( polygon . vertices , chamfer . radius ,
chamfer . quality , chamfer . qualityMin , chamfer . qualityMax ) ;
delete options . chamfer ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return Body . create ( Common . extend ( { } , polygon , options ) ) ;
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Utility to create a compound body based on set ( s ) of vertices .
*
* _Note : _ To optionally enable automatic concave vertices decomposition the [ poly - decomp ] ( https : //github.com/schteppe/poly-decomp.js)
* package must be first installed and provided see ` Common.setDecomp ` , otherwise the convex hull of each vertex set will be used .
*
* The resulting vertices are reorientated about their centre of mass ,
* and offset such that ` body.position ` corresponds to this point .
*
* The resulting offset may be found if needed by subtracting ` body.bounds ` from the original input bounds .
* To later move the centre of mass see ` Body.setCentre ` .
*
* Note that automatic conconcave decomposition results are not always optimal .
* For best results , simplify the input vertices as much as possible first .
* By default this function applies some addtional simplification to help .
*
* Some outputs may also require further manual processing afterwards to be robust .
* In particular some parts may need to be overlapped to avoid collision gaps .
* Thin parts and sharp points should be avoided or removed where possible .
*
* The options parameter object specifies any ` Matter.Body ` properties you wish to override the defaults .
*
* See the properties section of the ` Matter.Body ` module for detailed information on what you can pass via the ` options ` object .
* @ method fromVertices
* @ param { number } x
* @ param { number } y
* @ param { array } vertexSets One or more arrays of vertex points e . g . ` [[{ x: 0, y: 0 }...], ...] ` .
* @ param { object } [ options ] The body options .
* @ param { bool } [ flagInternal = false ] Optionally marks internal edges with ` isInternal ` .
* @ param { number } [ removeCollinear = 0.01 ] Threshold when simplifying vertices along the same edge .
* @ param { number } [ minimumArea = 10 ] Threshold when removing small parts .
* @ param { number } [ removeDuplicatePoints = 0.01 ] Threshold when simplifying nearby vertices .
* @ return { body }
* /
Bodies . fromVertices = function ( x , y , vertexSets , options , flagInternal , removeCollinear , minimumArea , removeDuplicatePoints ) {
var decomp = Common . getDecomp ( ) ,
canDecomp ,
body ,
parts ,
isConvex ,
isConcave ,
vertices ,
i ,
j ,
k ,
v ,
z ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// check decomp is as expected
canDecomp = Boolean ( decomp && decomp . quickDecomp ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
options = options || { } ;
parts = [ ] ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
flagInternal = typeof flagInternal !== 'undefined' ? flagInternal : false ;
removeCollinear = typeof removeCollinear !== 'undefined' ? removeCollinear : 0.01 ;
minimumArea = typeof minimumArea !== 'undefined' ? minimumArea : 10 ;
removeDuplicatePoints = typeof removeDuplicatePoints !== 'undefined' ? removeDuplicatePoints : 0.01 ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// ensure vertexSets is an array of arrays
if ( ! Common . isArray ( vertexSets [ 0 ] ) ) {
vertexSets = [ vertexSets ] ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( v = 0 ; v < vertexSets . length ; v += 1 ) {
vertices = vertexSets [ v ] ;
isConvex = Vertices . isConvex ( vertices ) ;
isConcave = ! isConvex ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( isConcave && ! canDecomp ) {
Common . warnOnce (
'Bodies.fromVertices: Install the \'poly-decomp\' library and use Common.setDecomp or provide \'decomp\' as a global to decompose concave vertices.'
) ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( isConvex || ! canDecomp ) {
if ( isConvex ) {
vertices = Vertices . clockwiseSort ( vertices ) ;
} else {
// fallback to convex hull when decomposition is not possible
vertices = Vertices . hull ( vertices ) ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
parts . push ( {
position : { x : x , y : y } ,
vertices : vertices
} ) ;
} else {
// initialise a decomposition
var concave = vertices . map ( function ( vertex ) {
return [ vertex . x , vertex . y ] ;
} ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// vertices are concave and simple, we can decompose into parts
decomp . makeCCW ( concave ) ;
if ( removeCollinear !== false )
decomp . removeCollinearPoints ( concave , removeCollinear ) ;
if ( removeDuplicatePoints !== false && decomp . removeDuplicatePoints )
decomp . removeDuplicatePoints ( concave , removeDuplicatePoints ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// use the quick decomposition algorithm (Bayazit)
var decomposed = decomp . quickDecomp ( concave ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// for each decomposed chunk
for ( i = 0 ; i < decomposed . length ; i ++ ) {
var chunk = decomposed [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// convert vertices into the correct structure
var chunkVertices = chunk . map ( function ( vertices ) {
return {
x : vertices [ 0 ] ,
y : vertices [ 1 ]
} ;
} ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// skip small chunks
if ( minimumArea > 0 && Vertices . area ( chunkVertices ) < minimumArea )
continue ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
// create a compound part
parts . push ( {
position : Vertices . centre ( chunkVertices ) ,
vertices : chunkVertices
} ) ;
}
}
2014-03-22 13:51:49 -04:00
}
2021-04-11 12:49:36 -04:00
// create body parts
for ( i = 0 ; i < parts . length ; i ++ ) {
parts [ i ] = Body . create ( Common . extend ( parts [ i ] , options ) ) ;
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
// flag internal edges (coincident part edges)
if ( flagInternal ) {
var coincident _max _dist = 5 ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
for ( i = 0 ; i < parts . length ; i ++ ) {
var partA = parts [ i ] ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( j = i + 1 ; j < parts . length ; j ++ ) {
var partB = parts [ j ] ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( Bounds . overlaps ( partA . bounds , partB . bounds ) ) {
var pav = partA . vertices ,
pbv = partB . vertices ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// iterate vertices of both parts
for ( k = 0 ; k < partA . vertices . length ; k ++ ) {
for ( z = 0 ; z < partB . vertices . length ; z ++ ) {
// find distances between the vertices
var da = Vector . magnitudeSquared ( Vector . sub ( pav [ ( k + 1 ) % pav . length ] , pbv [ z ] ) ) ,
db = Vector . magnitudeSquared ( Vector . sub ( pav [ k ] , pbv [ ( z + 1 ) % pbv . length ] ) ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// if both vertices are very close, consider the edge concident (internal)
if ( da < coincident _max _dist && db < coincident _max _dist ) {
pav [ k ] . isInternal = true ;
pbv [ z ] . isInternal = true ;
}
}
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
}
}
2020-12-26 17:44:24 -05:00
}
2016-09-19 18:53:35 -04:00
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
if ( parts . length > 1 ) {
// create the parent body to be returned, that contains generated compound parts
body = Body . create ( Common . extend ( { parts : parts . slice ( 0 ) } , options ) ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// offset such that body.position is at the centre off mass
Body . setPosition ( body , { x : x , y : y } ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return body ;
} else {
return parts [ 0 ] ;
2014-03-22 13:51:49 -04:00
}
} ;
2021-04-11 12:49:36 -04:00
} ) ( ) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
/***/ } ) ,
/* 12 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The ` Matter.Mouse ` module contains methods for creating and manipulating mouse inputs .
*
* @ class Mouse
* /
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
var Mouse = { } ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
module . exports = Mouse ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
( function ( ) {
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Creates a mouse input .
* @ method create
* @ param { HTMLElement } element
* @ return { mouse } A new mouse
* /
Mouse . create = function ( element ) {
var mouse = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( ! element ) {
Common . log ( 'Mouse.create: element was undefined, defaulting to document.body' , 'warn' ) ;
}
mouse . element = element || document . body ;
mouse . absolute = { x : 0 , y : 0 } ;
mouse . position = { x : 0 , y : 0 } ;
mouse . mousedownPosition = { x : 0 , y : 0 } ;
mouse . mouseupPosition = { x : 0 , y : 0 } ;
mouse . offset = { x : 0 , y : 0 } ;
mouse . scale = { x : 1 , y : 1 } ;
mouse . wheelDelta = 0 ;
mouse . button = - 1 ;
mouse . pixelRatio = parseInt ( mouse . element . getAttribute ( 'data-pixel-ratio' ) , 10 ) || 1 ;
mouse . sourceEvents = {
mousemove : null ,
mousedown : null ,
mouseup : null ,
mousewheel : null
} ;
mouse . mousemove = function ( event ) {
var position = Mouse . _getRelativeMousePosition ( event , mouse . element , mouse . pixelRatio ) ,
touches = event . changedTouches ;
if ( touches ) {
mouse . button = 0 ;
event . preventDefault ( ) ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
mouse . absolute . x = position . x ;
mouse . absolute . y = position . y ;
mouse . position . x = mouse . absolute . x * mouse . scale . x + mouse . offset . x ;
mouse . position . y = mouse . absolute . y * mouse . scale . y + mouse . offset . y ;
mouse . sourceEvents . mousemove = event ;
} ;
mouse . mousedown = function ( event ) {
var position = Mouse . _getRelativeMousePosition ( event , mouse . element , mouse . pixelRatio ) ,
touches = event . changedTouches ;
if ( touches ) {
mouse . button = 0 ;
event . preventDefault ( ) ;
} else {
mouse . button = event . button ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
mouse . absolute . x = position . x ;
mouse . absolute . y = position . y ;
mouse . position . x = mouse . absolute . x * mouse . scale . x + mouse . offset . x ;
mouse . position . y = mouse . absolute . y * mouse . scale . y + mouse . offset . y ;
mouse . mousedownPosition . x = mouse . position . x ;
mouse . mousedownPosition . y = mouse . position . y ;
mouse . sourceEvents . mousedown = event ;
} ;
mouse . mouseup = function ( event ) {
var position = Mouse . _getRelativeMousePosition ( event , mouse . element , mouse . pixelRatio ) ,
touches = event . changedTouches ;
if ( touches ) {
event . preventDefault ( ) ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
mouse . button = - 1 ;
mouse . absolute . x = position . x ;
mouse . absolute . y = position . y ;
mouse . position . x = mouse . absolute . x * mouse . scale . x + mouse . offset . x ;
mouse . position . y = mouse . absolute . y * mouse . scale . y + mouse . offset . y ;
mouse . mouseupPosition . x = mouse . position . x ;
mouse . mouseupPosition . y = mouse . position . y ;
mouse . sourceEvents . mouseup = event ;
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
mouse . mousewheel = function ( event ) {
mouse . wheelDelta = Math . max ( - 1 , Math . min ( 1 , event . wheelDelta || - event . detail ) ) ;
event . preventDefault ( ) ;
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
Mouse . setElement ( mouse , mouse . element ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return mouse ;
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Sets the element the mouse is bound to ( and relative to ) .
* @ method setElement
* @ param { mouse } mouse
* @ param { HTMLElement } element
* /
Mouse . setElement = function ( mouse , element ) {
mouse . element = element ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
element . addEventListener ( 'mousemove' , mouse . mousemove ) ;
element . addEventListener ( 'mousedown' , mouse . mousedown ) ;
element . addEventListener ( 'mouseup' , mouse . mouseup ) ;
element . addEventListener ( 'mousewheel' , mouse . mousewheel ) ;
element . addEventListener ( 'DOMMouseScroll' , mouse . mousewheel ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
element . addEventListener ( 'touchmove' , mouse . mousemove ) ;
element . addEventListener ( 'touchstart' , mouse . mousedown ) ;
element . addEventListener ( 'touchend' , mouse . mouseup ) ;
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Clears all captured source events .
* @ method clearSourceEvents
* @ param { mouse } mouse
* /
Mouse . clearSourceEvents = function ( mouse ) {
mouse . sourceEvents . mousemove = null ;
mouse . sourceEvents . mousedown = null ;
mouse . sourceEvents . mouseup = null ;
mouse . sourceEvents . mousewheel = null ;
mouse . wheelDelta = 0 ;
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Sets the mouse position offset .
* @ method setOffset
* @ param { mouse } mouse
* @ param { vector } offset
* /
Mouse . setOffset = function ( mouse , offset ) {
mouse . offset . x = offset . x ;
mouse . offset . y = offset . y ;
mouse . position . x = mouse . absolute . x * mouse . scale . x + mouse . offset . x ;
mouse . position . y = mouse . absolute . y * mouse . scale . y + mouse . offset . y ;
2016-09-19 18:53:35 -04:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Sets the mouse position scale .
* @ method setScale
* @ param { mouse } mouse
* @ param { vector } scale
* /
Mouse . setScale = function ( mouse , scale ) {
mouse . scale . x = scale . x ;
mouse . scale . y = scale . y ;
mouse . position . x = mouse . absolute . x * mouse . scale . x + mouse . offset . x ;
mouse . position . y = mouse . absolute . y * mouse . scale . y + mouse . offset . y ;
} ;
/ * *
* Gets the mouse position relative to an element given a screen pixel ratio .
* @ method _getRelativeMousePosition
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ param { } event
* @ param { } element
* @ param { number } pixelRatio
* @ return { }
2016-09-19 18:53:35 -04:00
* /
2021-04-11 12:49:36 -04:00
Mouse . _getRelativeMousePosition = function ( event , element , pixelRatio ) {
var elementBounds = element . getBoundingClientRect ( ) ,
rootNode = ( document . documentElement || document . body . parentNode || document . body ) ,
scrollX = ( window . pageXOffset !== undefined ) ? window . pageXOffset : rootNode . scrollLeft ,
scrollY = ( window . pageYOffset !== undefined ) ? window . pageYOffset : rootNode . scrollTop ,
touches = event . changedTouches ,
x , y ;
if ( touches ) {
x = touches [ 0 ] . pageX - elementBounds . left - scrollX ;
y = touches [ 0 ] . pageY - elementBounds . top - scrollY ;
} else {
x = event . pageX - elementBounds . left - scrollX ;
y = event . pageY - elementBounds . top - scrollY ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
return {
x : x / ( element . clientWidth / ( element . width || element . clientWidth ) * pixelRatio ) ,
y : y / ( element . clientHeight / ( element . height || element . clientHeight ) * pixelRatio )
} ;
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
} ) ( ) ;
2016-09-19 18:53:35 -04:00
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
/***/ } ) ,
/* 13 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The ` Matter.Detector ` module contains methods for detecting collisions given a set of pairs .
*
* @ class Detector
* /
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// TODO: speculative contacts
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
var Detector = { } ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
module . exports = Detector ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
var SAT = _ _webpack _require _ _ ( 14 ) ;
var Pair = _ _webpack _require _ _ ( 9 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
2016-11-02 20:49:53 -04:00
2021-04-11 12:49:36 -04:00
( function ( ) {
2016-11-02 20:49:53 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Finds all collisions given a list of pairs .
* @ method collisions
* @ param { pair [ ] } broadphasePairs
* @ param { engine } engine
* @ return { array } collisions
* /
Detector . collisions = function ( broadphasePairs , engine ) {
var collisions = [ ] ,
pairsTable = engine . pairs . table ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < broadphasePairs . length ; i ++ ) {
var bodyA = broadphasePairs [ i ] [ 0 ] ,
bodyB = broadphasePairs [ i ] [ 1 ] ;
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
if ( ( bodyA . isStatic || bodyA . isSleeping ) && ( bodyB . isStatic || bodyB . isSleeping ) )
continue ;
if ( ! Detector . canCollide ( bodyA . collisionFilter , bodyB . collisionFilter ) )
continue ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// mid phase
if ( Bounds . overlaps ( bodyA . bounds , bodyB . bounds ) ) {
for ( var j = bodyA . parts . length > 1 ? 1 : 0 ; j < bodyA . parts . length ; j ++ ) {
var partA = bodyA . parts [ j ] ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
for ( var k = bodyB . parts . length > 1 ? 1 : 0 ; k < bodyB . parts . length ; k ++ ) {
var partB = bodyB . parts [ k ] ;
if ( ( partA === bodyA && partB === bodyB ) || Bounds . overlaps ( partA . bounds , partB . bounds ) ) {
// find a previous collision we could reuse
var pairId = Pair . id ( partA , partB ) ,
pair = pairsTable [ pairId ] ,
previousCollision ;
if ( pair && pair . isActive ) {
previousCollision = pair . collision ;
} else {
previousCollision = null ;
}
// narrow phase
var collision = SAT . collides ( partA , partB , previousCollision ) ;
if ( collision . collided ) {
collisions . push ( collision ) ;
}
}
2020-12-26 17:44:24 -05:00
}
}
}
}
2021-04-11 12:49:36 -04:00
return collisions ;
2020-12-26 17:44:24 -05:00
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Returns ` true ` if both supplied collision filters will allow a collision to occur .
* See ` body.collisionFilter ` for more information .
* @ method canCollide
* @ param { } filterA
* @ param { } filterB
* @ return { bool } ` true ` if collision can occur
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Detector . canCollide = function ( filterA , filterB ) {
if ( filterA . group === filterB . group && filterA . group !== 0 )
return filterA . group > 0 ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
return ( filterA . mask & filterB . category ) !== 0 && ( filterB . mask & filterA . category ) !== 0 ;
} ;
2016-05-01 18:54:13 -04:00
2021-04-11 12:49:36 -04:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/***/ } ) ,
/* 14 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2015-07-05 10:57:31 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The ` Matter.SAT ` module contains methods for detecting collisions using the Separating Axis Theorem .
*
* @ class SAT
* /
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// TODO: true circles and curves
2015-06-29 15:58:24 -04:00
2021-04-11 12:49:36 -04:00
var SAT = { } ;
2015-06-29 15:58:24 -04:00
2021-04-11 12:49:36 -04:00
module . exports = SAT ;
2016-05-01 18:54:13 -04:00
2021-04-11 12:49:36 -04:00
var Vertices = _ _webpack _require _ _ ( 3 ) ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
( function ( ) {
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Detect collision between two bodies using the Separating Axis Theorem .
* @ method collides
* @ param { body } bodyA
* @ param { body } bodyB
* @ param { collision } previousCollision
* @ return { collision } collision
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
SAT . collides = function ( bodyA , bodyB , previousCollision ) {
var overlapAB ,
overlapBA ,
minOverlap ,
collision ,
canReusePrevCol = false ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( previousCollision ) {
// estimate total motion
var parentA = bodyA . parent ,
parentB = bodyB . parent ,
motion = parentA . speed * parentA . speed + parentA . angularSpeed * parentA . angularSpeed
+ parentB . speed * parentB . speed + parentB . angularSpeed * parentB . angularSpeed ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// we may be able to (partially) reuse collision result
// but only safe if collision was resting
canReusePrevCol = previousCollision && previousCollision . collided && motion < 0.2 ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
// reuse collision object
collision = previousCollision ;
} else {
collision = { collided : false , bodyA : bodyA , bodyB : bodyB } ;
}
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
if ( previousCollision && canReusePrevCol ) {
// if we can reuse the collision result
// we only need to test the previously found axis
var axisBodyA = collision . axisBody ,
axisBodyB = axisBodyA === bodyA ? bodyB : bodyA ,
axes = [ axisBodyA . axes [ previousCollision . axisNumber ] ] ;
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
minOverlap = SAT . _overlapAxes ( axisBodyA . vertices , axisBodyB . vertices , axes ) ;
collision . reused = true ;
if ( minOverlap . overlap <= 0 ) {
collision . collided = false ;
return collision ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
} else {
// if we can't reuse a result, perform a full SAT test
2015-12-05 11:47:50 -05:00
2021-04-11 12:49:36 -04:00
overlapAB = SAT . _overlapAxes ( bodyA . vertices , bodyB . vertices , bodyA . axes ) ;
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
if ( overlapAB . overlap <= 0 ) {
collision . collided = false ;
return collision ;
}
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
overlapBA = SAT . _overlapAxes ( bodyB . vertices , bodyA . vertices , bodyB . axes ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( overlapBA . overlap <= 0 ) {
collision . collided = false ;
return collision ;
2020-12-26 17:44:24 -05:00
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( overlapAB . overlap < overlapBA . overlap ) {
minOverlap = overlapAB ;
collision . axisBody = bodyA ;
} else {
minOverlap = overlapBA ;
collision . axisBody = bodyB ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
// important for reuse later
collision . axisNumber = minOverlap . axisNumber ;
2014-02-19 09:15:05 -05:00
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
collision . bodyA = bodyA . id < bodyB . id ? bodyA : bodyB ;
collision . bodyB = bodyA . id < bodyB . id ? bodyB : bodyA ;
collision . collided = true ;
collision . depth = minOverlap . overlap ;
collision . parentA = collision . bodyA . parent ;
collision . parentB = collision . bodyB . parent ;
bodyA = collision . bodyA ;
bodyB = collision . bodyB ;
// ensure normal is facing away from bodyA
if ( Vector . dot ( minOverlap . axis , Vector . sub ( bodyB . position , bodyA . position ) ) < 0 ) {
collision . normal = {
x : minOverlap . axis . x ,
y : minOverlap . axis . y
} ;
2020-12-26 17:44:24 -05:00
} else {
2021-04-11 12:49:36 -04:00
collision . normal = {
x : - minOverlap . axis . x ,
y : - minOverlap . axis . y
} ;
2016-04-09 15:12:34 -04:00
}
2021-04-11 12:49:36 -04:00
collision . tangent = Vector . perp ( collision . normal ) ;
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
collision . penetration = collision . penetration || { } ;
collision . penetration . x = collision . normal . x * collision . depth ;
collision . penetration . y = collision . normal . y * collision . depth ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// find support points, there is always either exactly one or two
var verticesB = SAT . _findSupports ( bodyA , bodyB , collision . normal ) ,
supports = [ ] ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// find the supports from bodyB that are inside bodyA
if ( Vertices . contains ( bodyA . vertices , verticesB [ 0 ] ) )
supports . push ( verticesB [ 0 ] ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( Vertices . contains ( bodyA . vertices , verticesB [ 1 ] ) )
supports . push ( verticesB [ 1 ] ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// find the supports from bodyA that are inside bodyB
if ( supports . length < 2 ) {
var verticesA = SAT . _findSupports ( bodyB , bodyA , Vector . neg ( collision . normal ) ) ;
if ( Vertices . contains ( bodyB . vertices , verticesA [ 0 ] ) )
supports . push ( verticesA [ 0 ] ) ;
2017-05-03 19:40:04 -04:00
2021-04-11 12:49:36 -04:00
if ( supports . length < 2 && Vertices . contains ( bodyB . vertices , verticesA [ 1 ] ) )
supports . push ( verticesA [ 1 ] ) ;
2015-05-20 15:38:41 -04:00
}
2021-04-11 12:49:36 -04:00
// account for the edge case of overlapping but no vertex containment
if ( supports . length < 1 )
supports = [ verticesB [ 0 ] ] ;
collision . supports = supports ;
return collision ;
2014-02-19 09:15:05 -05:00
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Find the overlap between two sets of vertices .
* @ method _overlapAxes
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ param { } verticesA
* @ param { } verticesB
* @ param { } axes
* @ return result
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
SAT . _overlapAxes = function ( verticesA , verticesB , axes ) {
var projectionA = Vector . _temp [ 0 ] ,
projectionB = Vector . _temp [ 1 ] ,
result = { overlap : Number . MAX _VALUE } ,
overlap ,
axis ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < axes . length ; i ++ ) {
axis = axes [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
SAT . _projectToAxis ( projectionA , verticesA , axis ) ;
SAT . _projectToAxis ( projectionB , verticesB , axis ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
overlap = Math . min ( projectionA . max - projectionB . min , projectionB . max - projectionA . min ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( overlap <= 0 ) {
result . overlap = overlap ;
return result ;
2014-02-19 09:15:05 -05:00
}
2015-01-20 19:15:04 -05:00
2021-04-11 12:49:36 -04:00
if ( overlap < result . overlap ) {
result . overlap = overlap ;
result . axis = axis ;
result . axisNumber = i ;
2020-12-26 17:44:24 -05:00
}
2015-01-20 19:15:04 -05:00
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return result ;
2015-01-20 19:15:04 -05:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Projects vertices on an axis and returns an interval .
* @ method _projectToAxis
2015-01-20 19:15:04 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ param { } projection
* @ param { } vertices
* @ param { } axis
2015-01-20 19:15:04 -05:00
* /
2021-04-11 12:49:36 -04:00
SAT . _projectToAxis = function ( projection , vertices , axis ) {
var min = Vector . dot ( vertices [ 0 ] , axis ) ,
max = min ;
2015-01-20 19:15:04 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 1 ; i < vertices . length ; i += 1 ) {
var dot = Vector . dot ( vertices [ i ] , axis ) ;
2015-01-20 19:15:04 -05:00
2021-04-11 12:49:36 -04:00
if ( dot > max ) {
max = dot ;
} else if ( dot < min ) {
min = dot ;
}
2015-01-20 19:15:04 -05:00
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
projection . min = min ;
projection . max = max ;
2015-01-20 19:15:04 -05:00
} ;
2021-04-11 12:49:36 -04:00
2015-01-20 19:15:04 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Finds supporting vertices given two bodies along a given direction using hill - climbing .
* @ method _findSupports
2015-01-20 19:15:04 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ param { } bodyA
* @ param { } bodyB
* @ param { } normal
* @ return [ vector ]
2015-01-20 19:15:04 -05:00
* /
2021-04-11 12:49:36 -04:00
SAT . _findSupports = function ( bodyA , bodyB , normal ) {
var nearestDistance = Number . MAX _VALUE ,
vertexToBody = Vector . _temp [ 0 ] ,
vertices = bodyB . vertices ,
bodyAPosition = bodyA . position ,
distance ,
vertex ,
vertexA ,
vertexB ;
2015-01-20 19:15:04 -05:00
2021-04-11 12:49:36 -04:00
// find closest vertex on bodyB
for ( var i = 0 ; i < vertices . length ; i ++ ) {
vertex = vertices [ i ] ;
vertexToBody . x = vertex . x - bodyAPosition . x ;
vertexToBody . y = vertex . y - bodyAPosition . y ;
distance = - Vector . dot ( normal , vertexToBody ) ;
2015-01-20 19:15:04 -05:00
2021-04-11 12:49:36 -04:00
if ( distance < nearestDistance ) {
nearestDistance = distance ;
vertexA = vertex ;
2020-12-26 17:44:24 -05:00
}
2015-01-20 19:15:04 -05:00
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
// find next closest vertex using the two connected to it
var prevIndex = vertexA . index - 1 >= 0 ? vertexA . index - 1 : vertices . length - 1 ;
vertex = vertices [ prevIndex ] ;
vertexToBody . x = vertex . x - bodyAPosition . x ;
vertexToBody . y = vertex . y - bodyAPosition . y ;
nearestDistance = - Vector . dot ( normal , vertexToBody ) ;
vertexB = vertex ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
var nextIndex = ( vertexA . index + 1 ) % vertices . length ;
vertex = vertices [ nextIndex ] ;
vertexToBody . x = vertex . x - bodyAPosition . x ;
vertexToBody . y = vertex . y - bodyAPosition . y ;
distance = - Vector . dot ( normal , vertexToBody ) ;
if ( distance < nearestDistance ) {
vertexB = vertex ;
}
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
return [ vertexA , vertexB ] ;
} ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
/***/ } ) ,
/* 15 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The ` Matter.Plugin ` module contains functions for registering and installing plugins on modules .
*
* @ class Plugin
* /
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
var Plugin = { } ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
module . exports = Plugin ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
( function ( ) {
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
Plugin . _registry = { } ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Registers a plugin object so it can be resolved later by name .
* @ method register
* @ param plugin { } The plugin to register .
* @ return { object } The plugin .
* /
Plugin . register = function ( plugin ) {
if ( ! Plugin . isPlugin ( plugin ) ) {
Common . warn ( 'Plugin.register:' , Plugin . toString ( plugin ) , 'does not implement all required fields.' ) ;
2020-12-26 17:44:24 -05:00
}
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
if ( plugin . name in Plugin . _registry ) {
var registered = Plugin . _registry [ plugin . name ] ,
pluginVersion = Plugin . versionParse ( plugin . version ) . number ,
registeredVersion = Plugin . versionParse ( registered . version ) . number ;
if ( pluginVersion > registeredVersion ) {
Common . warn ( 'Plugin.register:' , Plugin . toString ( registered ) , 'was upgraded to' , Plugin . toString ( plugin ) ) ;
Plugin . _registry [ plugin . name ] = plugin ;
} else if ( pluginVersion < registeredVersion ) {
Common . warn ( 'Plugin.register:' , Plugin . toString ( registered ) , 'can not be downgraded to' , Plugin . toString ( plugin ) ) ;
} else if ( plugin !== registered ) {
Common . warn ( 'Plugin.register:' , Plugin . toString ( plugin ) , 'is already registered to different plugin object' ) ;
}
2020-12-26 17:44:24 -05:00
} else {
2021-04-11 12:49:36 -04:00
Plugin . _registry [ plugin . name ] = plugin ;
2020-12-26 17:44:24 -05:00
}
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
return plugin ;
2020-12-26 17:44:24 -05:00
} ;
2014-06-09 14:40:24 -04:00
2014-07-29 11:26:49 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Resolves a dependency to a plugin object from the registry if it exists .
* The ` dependency ` may contain a version , but only the name matters when resolving .
* @ method resolve
* @ param dependency { string } The dependency .
* @ return { object } The plugin if resolved , otherwise ` undefined ` .
2014-07-29 11:26:49 -04:00
* /
2021-04-11 12:49:36 -04:00
Plugin . resolve = function ( dependency ) {
return Plugin . _registry [ Plugin . dependencyParse ( dependency ) . name ] ;
2014-03-11 06:29:14 -04:00
} ;
2014-03-24 16:11:42 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Returns a pretty printed plugin name and version .
* @ method toString
* @ param plugin { } The plugin .
* @ return { string } Pretty printed plugin name and version .
2014-03-24 16:11:42 -04:00
* /
2021-04-11 12:49:36 -04:00
Plugin . toString = function ( plugin ) {
return typeof plugin === 'string' ? plugin : ( plugin . name || 'anonymous' ) + '@' + ( plugin . version || plugin . range || '0.0.0' ) ;
} ;
2014-03-24 16:11:42 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Returns ` true ` if the object meets the minimum standard to be considered a plugin .
* This means it must define the following properties :
* - ` name `
* - ` version `
* - ` install `
* @ method isPlugin
* @ param obj { } The obj to test .
* @ return { boolean } ` true ` if the object can be considered a plugin otherwise ` false ` .
* /
Plugin . isPlugin = function ( obj ) {
return obj && obj . name && obj . version && obj . install ;
} ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Returns ` true ` if a plugin with the given ` name ` been installed on ` module ` .
* @ method isUsed
* @ param module { } The module .
* @ param name { string } The plugin name .
* @ return { boolean } ` true ` if a plugin with the given ` name ` been installed on ` module ` , otherwise ` false ` .
* /
Plugin . isUsed = function ( module , name ) {
return module . used . indexOf ( name ) > - 1 ;
2020-12-26 17:44:24 -05:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Returns ` true ` if ` plugin.for ` is applicable to ` module ` by comparing against ` module.name ` and ` module.version ` .
* If ` plugin.for ` is not specified then it is assumed to be applicable .
* The value of ` plugin.for ` is a string of the format ` 'module-name' ` or ` 'module-name@version' ` .
* @ method isFor
* @ param plugin { } The plugin .
* @ param module { } The module .
* @ return { boolean } ` true ` if ` plugin.for ` is applicable to ` module ` , otherwise ` false ` .
2014-03-11 06:29:14 -04:00
* /
2021-04-11 12:49:36 -04:00
Plugin . isFor = function ( plugin , module ) {
var parsed = plugin . for && Plugin . dependencyParse ( plugin . for ) ;
return ! plugin . for || ( module . name === parsed . name && Plugin . versionSatisfies ( module . version , parsed . range ) ) ;
} ;
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Installs the plugins by calling ` plugin.install ` on each plugin specified in ` plugins ` if passed , otherwise ` module.uses ` .
* For installing plugins on ` Matter ` see the convenience function ` Matter.use ` .
* Plugins may be specified either by their name or a reference to the plugin object .
* Plugins themselves may specify further dependencies , but each plugin is installed only once .
* Order is important , a topological sort is performed to find the best resulting order of installation .
* This sorting attempts to satisfy every dependency ' s requested ordering , but may not be exact in all cases .
* This function logs the resulting status of each dependency in the console , along with any warnings .
* - A green tick ✅ indicates a dependency was resolved and installed .
* - An orange diamond 🔶 indicates a dependency was resolved but a warning was thrown for it or one if its dependencies .
* - A red cross ❌ indicates a dependency could not be resolved .
* Avoid calling this function multiple times on the same module unless you intend to manually control installation order .
* @ method use
* @ param module { } The module install plugins on .
* @ param [ plugins = module . uses ] { } The plugins to install on module ( optional , defaults to ` module.uses ` ) .
* /
Plugin . use = function ( module , plugins ) {
module . uses = ( module . uses || [ ] ) . concat ( plugins || [ ] ) ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
if ( module . uses . length === 0 ) {
Common . warn ( 'Plugin.use:' , Plugin . toString ( module ) , 'does not specify any dependencies to install.' ) ;
return ;
2020-12-26 17:44:24 -05:00
}
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
var dependencies = Plugin . dependencies ( module ) ,
sortedDependencies = Common . topologicalSort ( dependencies ) ,
status = [ ] ;
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < sortedDependencies . length ; i += 1 ) {
if ( sortedDependencies [ i ] === module . name ) {
continue ;
}
2016-01-16 17:43:32 -05:00
2021-04-11 12:49:36 -04:00
var plugin = Plugin . resolve ( sortedDependencies [ i ] ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( ! plugin ) {
status . push ( '❌ ' + sortedDependencies [ i ] ) ;
continue ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( Plugin . isUsed ( module , plugin . name ) ) {
continue ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( ! Plugin . isFor ( plugin , module ) ) {
Common . warn ( 'Plugin.use:' , Plugin . toString ( plugin ) , 'is for' , plugin . for , 'but installed on' , Plugin . toString ( module ) + '.' ) ;
plugin . _warned = true ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( plugin . install ) {
plugin . install ( module ) ;
} else {
Common . warn ( 'Plugin.use:' , Plugin . toString ( plugin ) , 'does not specify an install function.' ) ;
plugin . _warned = true ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( plugin . _warned ) {
status . push ( '🔶 ' + Plugin . toString ( plugin ) ) ;
delete plugin . _warned ;
} else {
status . push ( '✅ ' + Plugin . toString ( plugin ) ) ;
2020-12-26 17:44:24 -05:00
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
module . used . push ( plugin . name ) ;
2020-12-26 17:44:24 -05:00
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( status . length > 0 ) {
Common . info ( status . join ( ' ' ) ) ;
2020-12-26 17:44:24 -05:00
}
} ;
2016-09-19 18:53:35 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Recursively finds all of a module ' s dependencies and returns a flat dependency graph .
* @ method dependencies
* @ param module { } The module .
* @ return { object } A dependency graph .
2016-09-19 18:53:35 -04:00
* /
2021-04-11 12:49:36 -04:00
Plugin . dependencies = function ( module , tracked ) {
var parsedBase = Plugin . dependencyParse ( module ) ,
name = parsedBase . name ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
tracked = tracked || { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( name in tracked ) {
return ;
}
2016-11-02 20:49:53 -04:00
2021-04-11 12:49:36 -04:00
module = Plugin . resolve ( module ) || module ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
tracked [ name ] = Common . map ( module . uses || [ ] , function ( dependency ) {
if ( Plugin . isPlugin ( dependency ) ) {
Plugin . register ( dependency ) ;
}
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
var parsed = Plugin . dependencyParse ( dependency ) ,
resolved = Plugin . resolve ( dependency ) ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
if ( resolved && ! Plugin . versionSatisfies ( resolved . version , parsed . range ) ) {
Common . warn (
'Plugin.dependencies:' , Plugin . toString ( resolved ) , 'does not satisfy' ,
Plugin . toString ( parsed ) , 'used by' , Plugin . toString ( parsedBase ) + '.'
) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
resolved . _warned = true ;
module . _warned = true ;
} else if ( ! resolved ) {
Common . warn (
'Plugin.dependencies:' , Plugin . toString ( dependency ) , 'used by' ,
Plugin . toString ( parsedBase ) , 'could not be resolved.'
) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
module . _warned = true ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
return parsed . name ;
} ) ;
for ( var i = 0 ; i < tracked [ name ] . length ; i += 1 ) {
Plugin . dependencies ( tracked [ name ] [ i ] , tracked ) ;
}
return tracked ;
2020-12-26 17:44:24 -05:00
} ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Parses a dependency string into its components .
* The ` dependency ` is a string of the format ` 'module-name' ` or ` 'module-name@version' ` .
* See documentation for ` Plugin.versionParse ` for a description of the format .
* This function can also handle dependencies that are already resolved ( e . g . a module object ) .
* @ method dependencyParse
* @ param dependency { string } The dependency of the format ` 'module-name' ` or ` 'module-name@version' ` .
* @ return { object } The dependency parsed into its components .
* /
Plugin . dependencyParse = function ( dependency ) {
if ( Common . isString ( dependency ) ) {
var pattern = /^[\w-]+(@(\*|[\^~]?\d+\.\d+\.\d+(-[0-9A-Za-z-]+)?))?$/ ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( ! pattern . test ( dependency ) ) {
Common . warn ( 'Plugin.dependencyParse:' , dependency , 'is not a valid dependency string.' ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
return {
name : dependency . split ( '@' ) [ 0 ] ,
range : dependency . split ( '@' ) [ 1 ] || '*'
} ;
}
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
return {
name : dependency . name ,
range : dependency . range || dependency . version
} ;
} ;
2014-05-05 14:32:51 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Parses a version string into its components .
* Versions are strictly of the format ` x.y.z ` ( as in [ semver ] ( http : //semver.org/)).
* Versions may optionally have a prerelease tag in the format ` x.y.z-alpha ` .
* Ranges are a strict subset of [ npm ranges ] ( https : //docs.npmjs.com/misc/semver#advanced-range-syntax).
* Only the following range types are supported :
* - Tilde ranges e . g . ` ~1.2.3 `
* - Caret ranges e . g . ` ^1.2.3 `
* - Greater than ranges e . g . ` >1.2.3 `
* - Greater than or equal ranges e . g . ` >=1.2.3 `
* - Exact version e . g . ` 1.2.3 `
* - Any version ` * `
* @ method versionParse
* @ param range { string } The version string .
* @ return { object } The version range parsed into its components .
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Plugin . versionParse = function ( range ) {
var pattern = /^(\*)|(\^|~|>=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-]+)?$/ ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( ! pattern . test ( range ) ) {
Common . warn ( 'Plugin.versionParse:' , range , 'is not a valid version or range.' ) ;
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
var parts = pattern . exec ( range ) ;
var major = Number ( parts [ 4 ] ) ;
var minor = Number ( parts [ 5 ] ) ;
var patch = Number ( parts [ 6 ] ) ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
return {
isRange : Boolean ( parts [ 1 ] || parts [ 2 ] ) ,
version : parts [ 3 ] ,
range : range ,
operator : parts [ 1 ] || parts [ 2 ] || '' ,
major : major ,
minor : minor ,
patch : patch ,
parts : [ major , minor , patch ] ,
prerelease : parts [ 7 ] ,
number : major * 1e8 + minor * 1e4 + patch
} ;
} ;
2014-05-05 14:32:51 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Returns ` true ` if ` version ` satisfies the given ` range ` .
* See documentation for ` Plugin.versionParse ` for a description of the format .
* If a version or range is not specified , then any version ( ` * ` ) is assumed to satisfy .
* @ method versionSatisfies
* @ param version { string } The version string .
* @ param range { string } The range string .
* @ return { boolean } ` true ` if ` version ` satisfies ` range ` , otherwise ` false ` .
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Plugin . versionSatisfies = function ( version , range ) {
range = range || '*' ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
var r = Plugin . versionParse ( range ) ,
v = Plugin . versionParse ( version ) ;
2014-05-05 14:32:51 -04:00
2021-04-11 12:49:36 -04:00
if ( r . isRange ) {
if ( r . operator === '*' || version === '*' ) {
return true ;
}
2014-05-05 14:32:51 -04:00
2021-04-11 12:49:36 -04:00
if ( r . operator === '>' ) {
return v . number > r . number ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( r . operator === '>=' ) {
return v . number >= r . number ;
}
2014-12-28 13:37:43 -05:00
2021-04-11 12:49:36 -04:00
if ( r . operator === '~' ) {
return v . major === r . major && v . minor === r . minor && v . patch >= r . patch ;
}
if ( r . operator === '^' ) {
if ( r . major > 0 ) {
return v . major === r . major && v . number >= r . number ;
}
if ( r . minor > 0 ) {
return v . minor === r . minor && v . patch >= r . patch ;
}
return v . patch === r . patch ;
}
}
return version === range || version === '*' ;
} ;
2016-09-19 18:53:35 -04:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 16 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2016-09-19 18:53:35 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.Render ` module is a simple canvas based renderer for visualising instances of ` Matter.Engine ` .
* It is intended for development and debugging purposes , but may also be suitable for simple games .
* It includes a number of drawing options including wireframe , vector with support for sprites and viewports .
2016-09-19 18:53:35 -04:00
*
2021-04-11 12:49:36 -04:00
* @ class Render
2016-09-19 18:53:35 -04:00
* /
2021-04-11 12:49:36 -04:00
var Render = { } ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
module . exports = Render ;
2016-09-19 18:53:35 -04:00
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2021-04-11 12:49:36 -04:00
var Composite = _ _webpack _require _ _ ( 5 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
var Events = _ _webpack _require _ _ ( 4 ) ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
var Mouse = _ _webpack _require _ _ ( 12 ) ;
2016-09-19 18:53:35 -04:00
( function ( ) {
2021-04-11 12:49:36 -04:00
var _requestAnimationFrame ,
_cancelAnimationFrame ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( typeof window !== 'undefined' ) {
_requestAnimationFrame = window . requestAnimationFrame || window . webkitRequestAnimationFrame
|| window . mozRequestAnimationFrame || window . msRequestAnimationFrame
|| function ( callback ) { window . setTimeout ( function ( ) { callback ( Common . now ( ) ) ; } , 1000 / 60 ) ; } ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
_cancelAnimationFrame = window . cancelAnimationFrame || window . mozCancelAnimationFrame
|| window . webkitCancelAnimationFrame || window . msCancelAnimationFrame ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
Render . _goodFps = 30 ;
Render . _goodDelta = 1000 / 60 ;
2016-09-19 18:53:35 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new renderer . The options parameter is an object that specifies any properties you wish to override the defaults .
* All properties have default values , and many are pre - calculated automatically based on other properties .
* See the properties section below for detailed information on what you can pass via the ` options ` object .
* @ method create
* @ param { object } [ options ]
* @ return { render } A new renderer
2016-09-19 18:53:35 -04:00
* /
2021-04-11 12:49:36 -04:00
Render . create = function ( options ) {
var defaults = {
controller : Render ,
engine : null ,
element : null ,
canvas : null ,
mouse : null ,
frameRequestId : null ,
timing : {
historySize : 60 ,
delta : 0 ,
deltaHistory : [ ] ,
lastTime : 0 ,
lastTimestamp : 0 ,
lastElapsed : 0 ,
timestampElapsed : 0 ,
timestampElapsedHistory : [ ] ,
engineDeltaHistory : [ ] ,
engineElapsedHistory : [ ] ,
elapsedHistory : [ ]
} ,
options : {
width : 800 ,
height : 600 ,
pixelRatio : 1 ,
background : '#14151f' ,
wireframeBackground : '#14151f' ,
hasBounds : ! ! options . bounds ,
enabled : true ,
wireframes : true ,
showSleeping : true ,
showDebug : false ,
showStats : false ,
showPerformance : false ,
showBroadphase : false ,
showBounds : false ,
showVelocity : false ,
showCollisions : false ,
showSeparations : false ,
showAxes : false ,
showPositions : false ,
showAngleIndicator : false ,
showIds : false ,
showVertexNumbers : false ,
showConvexHulls : false ,
showInternalEdges : false ,
showMousePosition : false
}
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
var render = Common . extend ( defaults , options ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( render . canvas ) {
render . canvas . width = render . options . width || render . canvas . width ;
render . canvas . height = render . options . height || render . canvas . height ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
render . mouse = options . mouse ;
render . engine = options . engine ;
render . canvas = render . canvas || _createCanvas ( render . options . width , render . options . height ) ;
render . context = render . canvas . getContext ( '2d' ) ;
render . textures = { } ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
render . bounds = render . bounds || {
min : {
x : 0 ,
y : 0
} ,
max : {
x : render . canvas . width ,
y : render . canvas . height
}
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( render . options . pixelRatio !== 1 ) {
Render . setPixelRatio ( render , render . options . pixelRatio ) ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( Common . isElement ( render . element ) ) {
render . element . appendChild ( render . canvas ) ;
} else if ( ! render . canvas . parentNode ) {
Common . log ( 'Render.create: options.element was undefined, render.canvas was created but not appended' , 'warn' ) ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
return render ;
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Continuously updates the render canvas on the ` requestAnimationFrame ` event .
* @ method run
* @ param { render } render
* /
Render . run = function ( render ) {
( function loop ( time ) {
render . frameRequestId = _requestAnimationFrame ( loop ) ;
_updateTiming ( render , time ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
Render . world ( render , time ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( render . options . showStats || render . options . showDebug ) {
Render . stats ( render , render . context , time ) ;
2016-11-02 20:49:53 -04:00
}
2021-04-11 12:49:36 -04:00
if ( render . options . showPerformance || render . options . showDebug ) {
Render . performance ( render , render . context , time ) ;
}
} ) ( ) ;
2020-12-26 17:44:24 -05:00
} ;
2016-09-19 18:53:35 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Ends execution of ` Render.run ` on the given ` render ` , by canceling the animation frame request event loop .
* @ method stop
* @ param { render } render
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . stop = function ( render ) {
_cancelAnimationFrame ( render . frameRequestId ) ;
2020-12-26 17:44:24 -05:00
} ;
2016-09-19 18:53:35 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Sets the pixel ratio of the renderer and updates the canvas .
* To automatically detect the correct ratio , pass the string ` 'auto' ` for ` pixelRatio ` .
* @ method setPixelRatio
* @ param { render } render
* @ param { number } pixelRatio
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . setPixelRatio = function ( render , pixelRatio ) {
var options = render . options ,
canvas = render . canvas ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( pixelRatio === 'auto' ) {
pixelRatio = _getPixelRatio ( canvas ) ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
options . pixelRatio = pixelRatio ;
canvas . setAttribute ( 'data-pixel-ratio' , pixelRatio ) ;
canvas . width = options . width * pixelRatio ;
canvas . height = options . height * pixelRatio ;
canvas . style . width = options . width + 'px' ;
canvas . style . height = options . height + 'px' ;
2020-12-26 17:44:24 -05:00
} ;
2016-09-19 18:53:35 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Positions and sizes the viewport around the given object bounds .
* Objects must have at least one of the following properties :
* - ` object.bounds `
* - ` object.position `
* - ` object.min ` and ` object.max `
* - ` object.x ` and ` object.y `
* @ method lookAt
* @ param { render } render
* @ param { object [ ] } objects
* @ param { vector } [ padding ]
* @ param { bool } [ center = true ]
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . lookAt = function ( render , objects , padding , center ) {
center = typeof center !== 'undefined' ? center : true ;
objects = Common . isArray ( objects ) ? objects : [ objects ] ;
padding = padding || {
x : 0 ,
y : 0
2020-12-26 17:44:24 -05:00
} ;
2021-04-11 12:49:36 -04:00
// find bounds of all objects
var bounds = {
min : { x : Infinity , y : Infinity } ,
max : { x : - Infinity , y : - Infinity }
} ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < objects . length ; i += 1 ) {
var object = objects [ i ] ,
min = object . bounds ? object . bounds . min : ( object . min || object . position || object ) ,
max = object . bounds ? object . bounds . max : ( object . max || object . position || object ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( min && max ) {
if ( min . x < bounds . min . x )
bounds . min . x = min . x ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( max . x > bounds . max . x )
bounds . max . x = max . x ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( min . y < bounds . min . y )
bounds . min . y = min . y ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
if ( max . y > bounds . max . y )
bounds . max . y = max . y ;
2020-12-26 17:44:24 -05:00
}
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// find ratios
var width = ( bounds . max . x - bounds . min . x ) + 2 * padding . x ,
height = ( bounds . max . y - bounds . min . y ) + 2 * padding . y ,
viewHeight = render . canvas . height ,
viewWidth = render . canvas . width ,
outerRatio = viewWidth / viewHeight ,
innerRatio = width / height ,
scaleX = 1 ,
scaleY = 1 ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// find scale factor
if ( innerRatio > outerRatio ) {
scaleY = innerRatio / outerRatio ;
} else {
scaleX = outerRatio / innerRatio ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// enable bounds
render . options . hasBounds = true ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// position and size
render . bounds . min . x = bounds . min . x ;
render . bounds . max . x = bounds . min . x + width * scaleX ;
render . bounds . min . y = bounds . min . y ;
render . bounds . max . y = bounds . min . y + height * scaleY ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// center
if ( center ) {
render . bounds . min . x += width * 0.5 - ( width * scaleX ) * 0.5 ;
render . bounds . max . x += width * 0.5 - ( width * scaleX ) * 0.5 ;
render . bounds . min . y += height * 0.5 - ( height * scaleY ) * 0.5 ;
render . bounds . max . y += height * 0.5 - ( height * scaleY ) * 0.5 ;
}
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// padding
render . bounds . min . x -= padding . x ;
render . bounds . max . x -= padding . x ;
render . bounds . min . y -= padding . y ;
render . bounds . max . y -= padding . y ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
// update mouse
if ( render . mouse ) {
Mouse . setScale ( render . mouse , {
x : ( render . bounds . max . x - render . bounds . min . x ) / render . canvas . width ,
y : ( render . bounds . max . y - render . bounds . min . y ) / render . canvas . height
} ) ;
2016-09-19 18:53:35 -04:00
2021-04-11 12:49:36 -04:00
Mouse . setOffset ( render . mouse , render . bounds . min ) ;
2016-09-19 18:53:35 -04:00
}
} ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Applies viewport transforms based on ` render.bounds ` to a render context .
* @ method startViewTransform
* @ param { render } render
* /
Render . startViewTransform = function ( render ) {
var boundsWidth = render . bounds . max . x - render . bounds . min . x ,
boundsHeight = render . bounds . max . y - render . bounds . min . y ,
boundsScaleX = boundsWidth / render . options . width ,
boundsScaleY = boundsHeight / render . options . height ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
render . context . setTransform (
render . options . pixelRatio / boundsScaleX , 0 , 0 ,
render . options . pixelRatio / boundsScaleY , 0 , 0
) ;
render . context . translate ( - render . bounds . min . x , - render . bounds . min . y ) ;
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Resets all transforms on the render context .
* @ method endViewTransform
* @ param { render } render
* /
Render . endViewTransform = function ( render ) {
render . context . setTransform ( render . options . pixelRatio , 0 , 0 , render . options . pixelRatio , 0 , 0 ) ;
} ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Renders the given ` engine ` ' s ` Matter.World ` object .
* This is the entry point for all rendering and should be called every time the scene changes .
* @ method world
* @ param { render } render
* /
Render . world = function ( render , time ) {
var startTime = Common . now ( ) ,
engine = render . engine ,
world = engine . world ,
canvas = render . canvas ,
context = render . context ,
options = render . options ,
timing = render . timing ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
var allBodies = Composite . allBodies ( world ) ,
allConstraints = Composite . allConstraints ( world ) ,
background = options . wireframes ? options . wireframeBackground : options . background ,
bodies = [ ] ,
constraints = [ ] ,
i ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
var event = {
timestamp : engine . timing . timestamp
} ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
Events . trigger ( render , 'beforeRender' , event ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// apply background if it has changed
if ( render . currentBackground !== background )
_applyBackground ( render , background ) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// clear the canvas with a transparent fill, to allow the canvas background to show
context . globalCompositeOperation = 'source-in' ;
context . fillStyle = "transparent" ;
context . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
context . globalCompositeOperation = 'source-over' ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// handle bounds
if ( options . hasBounds ) {
// filter out bodies that are not in view
for ( i = 0 ; i < allBodies . length ; i ++ ) {
var body = allBodies [ i ] ;
if ( Bounds . overlaps ( body . bounds , render . bounds ) )
bodies . push ( body ) ;
}
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// filter out constraints that are not in view
for ( i = 0 ; i < allConstraints . length ; i ++ ) {
var constraint = allConstraints [ i ] ,
bodyA = constraint . bodyA ,
bodyB = constraint . bodyB ,
pointAWorld = constraint . pointA ,
pointBWorld = constraint . pointB ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
if ( bodyA ) pointAWorld = Vector . add ( bodyA . position , constraint . pointA ) ;
if ( bodyB ) pointBWorld = Vector . add ( bodyB . position , constraint . pointB ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
if ( ! pointAWorld || ! pointBWorld )
continue ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
if ( Bounds . contains ( render . bounds , pointAWorld ) || Bounds . contains ( render . bounds , pointBWorld ) )
constraints . push ( constraint ) ;
}
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// transform the view
Render . startViewTransform ( render ) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// update mouse
if ( render . mouse ) {
Mouse . setScale ( render . mouse , {
x : ( render . bounds . max . x - render . bounds . min . x ) / render . options . width ,
y : ( render . bounds . max . y - render . bounds . min . y ) / render . options . height
} ) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
Mouse . setOffset ( render . mouse , render . bounds . min ) ;
}
} else {
constraints = allConstraints ;
bodies = allBodies ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
if ( render . options . pixelRatio !== 1 ) {
render . context . setTransform ( render . options . pixelRatio , 0 , 0 , render . options . pixelRatio , 0 , 0 ) ;
2020-12-26 17:44:24 -05:00
}
2015-08-12 19:38:20 -04:00
}
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
if ( ! options . wireframes || ( engine . enableSleeping && options . showSleeping ) ) {
// fully featured rendering of bodies
Render . bodies ( render , bodies , context ) ;
} else {
if ( options . showConvexHulls )
Render . bodyConvexHulls ( render , bodies , context ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
// optimised method for wireframes only
Render . bodyWireframes ( render , bodies , context ) ;
}
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showBounds )
Render . bodyBounds ( render , bodies , context ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showAxes || options . showAngleIndicator )
Render . bodyAxes ( render , bodies , context ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showPositions )
Render . bodyPositions ( render , bodies , context ) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showVelocity )
Render . bodyVelocity ( render , bodies , context ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( options . showIds )
Render . bodyIds ( render , bodies , context ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( options . showSeparations )
Render . separations ( render , engine . pairs . list , context ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( options . showCollisions )
Render . collisions ( render , engine . pairs . list , context ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( options . showVertexNumbers )
Render . vertexNumbers ( render , bodies , context ) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showMousePosition )
Render . mousePosition ( render , render . mouse , context ) ;
2015-12-05 11:47:50 -05:00
2021-04-11 12:49:36 -04:00
Render . constraints ( constraints , context ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showBroadphase )
Render . grid ( render , engine . grid , context ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
if ( options . hasBounds ) {
// revert view transforms
Render . endViewTransform ( render ) ;
2020-12-26 17:44:24 -05:00
}
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
Events . trigger ( render , 'afterRender' , event ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
// log the time elapsed computing this update
timing . lastElapsed = Common . now ( ) - startTime ;
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Renders statistics about the engine and world useful for debugging .
* @ private
* @ method stats
* @ param { render } render
* @ param { RenderingContext } context
* @ param { Number } time
* /
Render . stats = function ( render , context , time ) {
var engine = render . engine ,
world = engine . world ,
bodies = Composite . allBodies ( world ) ,
parts = 0 ,
width = 55 ,
height = 44 ,
x = 0 ,
y = 0 ;
// count parts
for ( var i = 0 ; i < bodies . length ; i += 1 ) {
parts += bodies [ i ] . parts . length ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// sections
var sections = {
'Part' : parts ,
'Body' : bodies . length ,
'Cons' : Composite . allConstraints ( world ) . length ,
'Comp' : Composite . allComposites ( world ) . length ,
'Pair' : engine . pairs . list . length
} ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
// background
context . fillStyle = '#0e0f19' ;
context . fillRect ( x , y , width * 5.5 , height ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
context . font = '12px Arial' ;
context . textBaseline = 'top' ;
context . textAlign = 'right' ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
// sections
for ( var key in sections ) {
var section = sections [ key ] ;
// label
context . fillStyle = '#aaa' ;
context . fillText ( key , x + width , y + 8 ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
// value
context . fillStyle = '#eee' ;
context . fillText ( section , x + width , y + 26 ) ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
x += width ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
} ;
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Renders engine and render performance information .
* @ private
* @ method performance
* @ param { render } render
* @ param { RenderingContext } context
* /
Render . performance = function ( render , context ) {
var engine = render . engine ,
timing = render . timing ,
deltaHistory = timing . deltaHistory ,
elapsedHistory = timing . elapsedHistory ,
timestampElapsedHistory = timing . timestampElapsedHistory ,
engineDeltaHistory = timing . engineDeltaHistory ,
engineElapsedHistory = timing . engineElapsedHistory ,
lastEngineDelta = engine . timing . lastDelta ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var deltaMean = _mean ( deltaHistory ) ,
elapsedMean = _mean ( elapsedHistory ) ,
engineDeltaMean = _mean ( engineDeltaHistory ) ,
engineElapsedMean = _mean ( engineElapsedHistory ) ,
timestampElapsedMean = _mean ( timestampElapsedHistory ) ,
rateMean = ( timestampElapsedMean / deltaMean ) || 0 ,
fps = ( 1000 / deltaMean ) || 0 ;
var graphHeight = 4 ,
gap = 12 ,
width = 60 ,
height = 34 ,
x = 10 ,
y = 69 ;
// background
context . fillStyle = '#0e0f19' ;
context . fillRect ( 0 , 50 , gap * 4 + width * 5 + 22 , height ) ;
// show FPS
Render . status (
context , x , y , width , graphHeight , deltaHistory . length ,
Math . round ( fps ) + ' fps' ,
fps / Render . _goodFps ,
function ( i ) { return ( deltaHistory [ i ] / deltaMean ) - 1 ; }
) ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
// show engine delta
Render . status (
context , x + gap + width , y , width , graphHeight , engineDeltaHistory . length ,
lastEngineDelta . toFixed ( 2 ) + ' dt' ,
Render . _goodDelta / lastEngineDelta ,
function ( i ) { return ( engineDeltaHistory [ i ] / engineDeltaMean ) - 1 ; }
) ;
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
// show engine update time
Render . status (
context , x + ( gap + width ) * 2 , y , width , graphHeight , engineElapsedHistory . length ,
engineElapsedMean . toFixed ( 2 ) + ' ut' ,
1 - ( engineElapsedMean / Render . _goodFps ) ,
function ( i ) { return ( engineElapsedHistory [ i ] / engineElapsedMean ) - 1 ; }
) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// show render time
Render . status (
context , x + ( gap + width ) * 3 , y , width , graphHeight , elapsedHistory . length ,
elapsedMean . toFixed ( 2 ) + ' rt' ,
1 - ( elapsedMean / Render . _goodFps ) ,
function ( i ) { return ( elapsedHistory [ i ] / elapsedMean ) - 1 ; }
) ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
// show effective speed
Render . status (
context , x + ( gap + width ) * 4 , y , width , graphHeight , timestampElapsedHistory . length ,
rateMean . toFixed ( 2 ) + ' x' ,
rateMean * rateMean * rateMean ,
function ( i ) { return ( ( ( timestampElapsedHistory [ i ] / deltaHistory [ i ] ) / rateMean ) || 0 ) - 1 ; }
) ;
} ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Renders a label , indicator and a chart .
* @ private
* @ method status
* @ param { RenderingContext } context
* @ param { number } x
* @ param { number } y
* @ param { number } width
* @ param { number } height
* @ param { number } count
* @ param { string } label
* @ param { string } indicator
* @ param { function } plotY
* /
Render . status = function ( context , x , y , width , height , count , label , indicator , plotY ) {
// background
context . strokeStyle = '#888' ;
context . fillStyle = '#444' ;
context . lineWidth = 1 ;
context . fillRect ( x , y + 7 , width , 1 ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// chart
context . beginPath ( ) ;
context . moveTo ( x , y + 7 - height * Common . clamp ( 0.4 * plotY ( 0 ) , - 2 , 2 ) ) ;
for ( var i = 0 ; i < width ; i += 1 ) {
context . lineTo ( x + i , y + 7 - ( i < count ? height * Common . clamp ( 0.4 * plotY ( i ) , - 2 , 2 ) : 0 ) ) ;
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
context . stroke ( ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// indicator
context . fillStyle = 'hsl(' + Common . clamp ( 25 + 95 * indicator , 0 , 120 ) + ',100%,60%)' ;
context . fillRect ( x , y - 7 , 4 , 4 ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// label
context . font = '12px Arial' ;
context . textBaseline = 'middle' ;
context . textAlign = 'right' ;
context . fillStyle = '#eee' ;
context . fillText ( label , x + width , y - 5 ) ;
2020-12-26 17:44:24 -05:00
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Description
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ method constraints
* @ param { constraint [ ] } constraints
* @ param { RenderingContext } context
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . constraints = function ( constraints , context ) {
var c = context ;
2014-07-29 11:26:49 -04:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < constraints . length ; i ++ ) {
var constraint = constraints [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( ! constraint . render . visible || ! constraint . pointA || ! constraint . pointB )
continue ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var bodyA = constraint . bodyA ,
bodyB = constraint . bodyB ,
start ,
end ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( bodyA ) {
start = Vector . add ( bodyA . position , constraint . pointA ) ;
} else {
start = constraint . pointA ;
2014-03-11 06:29:14 -04:00
}
2021-04-11 12:49:36 -04:00
if ( constraint . render . type === 'pin' ) {
c . beginPath ( ) ;
c . arc ( start . x , start . y , 3 , 0 , 2 * Math . PI ) ;
c . closePath ( ) ;
} else {
if ( bodyB ) {
end = Vector . add ( bodyB . position , constraint . pointB ) ;
} else {
end = constraint . pointB ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
c . moveTo ( start . x , start . y ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( constraint . render . type === 'spring' ) {
var delta = Vector . sub ( end , start ) ,
normal = Vector . perp ( Vector . normalise ( delta ) ) ,
coils = Math . ceil ( Common . clamp ( constraint . length / 5 , 12 , 20 ) ) ,
offset ;
2014-03-11 06:29:14 -04:00
2021-04-11 12:49:36 -04:00
for ( var j = 1 ; j < coils ; j += 1 ) {
offset = j % 2 === 0 ? 1 : - 1 ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
c . lineTo (
start . x + delta . x * ( j / coils ) + normal . x * offset * 4 ,
start . y + delta . y * ( j / coils ) + normal . y * offset * 4
) ;
}
}
c . lineTo ( end . x , end . y ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( constraint . render . lineWidth ) {
c . lineWidth = constraint . render . lineWidth ;
c . strokeStyle = constraint . render . strokeStyle ;
c . stroke ( ) ;
}
if ( constraint . render . anchors ) {
c . fillStyle = constraint . render . strokeStyle ;
c . beginPath ( ) ;
c . arc ( start . x , start . y , 3 , 0 , 2 * Math . PI ) ;
c . arc ( end . x , end . y , 3 , 0 , 2 * Math . PI ) ;
c . closePath ( ) ;
c . fill ( ) ;
}
}
2014-02-19 09:15:05 -05:00
} ;
2021-04-11 12:49:36 -04:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Description
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ method bodies
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . bodies = function ( render , bodies , context ) {
var c = context ,
engine = render . engine ,
options = render . options ,
showInternalEdges = options . showInternalEdges || ! options . wireframes ,
body ,
part ,
i ,
k ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
for ( i = 0 ; i < bodies . length ; i ++ ) {
body = bodies [ i ] ;
2015-06-29 15:58:24 -04:00
2021-04-11 12:49:36 -04:00
if ( ! body . render . visible )
continue ;
2015-06-29 15:58:24 -04:00
2021-04-11 12:49:36 -04:00
// handle compound parts
for ( k = body . parts . length > 1 ? 1 : 0 ; k < body . parts . length ; k ++ ) {
part = body . parts [ k ] ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( ! part . render . visible )
continue ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( options . showSleeping && body . isSleeping ) {
c . globalAlpha = 0.5 * part . render . opacity ;
} else if ( part . render . opacity !== 1 ) {
c . globalAlpha = part . render . opacity ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( part . render . sprite && part . render . sprite . texture && ! options . wireframes ) {
// part sprite
var sprite = part . render . sprite ,
texture = _getTexture ( render , sprite . texture ) ;
2016-01-16 17:43:32 -05:00
2021-04-11 12:49:36 -04:00
c . translate ( part . position . x , part . position . y ) ;
c . rotate ( part . angle ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . drawImage (
texture ,
texture . width * - sprite . xOffset * sprite . xScale ,
texture . height * - sprite . yOffset * sprite . yScale ,
texture . width * sprite . xScale ,
texture . height * sprite . yScale
) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// revert translation, hopefully faster than save / restore
c . rotate ( - part . angle ) ;
c . translate ( - part . position . x , - part . position . y ) ;
} else {
// part polygon
if ( part . circleRadius ) {
c . beginPath ( ) ;
c . arc ( part . position . x , part . position . y , part . circleRadius , 0 , 2 * Math . PI ) ;
} else {
c . beginPath ( ) ;
c . moveTo ( part . vertices [ 0 ] . x , part . vertices [ 0 ] . y ) ;
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
for ( var j = 1 ; j < part . vertices . length ; j ++ ) {
if ( ! part . vertices [ j - 1 ] . isInternal || showInternalEdges ) {
c . lineTo ( part . vertices [ j ] . x , part . vertices [ j ] . y ) ;
} else {
c . moveTo ( part . vertices [ j ] . x , part . vertices [ j ] . y ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( part . vertices [ j ] . isInternal && ! showInternalEdges ) {
c . moveTo ( part . vertices [ ( j + 1 ) % part . vertices . length ] . x , part . vertices [ ( j + 1 ) % part . vertices . length ] . y ) ;
}
}
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
c . lineTo ( part . vertices [ 0 ] . x , part . vertices [ 0 ] . y ) ;
c . closePath ( ) ;
}
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
if ( ! options . wireframes ) {
c . fillStyle = part . render . fillStyle ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( part . render . lineWidth ) {
c . lineWidth = part . render . lineWidth ;
c . strokeStyle = part . render . strokeStyle ;
c . stroke ( ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
c . fill ( ) ;
} else {
c . lineWidth = 1 ;
c . strokeStyle = '#bbb' ;
c . stroke ( ) ;
}
}
c . globalAlpha = 1 ;
}
2014-05-05 14:32:51 -04:00
}
2021-04-11 12:49:36 -04:00
} ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Optimised method for drawing body wireframes in one pass
* @ private
* @ method bodyWireframes
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
* /
Render . bodyWireframes = function ( render , bodies , context ) {
var c = context ,
showInternalEdges = render . options . showInternalEdges ,
body ,
part ,
i ,
j ,
k ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2016-02-15 16:24:17 -05:00
2021-04-11 12:49:36 -04:00
// render all bodies
for ( i = 0 ; i < bodies . length ; i ++ ) {
body = bodies [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( ! body . render . visible )
continue ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// handle compound parts
for ( k = body . parts . length > 1 ? 1 : 0 ; k < body . parts . length ; k ++ ) {
part = body . parts [ k ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
c . moveTo ( part . vertices [ 0 ] . x , part . vertices [ 0 ] . y ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
for ( j = 1 ; j < part . vertices . length ; j ++ ) {
if ( ! part . vertices [ j - 1 ] . isInternal || showInternalEdges ) {
c . lineTo ( part . vertices [ j ] . x , part . vertices [ j ] . y ) ;
} else {
c . moveTo ( part . vertices [ j ] . x , part . vertices [ j ] . y ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( part . vertices [ j ] . isInternal && ! showInternalEdges ) {
c . moveTo ( part . vertices [ ( j + 1 ) % part . vertices . length ] . x , part . vertices [ ( j + 1 ) % part . vertices . length ] . y ) ;
}
}
2014-05-05 14:32:51 -04:00
2021-04-11 12:49:36 -04:00
c . lineTo ( part . vertices [ 0 ] . x , part . vertices [ 0 ] . y ) ;
}
}
c . lineWidth = 1 ;
c . strokeStyle = '#bbb' ;
c . stroke ( ) ;
2014-02-19 09:15:05 -05:00
} ;
2015-05-20 15:38:41 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Optimised method for drawing body convex hull wireframes in one pass
* @ private
* @ method bodyConvexHulls
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
2015-05-20 15:38:41 -04:00
* /
2021-04-11 12:49:36 -04:00
Render . bodyConvexHulls = function ( render , bodies , context ) {
var c = context ,
body ,
part ,
i ,
j ,
k ;
2018-06-11 18:15:03 -04:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
// render convex hulls
for ( i = 0 ; i < bodies . length ; i ++ ) {
body = bodies [ i ] ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
if ( ! body . render . visible || body . parts . length === 1 )
continue ;
c . moveTo ( body . vertices [ 0 ] . x , body . vertices [ 0 ] . y ) ;
for ( j = 1 ; j < body . vertices . length ; j ++ ) {
c . lineTo ( body . vertices [ j ] . x , body . vertices [ j ] . y ) ;
}
c . lineTo ( body . vertices [ 0 ] . x , body . vertices [ 0 ] . y ) ;
}
c . lineWidth = 1 ;
c . strokeStyle = 'rgba(255,255,255,0.2)' ;
c . stroke ( ) ;
2020-12-26 17:44:24 -05:00
} ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Renders body vertex numbers .
* @ private
* @ method vertexNumbers
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . vertexNumbers = function ( render , bodies , context ) {
var c = context ,
i ,
j ,
k ;
for ( i = 0 ; i < bodies . length ; i ++ ) {
var parts = bodies [ i ] . parts ;
for ( k = parts . length > 1 ? 1 : 0 ; k < parts . length ; k ++ ) {
var part = parts [ k ] ;
for ( j = 0 ; j < part . vertices . length ; j ++ ) {
c . fillStyle = 'rgba(255,255,255,0.2)' ;
c . fillText ( i + '_' + j , part . position . x + ( part . vertices [ j ] . x - part . position . x ) * 0.8 , part . position . y + ( part . vertices [ j ] . y - part . position . y ) * 0.8 ) ;
}
}
}
2020-12-26 17:44:24 -05:00
} ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Renders mouse position .
* @ private
* @ method mousePosition
* @ param { render } render
2020-12-26 17:44:24 -05:00
* @ param { mouse } mouse
2021-04-11 12:49:36 -04:00
* @ param { RenderingContext } context
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . mousePosition = function ( render , mouse , context ) {
var c = context ;
c . fillStyle = 'rgba(255,255,255,0.8)' ;
c . fillText ( mouse . position . x + ' ' + mouse . position . y , mouse . position . x + 5 , mouse . position . y - 5 ) ;
2020-12-26 17:44:24 -05:00
} ;
2021-04-11 12:49:36 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Draws body bounds
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ method bodyBounds
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . bodyBounds = function ( render , bodies , context ) {
var c = context ,
engine = render . engine ,
options = render . options ;
c . beginPath ( ) ;
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
if ( body . render . visible ) {
var parts = bodies [ i ] . parts ;
for ( var j = parts . length > 1 ? 1 : 0 ; j < parts . length ; j ++ ) {
var part = parts [ j ] ;
c . rect ( part . bounds . min . x , part . bounds . min . y , part . bounds . max . x - part . bounds . min . x , part . bounds . max . y - part . bounds . min . y ) ;
}
}
}
if ( options . wireframes ) {
c . strokeStyle = 'rgba(255,255,255,0.08)' ;
2020-12-26 17:44:24 -05:00
} else {
2021-04-11 12:49:36 -04:00
c . strokeStyle = 'rgba(0,0,0,0.1)' ;
2015-05-20 15:38:41 -04:00
}
2021-04-11 12:49:36 -04:00
c . lineWidth = 1 ;
c . stroke ( ) ;
2020-12-26 17:44:24 -05:00
} ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Draws body angle indicators and axes
* @ private
* @ method bodyAxes
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
* /
Render . bodyAxes = function ( render , bodies , context ) {
var c = context ,
engine = render . engine ,
options = render . options ,
part ,
i ,
j ,
k ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
for ( i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ,
parts = body . parts ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
if ( ! body . render . visible )
continue ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
if ( options . showAxes ) {
// render all axes
for ( j = parts . length > 1 ? 1 : 0 ; j < parts . length ; j ++ ) {
part = parts [ j ] ;
for ( k = 0 ; k < part . axes . length ; k ++ ) {
var axis = part . axes [ k ] ;
c . moveTo ( part . position . x , part . position . y ) ;
c . lineTo ( part . position . x + axis . x * 20 , part . position . y + axis . y * 20 ) ;
}
}
} else {
for ( j = parts . length > 1 ? 1 : 0 ; j < parts . length ; j ++ ) {
part = parts [ j ] ;
for ( k = 0 ; k < part . axes . length ; k ++ ) {
// render a single axis indicator
c . moveTo ( part . position . x , part . position . y ) ;
c . lineTo ( ( part . vertices [ 0 ] . x + part . vertices [ part . vertices . length - 1 ] . x ) / 2 ,
( part . vertices [ 0 ] . y + part . vertices [ part . vertices . length - 1 ] . y ) / 2 ) ;
}
}
}
}
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
if ( options . wireframes ) {
c . strokeStyle = 'indianred' ;
c . lineWidth = 1 ;
} else {
c . strokeStyle = 'rgba(255, 255, 255, 0.4)' ;
c . globalCompositeOperation = 'overlay' ;
c . lineWidth = 2 ;
}
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
c . stroke ( ) ;
c . globalCompositeOperation = 'source-over' ;
} ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Draws body positions
* @ private
* @ method bodyPositions
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . bodyPositions = function ( render , bodies , context ) {
var c = context ,
engine = render . engine ,
options = render . options ,
body ,
part ,
i ,
k ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
// render current positions
for ( i = 0 ; i < bodies . length ; i ++ ) {
body = bodies [ i ] ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
if ( ! body . render . visible )
continue ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// handle compound parts
for ( k = 0 ; k < body . parts . length ; k ++ ) {
part = body . parts [ k ] ;
c . arc ( part . position . x , part . position . y , 3 , 0 , 2 * Math . PI , false ) ;
c . closePath ( ) ;
}
2015-05-20 15:38:41 -04:00
}
2021-04-11 12:49:36 -04:00
if ( options . wireframes ) {
c . fillStyle = 'indianred' ;
} else {
c . fillStyle = 'rgba(0,0,0,0.5)' ;
}
c . fill ( ) ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// render previous positions
for ( i = 0 ; i < bodies . length ; i ++ ) {
body = bodies [ i ] ;
if ( body . render . visible ) {
c . arc ( body . positionPrev . x , body . positionPrev . y , 2 , 0 , 2 * Math . PI , false ) ;
c . closePath ( ) ;
}
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . fillStyle = 'rgba(255,165,0,0.8)' ;
c . fill ( ) ;
} ;
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Draws body velocity
* @ private
* @ method bodyVelocity
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
* /
Render . bodyVelocity = function ( render , bodies , context ) {
var c = context ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
if ( ! body . render . visible )
continue ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
c . moveTo ( body . position . x , body . position . y ) ;
c . lineTo ( body . position . x + ( body . position . x - body . positionPrev . x ) * 2 , body . position . y + ( body . position . y - body . positionPrev . y ) * 2 ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
c . lineWidth = 3 ;
c . strokeStyle = 'cornflowerblue' ;
c . stroke ( ) ;
} ;
2021-01-31 16:56:25 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Draws body ids
* @ private
* @ method bodyIds
* @ param { render } render
* @ param { body [ ] } bodies
* @ param { RenderingContext } context
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . bodyIds = function ( render , bodies , context ) {
var c = context ,
i ,
j ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
for ( i = 0 ; i < bodies . length ; i ++ ) {
if ( ! bodies [ i ] . render . visible )
continue ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
var parts = bodies [ i ] . parts ;
for ( j = parts . length > 1 ? 1 : 0 ; j < parts . length ; j ++ ) {
var part = parts [ j ] ;
c . font = "12px Arial" ;
c . fillStyle = 'rgba(255,255,255,0.5)' ;
c . fillText ( part . id , part . position . x + 10 , part . position . y - 10 ) ;
}
2014-02-19 09:15:05 -05:00
}
} ;
2021-04-11 12:49:36 -04:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Description
* @ private
* @ method collisions
* @ param { render } render
* @ param { pair [ ] } pairs
* @ param { RenderingContext } context
* /
Render . collisions = function ( render , pairs , context ) {
var c = context ,
options = render . options ,
pair ,
collision ,
corrected ,
bodyA ,
bodyB ,
i ,
j ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// render collision positions
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
if ( ! pair . isActive )
continue ;
collision = pair . collision ;
for ( j = 0 ; j < pair . activeContacts . length ; j ++ ) {
var contact = pair . activeContacts [ j ] ,
vertex = contact . vertex ;
c . rect ( vertex . x - 1.5 , vertex . y - 1.5 , 3.5 , 3.5 ) ;
}
}
if ( options . wireframes ) {
c . fillStyle = 'rgba(255,255,255,0.7)' ;
2020-12-26 17:44:24 -05:00
} else {
2021-04-11 12:49:36 -04:00
c . fillStyle = 'orange' ;
2014-02-19 09:15:05 -05:00
}
2021-04-11 12:49:36 -04:00
c . fill ( ) ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// render collision normals
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
if ( ! pair . isActive )
continue ;
collision = pair . collision ;
if ( pair . activeContacts . length > 0 ) {
var normalPosX = pair . activeContacts [ 0 ] . vertex . x ,
normalPosY = pair . activeContacts [ 0 ] . vertex . y ;
if ( pair . activeContacts . length === 2 ) {
normalPosX = ( pair . activeContacts [ 0 ] . vertex . x + pair . activeContacts [ 1 ] . vertex . x ) / 2 ;
normalPosY = ( pair . activeContacts [ 0 ] . vertex . y + pair . activeContacts [ 1 ] . vertex . y ) / 2 ;
}
if ( collision . bodyB === collision . supports [ 0 ] . body || collision . bodyA . isStatic === true ) {
c . moveTo ( normalPosX - collision . normal . x * 8 , normalPosY - collision . normal . y * 8 ) ;
} else {
c . moveTo ( normalPosX + collision . normal . x * 8 , normalPosY + collision . normal . y * 8 ) ;
}
c . lineTo ( normalPosX , normalPosY ) ;
}
2020-12-26 17:44:24 -05:00
}
2021-04-11 12:49:36 -04:00
if ( options . wireframes ) {
c . strokeStyle = 'rgba(255,165,0,0.7)' ;
} else {
c . strokeStyle = 'orange' ;
}
c . lineWidth = 1 ;
c . stroke ( ) ;
2014-02-19 09:15:05 -05:00
} ;
2014-03-30 14:45:30 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Description
* @ private
* @ method separations
* @ param { render } render
* @ param { pair [ ] } pairs
* @ param { RenderingContext } context
2014-03-30 14:45:30 -04:00
* /
2021-04-11 12:49:36 -04:00
Render . separations = function ( render , pairs , context ) {
var c = context ,
options = render . options ,
pair ,
collision ,
corrected ,
bodyA ,
bodyB ,
i ,
j ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
// render separations
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( ! pair . isActive )
continue ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
collision = pair . collision ;
bodyA = collision . bodyA ;
bodyB = collision . bodyB ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var k = 1 ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( ! bodyB . isStatic && ! bodyA . isStatic ) k = 0.5 ;
if ( bodyB . isStatic ) k = 0 ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . moveTo ( bodyB . position . x , bodyB . position . y ) ;
c . lineTo ( bodyB . position . x - collision . penetration . x * k , bodyB . position . y - collision . penetration . y * k ) ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
k = 1 ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
if ( ! bodyB . isStatic && ! bodyA . isStatic ) k = 0.5 ;
if ( bodyA . isStatic ) k = 0 ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
c . moveTo ( bodyA . position . x , bodyA . position . y ) ;
c . lineTo ( bodyA . position . x + collision . penetration . x * k , bodyA . position . y + collision . penetration . y * k ) ;
2014-03-30 14:45:30 -04:00
}
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
if ( options . wireframes ) {
c . strokeStyle = 'rgba(255,165,0,0.5)' ;
} else {
c . strokeStyle = 'orange' ;
}
c . stroke ( ) ;
2014-03-30 14:45:30 -04:00
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Description
* @ private
* @ method grid
* @ param { render } render
* @ param { grid } grid
* @ param { RenderingContext } context
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Render . grid = function ( render , grid , context ) {
var c = context ,
options = render . options ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( options . wireframes ) {
c . strokeStyle = 'rgba(255,180,0,0.1)' ;
} else {
c . strokeStyle = 'rgba(255,180,0,0.5)' ;
2021-01-31 16:56:25 -05:00
}
2021-04-11 12:49:36 -04:00
c . beginPath ( ) ;
2021-01-31 16:56:25 -05:00
2021-04-11 12:49:36 -04:00
var bucketKeys = Common . keys ( grid . buckets ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < bucketKeys . length ; i ++ ) {
var bucketId = bucketKeys [ i ] ;
2021-01-31 16:56:25 -05:00
2021-04-11 12:49:36 -04:00
if ( grid . buckets [ bucketId ] . length < 2 )
continue ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
var region = bucketId . split ( /C|R/ ) ;
c . rect ( 0.5 + parseInt ( region [ 1 ] , 10 ) * grid . bucketWidth ,
0.5 + parseInt ( region [ 2 ] , 10 ) * grid . bucketHeight ,
grid . bucketWidth ,
grid . bucketHeight ) ;
}
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
c . lineWidth = 1 ;
c . stroke ( ) ;
} ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Description
* @ private
* @ method inspector
* @ param { inspector } inspector
* @ param { RenderingContext } context
* /
Render . inspector = function ( inspector , context ) {
var engine = inspector . engine ,
selected = inspector . selected ,
render = inspector . render ,
options = render . options ,
bounds ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
if ( options . hasBounds ) {
var boundsWidth = render . bounds . max . x - render . bounds . min . x ,
boundsHeight = render . bounds . max . y - render . bounds . min . y ,
boundsScaleX = boundsWidth / render . options . width ,
boundsScaleY = boundsHeight / render . options . height ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
context . scale ( 1 / boundsScaleX , 1 / boundsScaleY ) ;
context . translate ( - render . bounds . min . x , - render . bounds . min . y ) ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < selected . length ; i ++ ) {
var item = selected [ i ] . data ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
context . translate ( 0.5 , 0.5 ) ;
context . lineWidth = 1 ;
context . strokeStyle = 'rgba(255,165,0,0.9)' ;
context . setLineDash ( [ 1 , 2 ] ) ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
switch ( item . type ) {
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
case 'body' :
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
// render body selections
bounds = item . bounds ;
context . beginPath ( ) ;
context . rect ( Math . floor ( bounds . min . x - 3 ) , Math . floor ( bounds . min . y - 3 ) ,
Math . floor ( bounds . max . x - bounds . min . x + 6 ) , Math . floor ( bounds . max . y - bounds . min . y + 6 ) ) ;
context . closePath ( ) ;
context . stroke ( ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
break ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
case 'constraint' :
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
// render constraint selections
var point = item . pointA ;
if ( item . bodyA )
point = item . pointB ;
context . beginPath ( ) ;
context . arc ( point . x , point . y , 10 , 0 , 2 * Math . PI ) ;
context . closePath ( ) ;
context . stroke ( ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
break ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
}
2021-01-31 16:56:25 -05:00
2021-04-11 12:49:36 -04:00
context . setLineDash ( [ ] ) ;
context . translate ( - 0.5 , - 0.5 ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// render selection region
if ( inspector . selectStart !== null ) {
context . translate ( 0.5 , 0.5 ) ;
context . lineWidth = 1 ;
context . strokeStyle = 'rgba(255,165,0,0.6)' ;
context . fillStyle = 'rgba(255,165,0,0.1)' ;
bounds = inspector . selectBounds ;
context . beginPath ( ) ;
context . rect ( Math . floor ( bounds . min . x ) , Math . floor ( bounds . min . y ) ,
Math . floor ( bounds . max . x - bounds . min . x ) , Math . floor ( bounds . max . y - bounds . min . y ) ) ;
context . closePath ( ) ;
context . stroke ( ) ;
context . fill ( ) ;
context . translate ( - 0.5 , - 0.5 ) ;
2014-02-19 09:15:05 -05:00
}
2021-04-11 12:49:36 -04:00
if ( options . hasBounds )
context . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
} ;
2016-01-16 17:43:32 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Updates render timing .
* @ method _updateTiming
* @ private
* @ param { render } render
* @ param { number } time
* /
var _updateTiming = function ( render , time ) {
var engine = render . engine ,
timing = render . timing ,
historySize = timing . historySize ,
timestamp = engine . timing . timestamp ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
timing . delta = time - timing . lastTime || Render . _goodDelta ;
timing . lastTime = time ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
timing . timestampElapsed = timestamp - timing . lastTimestamp || 0 ;
timing . lastTimestamp = timestamp ;
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
timing . deltaHistory . unshift ( timing . delta ) ;
timing . deltaHistory . length = Math . min ( timing . deltaHistory . length , historySize ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
timing . engineDeltaHistory . unshift ( engine . timing . lastDelta ) ;
timing . engineDeltaHistory . length = Math . min ( timing . engineDeltaHistory . length , historySize ) ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
timing . timestampElapsedHistory . unshift ( timing . timestampElapsed ) ;
timing . timestampElapsedHistory . length = Math . min ( timing . timestampElapsedHistory . length , historySize ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
timing . engineElapsedHistory . unshift ( engine . timing . lastElapsed ) ;
timing . engineElapsedHistory . length = Math . min ( timing . engineElapsedHistory . length , historySize ) ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
timing . elapsedHistory . unshift ( timing . lastElapsed ) ;
timing . elapsedHistory . length = Math . min ( timing . elapsedHistory . length , historySize ) ;
} ;
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Returns the mean value of the given numbers .
* @ method _mean
* @ private
* @ param { Number [ ] } values
* @ return { Number } the mean of given values
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
var _mean = function ( values ) {
var result = 0 ;
for ( var i = 0 ; i < values . length ; i += 1 ) {
result += values [ i ] ;
2014-02-19 09:15:05 -05:00
}
2021-04-11 12:49:36 -04:00
return ( result / values . length ) || 0 ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* @ method _createCanvas
* @ private
* @ param { } width
* @ param { } height
* @ return canvas
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
var _createCanvas = function ( width , height ) {
var canvas = document . createElement ( 'canvas' ) ;
canvas . width = width ;
canvas . height = height ;
canvas . oncontextmenu = function ( ) { return false ; } ;
canvas . onselectstart = function ( ) { return false ; } ;
return canvas ;
2014-02-19 09:15:05 -05:00
} ;
2014-05-01 09:09:06 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Gets the pixel ratio of the canvas .
* @ method _getPixelRatio
* @ private
* @ param { HTMLElement } canvas
* @ return { Number } pixel ratio
* /
var _getPixelRatio = function ( canvas ) {
var context = canvas . getContext ( '2d' ) ,
devicePixelRatio = window . devicePixelRatio || 1 ,
backingStorePixelRatio = context . webkitBackingStorePixelRatio || context . mozBackingStorePixelRatio
|| context . msBackingStorePixelRatio || context . oBackingStorePixelRatio
|| context . backingStorePixelRatio || 1 ;
return devicePixelRatio / backingStorePixelRatio ;
2014-05-01 09:09:06 -04:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Gets the requested texture ( an Image ) via its path
* @ method _getTexture
* @ private
* @ param { render } render
* @ param { string } imagePath
* @ return { Image } texture
2014-05-01 09:09:06 -04:00
* /
2021-04-11 12:49:36 -04:00
var _getTexture = function ( render , imagePath ) {
var image = render . textures [ imagePath ] ;
if ( image )
return image ;
image = render . textures [ imagePath ] = new Image ( ) ;
image . src = imagePath ;
return image ;
2020-12-26 17:44:24 -05:00
} ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Applies the background to the canvas using CSS .
* @ method applyBackground
* @ private
* @ param { render } render
* @ param { string } background
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
var _applyBackground = function ( render , background ) {
var cssBackground = background ;
if ( /(jpg|gif|png)$/ . test ( background ) )
cssBackground = 'url(' + background + ')' ;
render . canvas . style . background = cssBackground ;
render . canvas . style . backgroundSize = "contain" ;
render . currentBackground = background ;
2020-12-26 17:44:24 -05:00
} ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
/ *
*
* Events Documentation
*
* /
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired before rendering
*
* @ event beforeRender
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-05-20 15:38:41 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired after rendering
*
* @ event afterRender
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ *
*
* Properties Documentation
*
* /
2018-06-11 18:15:03 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A back - reference to the ` Matter.Render ` module .
*
* @ property controller
* @ type render
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A reference to the ` Matter.Engine ` instance to be used .
*
* @ property engine
* @ type engine
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A reference to the element where the canvas is to be inserted ( if ` render.canvas ` has not been specified )
*
* @ property element
* @ type HTMLElement
* @ default null
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The canvas element to render to . If not specified , one will be created if ` render.element ` has been specified .
*
* @ property canvas
* @ type HTMLCanvasElement
* @ default null
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A ` Bounds ` object that specifies the drawing view region .
* Rendering will be automatically transformed and scaled to fit within the canvas size ( ` render.options.width ` and ` render.options.height ` ) .
* This allows for creating views that can pan or zoom around the scene .
* You must also set ` render.options.hasBounds ` to ` true ` to enable bounded rendering .
*
* @ property bounds
* @ type bounds
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The 2 d rendering context from the ` render.canvas ` element .
*
* @ property context
* @ type CanvasRenderingContext2D
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The sprite texture cache .
*
* @ property textures
* @ type { }
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The mouse to render if ` render.options.showMousePosition ` is enabled .
*
* @ property mouse
* @ type mouse
* @ default null
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The configuration options of the renderer .
*
* @ property options
* @ type { }
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The target width in pixels of the ` render.canvas ` to be created .
* See also the ` options.pixelRatio ` property to change render quality .
*
* @ property options . width
* @ type number
* @ default 800
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* The target height in pixels of the ` render.canvas ` to be created .
* See also the ` options.pixelRatio ` property to change render quality .
*
* @ property options . height
* @ type number
* @ default 600
2020-12-26 17:44:24 -05:00
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* The [ pixel ratio ] ( https : //developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio) to use when rendering.
*
* @ property options . pixelRatio
* @ type number
* @ default 1
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A CSS background color string to use when ` render.options.wireframes ` is disabled .
* This may be also set to ` 'transparent' ` or equivalent .
*
* @ property options . background
* @ type string
* @ default '#14151f'
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A CSS background color string to use when ` render.options.wireframes ` is enabled .
* This may be also set to ` 'transparent' ` or equivalent .
*
* @ property options . wireframeBackground
* @ type string
* @ default '#14151f'
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag that specifies if ` render.bounds ` should be used when rendering .
*
* @ property options . hasBounds
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable all debug information overlays together .
* This includes and has priority over the values of :
*
* - ` render.options.showStats `
* - ` render.options.showPerformance `
*
* @ property options . showDebug
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* A flag to enable or disable the engine stats info overlay .
* From left to right , the values shown are :
*
* - body parts total
* - body total
* - constraints total
* - composites total
* - collision pairs total
*
* @ property options . showStats
* @ type boolean
* @ default false
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable performance charts .
* From left to right , the values shown are :
*
* - average render frequency ( e . g . 60 fps )
* - exact engine delta time used for last update ( e . g . 16.66 ms )
* - average engine execution duration ( e . g . 5.00 ms )
* - average render execution duration ( e . g . 0.40 ms )
* - average effective play speed ( e . g . '1.00x' is 'real-time' )
*
* Each value is recorded over a fixed sample of past frames ( 60 frames ) .
*
* A chart shown below each value indicates the variance from the average over the sample .
* The more stable or fixed the value is the flatter the chart will appear .
*
* @ property options . showPerformance
* @ type boolean
* @ default false
* /
/ * *
* A flag to enable or disable rendering entirely .
*
* @ property options . enabled
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to toggle wireframe rendering otherwise solid fill rendering is used .
*
* @ property options . wireframes
* @ type boolean
* @ default true
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable sleeping bodies indicators .
*
* @ property options . showSleeping
* @ type boolean
* @ default true
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* A flag to enable or disable the debug information overlay .
*
* @ property options . showDebug
* @ type boolean
* @ default false
2020-12-26 17:44:24 -05:00
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the collision broadphase debug overlay .
*
* @ property options . showBroadphase
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body bounds debug overlay .
*
* @ property options . showBounds
* @ type boolean
* @ default false
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body velocity debug overlay .
*
* @ property options . showVelocity
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* A flag to enable or disable the body collisions debug overlay .
*
* @ property options . showCollisions
* @ type boolean
* @ default false
2020-12-26 17:44:24 -05:00
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the collision resolver separations debug overlay .
*
* @ property options . showSeparations
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body axes debug overlay .
*
* @ property options . showAxes
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body positions debug overlay .
*
* @ property options . showPositions
* @ type boolean
* @ default false
* /
2021-01-17 18:13:32 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body angle debug overlay .
*
* @ property options . showAngleIndicator
* @ type boolean
* @ default false
* /
2021-01-17 18:13:32 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body and part ids debug overlay .
*
* @ property options . showIds
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body vertex numbers debug overlay .
*
* @ property options . showVertexNumbers
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body convex hulls debug overlay .
*
* @ property options . showConvexHulls
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the body internal edges debug overlay .
*
* @ property options . showInternalEdges
* @ type boolean
* @ default false
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag to enable or disable the mouse position debug overlay .
*
* @ property options . showMousePosition
* @ type boolean
* @ default false
* /
2015-05-20 15:38:41 -04:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 17 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports ) {
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* The ` Matter.Contact ` module contains methods for creating and manipulating collision contacts .
2014-02-28 20:10:08 -05:00
*
2020-12-26 17:44:24 -05:00
* @ class Contact
2014-02-28 20:10:08 -05:00
* /
2020-12-26 17:44:24 -05:00
var Contact = { } ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
module . exports = Contact ;
2015-08-17 18:50:03 -04:00
2014-02-19 09:15:05 -05:00
( function ( ) {
2015-05-20 15:38:41 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Creates a new contact .
2015-05-20 15:38:41 -04:00
* @ method create
2020-12-26 17:44:24 -05:00
* @ param { vertex } vertex
* @ return { contact } A new contact
2015-05-20 15:38:41 -04:00
* /
2020-12-26 17:44:24 -05:00
Contact . create = function ( vertex ) {
return {
id : Contact . id ( vertex ) ,
vertex : vertex ,
normalImpulse : 0 ,
tangentImpulse : 0
} ;
2015-05-20 15:38:41 -04:00
} ;
2020-12-26 17:44:24 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2020-12-26 17:44:24 -05:00
* Generates a contact id .
* @ method id
* @ param { vertex } vertex
* @ return { string } Unique contactID
2014-06-09 14:40:24 -04:00
* /
2020-12-26 17:44:24 -05:00
Contact . id = function ( vertex ) {
return vertex . body . id + '_' + vertex . index ;
2014-06-09 14:40:24 -04:00
} ;
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 18 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.Engine ` module contains methods for creating and manipulating engines .
* An engine is a controller that manages updating the simulation of the world .
* See ` Matter.Runner ` for an optional game loop utility .
2020-12-26 17:44:24 -05:00
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
2021-04-11 12:49:36 -04:00
* @ class Engine
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
var Engine = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
module . exports = Engine ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var Sleeping = _ _webpack _require _ _ ( 7 ) ;
var Resolver = _ _webpack _require _ _ ( 19 ) ;
var Detector = _ _webpack _require _ _ ( 13 ) ;
var Pairs = _ _webpack _require _ _ ( 20 ) ;
var Grid = _ _webpack _require _ _ ( 21 ) ;
var Events = _ _webpack _require _ _ ( 4 ) ;
2020-12-26 17:44:24 -05:00
var Composite = _ _webpack _require _ _ ( 5 ) ;
var Constraint = _ _webpack _require _ _ ( 8 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
2021-04-11 12:49:36 -04:00
var Body = _ _webpack _require _ _ ( 6 ) ;
2020-12-26 17:44:24 -05:00
( function ( ) {
2014-02-19 09:15:05 -05:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new engine . The options parameter is an object that specifies any properties you wish to override the defaults .
* All properties have default values , and many are pre - calculated automatically based on other properties .
2020-12-26 17:44:24 -05:00
* See the properties section below for detailed information on what you can pass via the ` options ` object .
* @ method create
2021-04-11 12:49:36 -04:00
* @ param { object } [ options ]
* @ return { engine } engine
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . create = function ( options ) {
options = options || { } ;
2020-12-26 17:44:24 -05:00
var defaults = {
2021-04-11 12:49:36 -04:00
positionIterations : 6 ,
velocityIterations : 4 ,
constraintIterations : 2 ,
enableSleeping : false ,
events : [ ] ,
plugin : { } ,
grid : null ,
2020-12-26 17:44:24 -05:00
gravity : {
x : 0 ,
y : 1 ,
scale : 0.001
} ,
2021-04-11 12:49:36 -04:00
timing : {
timestamp : 0 ,
timeScale : 1 ,
lastDelta : 0 ,
lastElapsed : 0
2020-12-26 17:44:24 -05:00
}
} ;
2021-04-11 12:49:36 -04:00
var engine = Common . extend ( defaults , options ) ;
engine . world = options . world || Composite . create ( { label : 'World' } ) ;
engine . grid = Grid . create ( options . grid || options . broadphase ) ;
engine . pairs = Pairs . create ( ) ;
// temporary back compatibility
engine . world . gravity = engine . gravity ;
engine . broadphase = engine . grid ;
engine . metrics = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return engine ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Moves the simulation forward in time by ` delta ` ms .
* The ` correction ` argument is an optional ` Number ` that specifies the time correction factor to apply to the update .
* This can help improve the accuracy of the simulation in cases where ` delta ` is changing between updates .
* The value of ` correction ` is defined as ` delta / lastDelta ` , i . e . the percentage change of ` delta ` over the last step .
* Therefore the value is always ` 1 ` ( no correction ) when ` delta ` constant ( or when no correction is desired , which is the default ) .
* See the paper on < a href = "http://lonesock.net/article/verlet.html" > Time Corrected Verlet < / a > f o r m o r e i n f o r m a t i o n .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* Triggers ` beforeUpdate ` and ` afterUpdate ` events .
* Triggers ` collisionStart ` , ` collisionActive ` and ` collisionEnd ` events .
* @ method update
* @ param { engine } engine
* @ param { number } [ delta = 16.666 ]
* @ param { number } [ correction = 1 ]
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . update = function ( engine , delta , correction ) {
var startTime = Common . now ( ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
delta = delta || 1000 / 60 ;
correction = correction || 1 ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
var world = engine . world ,
timing = engine . timing ,
grid = engine . grid ,
gridPairs = [ ] ,
i ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// increment timestamp
timing . timestamp += delta * timing . timeScale ;
timing . lastDelta = delta * timing . timeScale ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
// create an event object
var event = {
timestamp : timing . timestamp
} ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
Events . trigger ( engine , 'beforeUpdate' , event ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// get lists of all bodies and constraints, no matter what composites they are in
var allBodies = Composite . allBodies ( world ) ,
allConstraints = Composite . allConstraints ( world ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// if sleeping enabled, call the sleeping controller
if ( engine . enableSleeping )
Sleeping . update ( allBodies , timing . timeScale ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// applies gravity to all bodies
Engine . _bodiesApplyGravity ( allBodies , engine . gravity ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// update all body position and rotation by integration
Engine . _bodiesUpdate ( allBodies , delta , timing . timeScale , correction , world . bounds ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// update all constraints (first pass)
Constraint . preSolveAll ( allBodies ) ;
for ( i = 0 ; i < engine . constraintIterations ; i ++ ) {
Constraint . solveAll ( allConstraints , timing . timeScale ) ;
}
Constraint . postSolveAll ( allBodies ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// broadphase pass: find potential collision pairs
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// if world is dirty, we must flush the whole grid
if ( world . isModified )
Grid . clear ( grid ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// update the grid buckets based on current bodies
Grid . update ( grid , allBodies , engine , world . isModified ) ;
gridPairs = grid . pairsList ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// clear all composite modified flags
if ( world . isModified ) {
Composite . setModified ( world , false , false , true ) ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// narrowphase pass: find actual collisions, then create or update collision pairs
var collisions = Detector . collisions ( gridPairs , engine ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// update collision pairs
var pairs = engine . pairs ,
timestamp = timing . timestamp ;
Pairs . update ( pairs , collisions , timestamp ) ;
Pairs . removeOld ( pairs , timestamp ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// wake up bodies involved in collisions
if ( engine . enableSleeping )
Sleeping . afterCollisions ( pairs . list , timing . timeScale ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// trigger collision events
if ( pairs . collisionStart . length > 0 )
Events . trigger ( engine , 'collisionStart' , { pairs : pairs . collisionStart } ) ;
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
// iteratively resolve position between collisions
Resolver . preSolvePosition ( pairs . list ) ;
for ( i = 0 ; i < engine . positionIterations ; i ++ ) {
Resolver . solvePosition ( pairs . list , timing . timeScale ) ;
}
Resolver . postSolvePosition ( allBodies ) ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
// update all constraints (second pass)
Constraint . preSolveAll ( allBodies ) ;
for ( i = 0 ; i < engine . constraintIterations ; i ++ ) {
Constraint . solveAll ( allConstraints , timing . timeScale ) ;
}
Constraint . postSolveAll ( allBodies ) ;
2014-02-28 20:10:08 -05:00
2021-04-11 12:49:36 -04:00
// iteratively resolve velocity between collisions
Resolver . preSolveVelocity ( pairs . list ) ;
for ( i = 0 ; i < engine . velocityIterations ; i ++ ) {
Resolver . solveVelocity ( pairs . list , timing . timeScale ) ;
2020-12-26 17:44:24 -05:00
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// trigger collision events
if ( pairs . collisionActive . length > 0 )
Events . trigger ( engine , 'collisionActive' , { pairs : pairs . collisionActive } ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( pairs . collisionEnd . length > 0 )
Events . trigger ( engine , 'collisionEnd' , { pairs : pairs . collisionEnd } ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// clear force buffers
Engine . _bodiesClearForces ( allBodies ) ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
Events . trigger ( engine , 'afterUpdate' , event ) ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
// log the time elapsed computing this update
engine . timing . lastElapsed = Common . now ( ) - startTime ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
return engine ;
2020-12-26 17:44:24 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Merges two engines by keeping the configuration of ` engineA ` but replacing the world with the one from ` engineB ` .
* @ method merge
* @ param { engine } engineA
* @ param { engine } engineB
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . merge = function ( engineA , engineB ) {
Common . extend ( engineA , engineB ) ;
if ( engineB . world ) {
engineA . world = engineB . world ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
Engine . clear ( engineA ) ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
var bodies = Composite . allBodies ( engineA . world ) ;
2014-06-09 14:40:24 -04:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
Sleeping . set ( body , false ) ;
body . id = Common . nextId ( ) ;
}
2020-12-26 17:44:24 -05:00
}
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Clears the engine including the world , pairs and broadphase .
2020-12-26 17:44:24 -05:00
* @ method clear
2021-04-11 12:49:36 -04:00
* @ param { engine } engine
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . clear = function ( engine ) {
var world = engine . world ,
bodies = Composite . allBodies ( world ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
Pairs . clear ( engine . pairs ) ;
Grid . clear ( engine . grid ) ;
Grid . update ( engine . grid , bodies , engine , true ) ;
} ;
2015-05-20 15:38:41 -04:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Zeroes the ` body.force ` and ` body.torque ` force buffers .
* @ method _bodiesClearForces
* @ private
* @ param { body [ ] } bodies
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . _bodiesClearForces = function ( bodies ) {
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// reset force buffers
body . force . x = 0 ;
body . force . y = 0 ;
body . torque = 0 ;
2014-02-19 09:15:05 -05:00
}
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Applys a mass dependant force to all given bodies .
* @ method _bodiesApplyGravity
* @ private
* @ param { body [ ] } bodies
* @ param { vector } gravity
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . _bodiesApplyGravity = function ( bodies , gravity ) {
var gravityScale = typeof gravity . scale !== 'undefined' ? gravity . scale : 0.001 ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
if ( ( gravity . x === 0 && gravity . y === 0 ) || gravityScale === 0 ) {
return ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( body . isStatic || body . isSleeping )
2020-12-26 17:44:24 -05:00
continue ;
2021-04-11 12:49:36 -04:00
// apply gravity
body . force . y += body . mass * gravity . y * gravityScale ;
body . force . x += body . mass * gravity . x * gravityScale ;
2014-06-09 14:40:24 -04:00
}
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Applys ` Body.update ` to all given ` bodies ` .
* @ method _bodiesUpdate
* @ private
2020-12-26 17:44:24 -05:00
* @ param { body [ ] } bodies
2021-04-11 12:49:36 -04:00
* @ param { number } deltaTime
* The amount of time elapsed between updates
* @ param { number } timeScale
* @ param { number } correction
* The Verlet correction factor ( deltaTime / lastDeltaTime )
* @ param { bounds } worldBounds
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Engine . _bodiesUpdate = function ( bodies , deltaTime , timeScale , correction , worldBounds ) {
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( body . isStatic || body . isSleeping )
continue ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
Body . update ( body , deltaTime , timeScale , correction ) ;
2020-12-26 17:44:24 -05:00
}
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-14 19:36:35 -04:00
* A deprecated alias for ` Runner.run ` , use ` Matter.Runner.run(engine) ` instead and see ` Matter.Runner ` for more information .
* @ deprecated use Matter . Runner . run ( engine ) instead
2021-04-11 12:49:36 -04:00
* @ method run
* @ param { engine } engine
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
/ * *
* Fired just before an update
*
* @ event beforeUpdate
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ * *
* Fired after engine update and all collision events
*
* @ event afterUpdate
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ * *
* Fired after engine update , provides a list of all pairs that have started to collide in the current tick ( if any )
*
* @ event collisionStart
* @ param { } event An event object
* @ param { } event . pairs List of affected pairs
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ * *
* Fired after engine update , provides a list of all pairs that are colliding in the current tick ( if any )
*
* @ event collisionActive
* @ param { } event An event object
* @ param { } event . pairs List of affected pairs
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ * *
* Fired after engine update , provides a list of all pairs that have ended collision in the current tick ( if any )
*
* @ event collisionEnd
* @ param { } event An event object
* @ param { } event . pairs List of affected pairs
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
/ *
*
* Properties Documentation
*
* /
/ * *
* An integer ` Number ` that specifies the number of position iterations to perform each update .
* The higher the value , the higher quality the simulation will be at the expense of performance .
*
* @ property positionIterations
* @ type number
* @ default 6
* /
/ * *
* An integer ` Number ` that specifies the number of velocity iterations to perform each update .
* The higher the value , the higher quality the simulation will be at the expense of performance .
*
* @ property velocityIterations
* @ type number
* @ default 4
* /
/ * *
* An integer ` Number ` that specifies the number of constraint iterations to perform each update .
* The higher the value , the higher quality the simulation will be at the expense of performance .
* The default value of ` 2 ` is usually very adequate .
*
* @ property constraintIterations
* @ type number
* @ default 2
* /
/ * *
* A flag that specifies whether the engine should allow sleeping via the ` Matter.Sleeping ` module .
* Sleeping can improve stability and performance , but often at the expense of accuracy .
*
* @ property enableSleeping
* @ type boolean
* @ default false
* /
/ * *
* An ` Object ` containing properties regarding the timing systems of the engine .
*
* @ property timing
* @ type object
* /
/ * *
* A ` Number ` that specifies the global scaling factor of time for all bodies .
* A value of ` 0 ` freezes the simulation .
* A value of ` 0.1 ` gives a slow - motion effect .
* A value of ` 1.2 ` gives a speed - up effect .
*
* @ property timing . timeScale
* @ type number
* @ default 1
* /
/ * *
* A ` Number ` that specifies the current simulation - time in milliseconds starting from ` 0 ` .
* It is incremented on every ` Engine.update ` by the given ` delta ` argument .
*
* @ property timing . timestamp
* @ type number
* @ default 0
* /
/ * *
* A ` Number ` that represents the total execution time elapsed during the last ` Engine.update ` in milliseconds .
* It is updated by timing from the start of the last ` Engine.update ` call until it ends .
*
* This value will also include the total execution time of all event handlers directly or indirectly triggered by the engine update .
*
* @ property timing . lastElapsed
* @ type number
* @ default 0
* /
/ * *
* A ` Number ` that represents the ` delta ` value used in the last engine update .
*
* @ property timing . lastDelta
* @ type number
* @ default 0
* /
/ * *
* A ` Matter.Grid ` instance .
*
* @ property grid
* @ type grid
* @ default a Matter . Grid instance
* /
/ * *
* Replaced by and now alias for ` engine.grid ` .
*
* @ deprecated use ` engine.grid `
* @ property broadphase
* @ type grid
* @ default a Matter . Grid instance
* /
/ * *
* The root ` Matter.Composite ` instance that will contain all bodies , constraints and other composites to be simulated by this engine .
*
* @ property world
* @ type composite
* @ default a Matter . Composite instance
* /
/ * *
* An object reserved for storing plugin - specific properties .
*
* @ property plugin
* @ type { }
* /
/ * *
* The gravity to apply on all bodies in ` engine.world ` .
*
* @ property gravity
* @ type object
* /
/ * *
* The gravity x component .
*
* @ property gravity . x
* @ type object
* @ default 0
* /
/ * *
* The gravity y component .
*
* @ property gravity . y
* @ type object
* @ default 1
* /
/ * *
* The gravity scale factor .
*
* @ property gravity . scale
* @ type object
* @ default 0.001
* /
} ) ( ) ;
/***/ } ) ,
/* 19 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
* The ` Matter.Resolver ` module contains methods for resolving collision pairs .
*
* @ class Resolver
* /
var Resolver = { } ;
module . exports = Resolver ;
var Vertices = _ _webpack _require _ _ ( 3 ) ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
( function ( ) {
Resolver . _restingThresh = 4 ;
Resolver . _restingThreshTangent = 6 ;
Resolver . _positionDampen = 0.9 ;
Resolver . _positionWarming = 0.8 ;
Resolver . _frictionNormalMultiplier = 5 ;
/ * *
* Prepare pairs for position solving .
* @ method preSolvePosition
* @ param { pair [ ] } pairs
* /
Resolver . preSolvePosition = function ( pairs ) {
var i ,
pair ,
activeCount ;
// find total contacts on each body
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
if ( ! pair . isActive )
continue ;
activeCount = pair . activeContacts . length ;
pair . collision . parentA . totalContacts += activeCount ;
pair . collision . parentB . totalContacts += activeCount ;
}
} ;
/ * *
* Find a solution for pair positions .
* @ method solvePosition
* @ param { pair [ ] } pairs
* @ param { number } timeScale
* /
Resolver . solvePosition = function ( pairs , timeScale ) {
var i ,
pair ,
collision ,
bodyA ,
bodyB ,
normal ,
bodyBtoA ,
contactShare ,
positionImpulse ,
contactCount = { } ,
tempA = Vector . _temp [ 0 ] ,
tempB = Vector . _temp [ 1 ] ,
tempC = Vector . _temp [ 2 ] ,
tempD = Vector . _temp [ 3 ] ;
// find impulses required to resolve penetration
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
if ( ! pair . isActive || pair . isSensor )
continue ;
collision = pair . collision ;
bodyA = collision . parentA ;
bodyB = collision . parentB ;
normal = collision . normal ;
// get current separation between body edges involved in collision
bodyBtoA = Vector . sub ( Vector . add ( bodyB . positionImpulse , bodyB . position , tempA ) ,
Vector . add ( bodyA . positionImpulse ,
Vector . sub ( bodyB . position , collision . penetration , tempB ) , tempC ) , tempD ) ;
pair . separation = Vector . dot ( normal , bodyBtoA ) ;
}
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
if ( ! pair . isActive || pair . isSensor )
continue ;
collision = pair . collision ;
bodyA = collision . parentA ;
bodyB = collision . parentB ;
normal = collision . normal ;
positionImpulse = ( pair . separation - pair . slop ) * timeScale ;
if ( bodyA . isStatic || bodyB . isStatic )
positionImpulse *= 2 ;
if ( ! ( bodyA . isStatic || bodyA . isSleeping ) ) {
contactShare = Resolver . _positionDampen / bodyA . totalContacts ;
bodyA . positionImpulse . x += normal . x * positionImpulse * contactShare ;
bodyA . positionImpulse . y += normal . y * positionImpulse * contactShare ;
}
if ( ! ( bodyB . isStatic || bodyB . isSleeping ) ) {
contactShare = Resolver . _positionDampen / bodyB . totalContacts ;
bodyB . positionImpulse . x -= normal . x * positionImpulse * contactShare ;
bodyB . positionImpulse . y -= normal . y * positionImpulse * contactShare ;
}
}
} ;
/ * *
* Apply position resolution .
* @ method postSolvePosition
* @ param { body [ ] } bodies
* /
Resolver . postSolvePosition = function ( bodies ) {
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
// reset contact count
body . totalContacts = 0 ;
if ( body . positionImpulse . x !== 0 || body . positionImpulse . y !== 0 ) {
// update body geometry
for ( var j = 0 ; j < body . parts . length ; j ++ ) {
var part = body . parts [ j ] ;
Vertices . translate ( part . vertices , body . positionImpulse ) ;
Bounds . update ( part . bounds , part . vertices , body . velocity ) ;
part . position . x += body . positionImpulse . x ;
part . position . y += body . positionImpulse . y ;
}
// move the body without changing velocity
body . positionPrev . x += body . positionImpulse . x ;
body . positionPrev . y += body . positionImpulse . y ;
if ( Vector . dot ( body . positionImpulse , body . velocity ) < 0 ) {
// reset cached impulse if the body has velocity along it
body . positionImpulse . x = 0 ;
body . positionImpulse . y = 0 ;
} else {
// warm the next iteration
body . positionImpulse . x *= Resolver . _positionWarming ;
body . positionImpulse . y *= Resolver . _positionWarming ;
}
}
}
} ;
/ * *
* Prepare pairs for velocity solving .
* @ method preSolveVelocity
* @ param { pair [ ] } pairs
* /
Resolver . preSolveVelocity = function ( pairs ) {
var i ,
j ,
pair ,
contacts ,
collision ,
bodyA ,
bodyB ,
normal ,
tangent ,
contact ,
contactVertex ,
normalImpulse ,
tangentImpulse ,
offset ,
impulse = Vector . _temp [ 0 ] ,
tempA = Vector . _temp [ 1 ] ;
for ( i = 0 ; i < pairs . length ; i ++ ) {
pair = pairs [ i ] ;
if ( ! pair . isActive || pair . isSensor )
continue ;
2020-12-26 17:44:24 -05:00
contacts = pair . activeContacts ;
collision = pair . collision ;
bodyA = collision . parentA ;
bodyB = collision . parentB ;
normal = collision . normal ;
tangent = collision . tangent ;
// resolve each contact
for ( j = 0 ; j < contacts . length ; j ++ ) {
contact = contacts [ j ] ;
contactVertex = contact . vertex ;
normalImpulse = contact . normalImpulse ;
tangentImpulse = contact . tangentImpulse ;
if ( normalImpulse !== 0 || tangentImpulse !== 0 ) {
// total impulse from contact
impulse . x = ( normal . x * normalImpulse ) + ( tangent . x * tangentImpulse ) ;
impulse . y = ( normal . y * normalImpulse ) + ( tangent . y * tangentImpulse ) ;
// apply impulse from contact
if ( ! ( bodyA . isStatic || bodyA . isSleeping ) ) {
offset = Vector . sub ( contactVertex , bodyA . position , tempA ) ;
bodyA . positionPrev . x += impulse . x * bodyA . inverseMass ;
bodyA . positionPrev . y += impulse . y * bodyA . inverseMass ;
bodyA . anglePrev += Vector . cross ( offset , impulse ) * bodyA . inverseInertia ;
}
if ( ! ( bodyB . isStatic || bodyB . isSleeping ) ) {
offset = Vector . sub ( contactVertex , bodyB . position , tempA ) ;
bodyB . positionPrev . x -= impulse . x * bodyB . inverseMass ;
bodyB . positionPrev . y -= impulse . y * bodyB . inverseMass ;
bodyB . anglePrev -= Vector . cross ( offset , impulse ) * bodyB . inverseInertia ;
}
}
2014-02-19 09:15:05 -05:00
}
}
} ;
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Find a solution for pair velocities .
* @ method solveVelocity
* @ param { pair [ ] } pairs
* @ param { number } timeScale
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Resolver . solveVelocity = function ( pairs , timeScale ) {
var timeScaleSquared = timeScale * timeScale ,
impulse = Vector . _temp [ 0 ] ,
tempA = Vector . _temp [ 1 ] ,
tempB = Vector . _temp [ 2 ] ,
tempC = Vector . _temp [ 3 ] ,
tempD = Vector . _temp [ 4 ] ,
tempE = Vector . _temp [ 5 ] ;
for ( var i = 0 ; i < pairs . length ; i ++ ) {
var pair = pairs [ i ] ;
if ( ! pair . isActive || pair . isSensor )
continue ;
var collision = pair . collision ,
bodyA = collision . parentA ,
bodyB = collision . parentB ,
normal = collision . normal ,
tangent = collision . tangent ,
contacts = pair . activeContacts ,
contactShare = 1 / contacts . length ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
// update body velocities
bodyA . velocity . x = bodyA . position . x - bodyA . positionPrev . x ;
bodyA . velocity . y = bodyA . position . y - bodyA . positionPrev . y ;
bodyB . velocity . x = bodyB . position . x - bodyB . positionPrev . x ;
bodyB . velocity . y = bodyB . position . y - bodyB . positionPrev . y ;
bodyA . angularVelocity = bodyA . angle - bodyA . anglePrev ;
bodyB . angularVelocity = bodyB . angle - bodyB . anglePrev ;
// resolve each contact
for ( var j = 0 ; j < contacts . length ; j ++ ) {
var contact = contacts [ j ] ,
contactVertex = contact . vertex ,
offsetA = Vector . sub ( contactVertex , bodyA . position , tempA ) ,
offsetB = Vector . sub ( contactVertex , bodyB . position , tempB ) ,
velocityPointA = Vector . add ( bodyA . velocity , Vector . mult ( Vector . perp ( offsetA ) , bodyA . angularVelocity ) , tempC ) ,
velocityPointB = Vector . add ( bodyB . velocity , Vector . mult ( Vector . perp ( offsetB ) , bodyB . angularVelocity ) , tempD ) ,
relativeVelocity = Vector . sub ( velocityPointA , velocityPointB , tempE ) ,
normalVelocity = Vector . dot ( normal , relativeVelocity ) ;
var tangentVelocity = Vector . dot ( tangent , relativeVelocity ) ,
tangentSpeed = Math . abs ( tangentVelocity ) ,
tangentVelocityDirection = Common . sign ( tangentVelocity ) ;
// raw impulses
var normalImpulse = ( 1 + pair . restitution ) * normalVelocity ,
normalForce = Common . clamp ( pair . separation + normalVelocity , 0 , 1 ) * Resolver . _frictionNormalMultiplier ;
// coulomb friction
var tangentImpulse = tangentVelocity ,
maxFriction = Infinity ;
if ( tangentSpeed > pair . friction * pair . frictionStatic * normalForce * timeScaleSquared ) {
maxFriction = tangentSpeed ;
tangentImpulse = Common . clamp (
pair . friction * tangentVelocityDirection * timeScaleSquared ,
- maxFriction , maxFriction
) ;
}
// modify impulses accounting for mass, inertia and offset
var oAcN = Vector . cross ( offsetA , normal ) ,
oBcN = Vector . cross ( offsetB , normal ) ,
share = contactShare / ( bodyA . inverseMass + bodyB . inverseMass + bodyA . inverseInertia * oAcN * oAcN + bodyB . inverseInertia * oBcN * oBcN ) ;
normalImpulse *= share ;
tangentImpulse *= share ;
// handle high velocity and resting collisions separately
if ( normalVelocity < 0 && normalVelocity * normalVelocity > Resolver . _restingThresh * timeScaleSquared ) {
// high normal velocity so clear cached contact normal impulse
contact . normalImpulse = 0 ;
} else {
// solve resting collision constraints using Erin Catto's method (GDC08)
// impulse constraint tends to 0
var contactNormalImpulse = contact . normalImpulse ;
contact . normalImpulse = Math . min ( contact . normalImpulse + normalImpulse , 0 ) ;
normalImpulse = contact . normalImpulse - contactNormalImpulse ;
}
// handle high velocity and resting collisions separately
if ( tangentVelocity * tangentVelocity > Resolver . _restingThreshTangent * timeScaleSquared ) {
// high tangent velocity so clear cached contact tangent impulse
contact . tangentImpulse = 0 ;
} else {
// solve resting collision constraints using Erin Catto's method (GDC08)
// tangent impulse tends to -tangentSpeed or +tangentSpeed
var contactTangentImpulse = contact . tangentImpulse ;
contact . tangentImpulse = Common . clamp ( contact . tangentImpulse + tangentImpulse , - maxFriction , maxFriction ) ;
tangentImpulse = contact . tangentImpulse - contactTangentImpulse ;
}
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
// total impulse from contact
impulse . x = ( normal . x * normalImpulse ) + ( tangent . x * tangentImpulse ) ;
impulse . y = ( normal . y * normalImpulse ) + ( tangent . y * tangentImpulse ) ;
// apply impulse from contact
if ( ! ( bodyA . isStatic || bodyA . isSleeping ) ) {
bodyA . positionPrev . x += impulse . x * bodyA . inverseMass ;
bodyA . positionPrev . y += impulse . y * bodyA . inverseMass ;
bodyA . anglePrev += Vector . cross ( offsetA , impulse ) * bodyA . inverseInertia ;
}
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
if ( ! ( bodyB . isStatic || bodyB . isSleeping ) ) {
bodyB . positionPrev . x -= impulse . x * bodyB . inverseMass ;
bodyB . positionPrev . y -= impulse . y * bodyB . inverseMass ;
bodyB . anglePrev -= Vector . cross ( offsetB , impulse ) * bodyB . inverseInertia ;
}
}
2014-05-01 09:09:06 -04:00
}
} ;
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-05-05 14:32:51 -04:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 20 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-05-05 14:32:51 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.Pairs ` module contains methods for creating and manipulating collision pair sets .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ class Pairs
2020-12-26 17:44:24 -05:00
* /
2014-05-05 14:32:51 -04:00
2021-04-11 12:49:36 -04:00
var Pairs = { } ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
module . exports = Pairs ;
2015-08-17 18:50:03 -04:00
2021-04-11 12:49:36 -04:00
var Pair = _ _webpack _require _ _ ( 9 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
2017-11-29 19:16:03 -05:00
2021-04-11 12:49:36 -04:00
( function ( ) {
Pairs . _pairMaxIdleLife = 1000 ;
2016-05-01 18:54:13 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new pairs structure .
* @ method create
* @ param { object } options
* @ return { pairs } A new pairs structure
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Pairs . create = function ( options ) {
return Common . extend ( {
table : { } ,
list : [ ] ,
collisionStart : [ ] ,
collisionActive : [ ] ,
collisionEnd : [ ]
} , options ) ;
2020-12-26 17:44:24 -05:00
} ;
2016-05-01 18:54:13 -04:00
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Updates pairs given a list of collisions .
* @ method update
* @ param { object } pairs
* @ param { collision [ ] } collisions
* @ param { number } timestamp
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Pairs . update = function ( pairs , collisions , timestamp ) {
var pairsList = pairs . list ,
pairsTable = pairs . table ,
collisionStart = pairs . collisionStart ,
collisionEnd = pairs . collisionEnd ,
collisionActive = pairs . collisionActive ,
collision ,
pairId ,
pair ,
i ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// clear collision state arrays, but maintain old reference
collisionStart . length = 0 ;
collisionEnd . length = 0 ;
collisionActive . length = 0 ;
for ( i = 0 ; i < pairsList . length ; i ++ ) {
pairsList [ i ] . confirmedActive = false ;
2015-12-23 08:08:54 -05:00
}
2021-04-11 12:49:36 -04:00
for ( i = 0 ; i < collisions . length ; i ++ ) {
collision = collisions [ i ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( collision . collided ) {
pairId = Pair . id ( collision . bodyA , collision . bodyB ) ;
2014-03-30 14:45:30 -04:00
2021-04-11 12:49:36 -04:00
pair = pairsTable [ pairId ] ;
if ( pair ) {
// pair already exists (but may or may not be active)
if ( pair . isActive ) {
// pair exists and is active
collisionActive . push ( pair ) ;
} else {
// pair exists but was inactive, so a collision has just started again
collisionStart . push ( pair ) ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// update the pair
Pair . update ( pair , collision , timestamp ) ;
pair . confirmedActive = true ;
} else {
// pair did not exist, create a new pair
pair = Pair . create ( collision , timestamp ) ;
pairsTable [ pairId ] = pair ;
// push the new pair
collisionStart . push ( pair ) ;
pairsList . push ( pair ) ;
}
}
2014-12-28 13:37:43 -05:00
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// deactivate previously active pairs that are now inactive
for ( i = 0 ; i < pairsList . length ; i ++ ) {
pair = pairsList [ i ] ;
if ( pair . isActive && ! pair . confirmedActive ) {
Pair . setActive ( pair , false , timestamp ) ;
collisionEnd . push ( pair ) ;
}
}
} ;
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Finds and removes pairs that have been inactive for a set amount of time .
* @ method removeOld
* @ param { object } pairs
* @ param { number } timestamp
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Pairs . removeOld = function ( pairs , timestamp ) {
var pairsList = pairs . list ,
pairsTable = pairs . table ,
indexesToRemove = [ ] ,
pair ,
collision ,
pairIndex ,
i ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
for ( i = 0 ; i < pairsList . length ; i ++ ) {
pair = pairsList [ i ] ;
collision = pair . collision ;
// never remove sleeping pairs
if ( collision . bodyA . isSleeping || collision . bodyB . isSleeping ) {
pair . timeUpdated = timestamp ;
2020-12-26 17:44:24 -05:00
continue ;
2021-04-11 12:49:36 -04:00
}
2014-12-28 13:37:43 -05:00
2021-04-11 12:49:36 -04:00
// if pair is inactive for too long, mark it to be removed
if ( timestamp - pair . timeUpdated > Pairs . _pairMaxIdleLife ) {
indexesToRemove . push ( i ) ;
}
}
// remove marked pairs
for ( i = 0 ; i < indexesToRemove . length ; i ++ ) {
pairIndex = indexesToRemove [ i ] - i ;
pair = pairsList [ pairIndex ] ;
delete pairsTable [ pair . id ] ;
pairsList . splice ( pairIndex , 1 ) ;
2014-03-22 13:51:49 -04:00
}
2014-02-19 09:15:05 -05:00
} ;
2016-05-01 18:54:13 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Clears the given pairs structure .
* @ method clear
* @ param { pairs } pairs
* @ return { pairs } pairs
2016-05-01 18:54:13 -04:00
* /
2021-04-11 12:49:36 -04:00
Pairs . clear = function ( pairs ) {
pairs . table = { } ;
pairs . list . length = 0 ;
pairs . collisionStart . length = 0 ;
pairs . collisionActive . length = 0 ;
pairs . collisionEnd . length = 0 ;
return pairs ;
} ;
2016-05-01 18:54:13 -04:00
2021-04-11 12:49:36 -04:00
} ) ( ) ;
2016-05-01 18:54:13 -04:00
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/***/ } ) ,
/* 21 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* The ` Matter.Grid ` module contains methods for creating and manipulating collision broadphase grid structures .
*
* @ class Grid
* /
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var Grid = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
module . exports = Grid ;
var Pair = _ _webpack _require _ _ ( 9 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
( function ( ) {
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new grid .
* @ method create
* @ param { } options
* @ return { grid } A new grid
2014-12-28 13:37:43 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . create = function ( options ) {
var defaults = {
buckets : { } ,
pairs : { } ,
pairsList : [ ] ,
bucketWidth : 48 ,
bucketHeight : 48
} ;
return Common . extend ( defaults , options ) ;
} ;
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* The width of a single grid bucket .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ property bucketWidth
2020-12-26 17:44:24 -05:00
* @ type number
2021-04-11 12:49:36 -04:00
* @ default 48
2020-12-26 17:44:24 -05:00
* /
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* The height of a single grid bucket .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ property bucketHeight
2020-12-26 17:44:24 -05:00
* @ type number
2021-04-11 12:49:36 -04:00
* @ default 48
2020-12-26 17:44:24 -05:00
* /
2014-12-28 13:37:43 -05:00
2017-01-26 18:49:29 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Updates the grid .
* @ method update
* @ param { grid } grid
* @ param { body [ ] } bodies
* @ param { engine } engine
* @ param { boolean } forceUpdate
2017-01-26 18:49:29 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . update = function ( grid , bodies , engine , forceUpdate ) {
var i , col , row ,
world = engine . world ,
buckets = grid . buckets ,
bucket ,
bucketId ,
gridChanged = false ;
for ( i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
if ( body . isSleeping && ! forceUpdate )
continue ;
// temporary back compatibility bounds check
if ( world . bounds && ( body . bounds . max . x < world . bounds . min . x || body . bounds . min . x > world . bounds . max . x
|| body . bounds . max . y < world . bounds . min . y || body . bounds . min . y > world . bounds . max . y ) )
continue ;
var newRegion = Grid . _getRegion ( grid , body ) ;
// if the body has changed grid region
if ( ! body . region || newRegion . id !== body . region . id || forceUpdate ) {
if ( ! body . region || forceUpdate )
body . region = newRegion ;
var union = Grid . _regionUnion ( newRegion , body . region ) ;
// update grid buckets affected by region change
// iterate over the union of both regions
for ( col = union . startCol ; col <= union . endCol ; col ++ ) {
for ( row = union . startRow ; row <= union . endRow ; row ++ ) {
bucketId = Grid . _getBucketId ( col , row ) ;
bucket = buckets [ bucketId ] ;
var isInsideNewRegion = ( col >= newRegion . startCol && col <= newRegion . endCol
&& row >= newRegion . startRow && row <= newRegion . endRow ) ;
var isInsideOldRegion = ( col >= body . region . startCol && col <= body . region . endCol
&& row >= body . region . startRow && row <= body . region . endRow ) ;
// remove from old region buckets
if ( ! isInsideNewRegion && isInsideOldRegion ) {
if ( isInsideOldRegion ) {
if ( bucket )
Grid . _bucketRemoveBody ( grid , bucket , body ) ;
}
}
// add to new region buckets
if ( body . region === newRegion || ( isInsideNewRegion && ! isInsideOldRegion ) || forceUpdate ) {
if ( ! bucket )
bucket = Grid . _createBucket ( buckets , bucketId ) ;
Grid . _bucketAddBody ( grid , bucket , body ) ;
}
}
}
// set the new region
body . region = newRegion ;
// flag changes so we can update pairs
gridChanged = true ;
}
}
// update pairs list only if pairs changed (i.e. a body changed region)
if ( gridChanged )
grid . pairsList = Grid . _createActivePairsList ( grid ) ;
} ;
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Clears the grid .
* @ method clear
* @ param { grid } grid
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . clear = function ( grid ) {
grid . buckets = { } ;
grid . pairs = { } ;
grid . pairsList = [ ] ;
} ;
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Finds the union of two regions .
* @ method _regionUnion
* @ private
* @ param { } regionA
* @ param { } regionB
* @ return { } region
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _regionUnion = function ( regionA , regionB ) {
var startCol = Math . min ( regionA . startCol , regionB . startCol ) ,
endCol = Math . max ( regionA . endCol , regionB . endCol ) ,
startRow = Math . min ( regionA . startRow , regionB . startRow ) ,
endRow = Math . max ( regionA . endRow , regionB . endRow ) ;
return Grid . _createRegion ( startCol , endCol , startRow , endRow ) ;
} ;
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Gets the region a given body falls in for a given grid .
* @ method _getRegion
* @ private
* @ param { } grid
* @ param { } body
* @ return { } region
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _getRegion = function ( grid , body ) {
var bounds = body . bounds ,
startCol = Math . floor ( bounds . min . x / grid . bucketWidth ) ,
endCol = Math . floor ( bounds . max . x / grid . bucketWidth ) ,
startRow = Math . floor ( bounds . min . y / grid . bucketHeight ) ,
endRow = Math . floor ( bounds . max . y / grid . bucketHeight ) ;
return Grid . _createRegion ( startCol , endCol , startRow , endRow ) ;
} ;
2017-11-29 19:16:03 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a region .
* @ method _createRegion
* @ private
* @ param { } startCol
* @ param { } endCol
* @ param { } startRow
* @ param { } endRow
* @ return { } region
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _createRegion = function ( startCol , endCol , startRow , endRow ) {
return {
id : startCol + ',' + endCol + ',' + startRow + ',' + endRow ,
startCol : startCol ,
endCol : endCol ,
startRow : startRow ,
endRow : endRow
} ;
} ;
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Gets the bucket id at the given position .
* @ method _getBucketId
* @ private
* @ param { } column
* @ param { } row
* @ return { string } bucket id
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _getBucketId = function ( column , row ) {
return 'C' + column + 'R' + row ;
} ;
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a bucket .
* @ method _createBucket
* @ private
* @ param { } buckets
* @ param { } bucketId
* @ return { } bucket
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _createBucket = function ( buckets , bucketId ) {
var bucket = buckets [ bucketId ] = [ ] ;
return bucket ;
} ;
2017-01-26 18:49:29 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Adds a body to a bucket .
* @ method _bucketAddBody
* @ private
* @ param { } grid
* @ param { } bucket
* @ param { } body
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _bucketAddBody = function ( grid , bucket , body ) {
// add new pairs
for ( var i = 0 ; i < bucket . length ; i ++ ) {
var bodyB = bucket [ i ] ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
if ( body . id === bodyB . id || ( body . isStatic && bodyB . isStatic ) )
continue ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
// keep track of the number of buckets the pair exists in
// important for Grid.update to work
var pairId = Pair . id ( body , bodyB ) ,
pair = grid . pairs [ pairId ] ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
if ( pair ) {
pair [ 2 ] += 1 ;
} else {
grid . pairs [ pairId ] = [ body , bodyB , 1 ] ;
}
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
// add to bodies (after pairs, otherwise pairs with self)
bucket . push ( body ) ;
} ;
2017-01-26 18:49:29 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Removes a body from a bucket .
* @ method _bucketRemoveBody
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ param { } grid
* @ param { } bucket
* @ param { } body
2017-01-26 18:49:29 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _bucketRemoveBody = function ( grid , bucket , body ) {
// remove from bucket
bucket . splice ( Common . indexOf ( bucket , body ) , 1 ) ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
// update pair counts
for ( var i = 0 ; i < bucket . length ; i ++ ) {
// keep track of the number of buckets the pair exists in
// important for _createActivePairsList to work
var bodyB = bucket [ i ] ,
pairId = Pair . id ( body , bodyB ) ,
pair = grid . pairs [ pairId ] ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
if ( pair )
pair [ 2 ] -= 1 ;
2020-12-26 17:44:24 -05:00
}
2017-01-26 18:49:29 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Generates a list of the active pairs in the grid .
* @ method _createActivePairsList
2020-12-26 17:44:24 -05:00
* @ private
2021-04-11 12:49:36 -04:00
* @ param { } grid
* @ return [ ] pairs
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Grid . _createActivePairsList = function ( grid ) {
var pairKeys ,
pair ,
pairs = [ ] ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
// grid.pairs is used as a hashmap
pairKeys = Common . keys ( grid . pairs ) ;
// iterate over grid.pairs
for ( var k = 0 ; k < pairKeys . length ; k ++ ) {
pair = grid . pairs [ pairKeys [ k ] ] ;
// if pair exists in at least one bucket
// it is a pair that needs further collision testing so push it
if ( pair [ 2 ] > 0 ) {
pairs . push ( pair ) ;
} else {
delete grid . pairs [ pairKeys [ k ] ] ;
}
2020-12-26 17:44:24 -05:00
}
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
return pairs ;
} ;
2020-12-26 17:44:24 -05:00
} ) ( ) ;
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 22 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2021-04-11 12:49:36 -04:00
var Matter = module . exports = _ _webpack _require _ _ ( 23 ) ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
Matter . Axes = _ _webpack _require _ _ ( 10 ) ;
Matter . Bodies = _ _webpack _require _ _ ( 11 ) ;
2020-12-26 17:44:24 -05:00
Matter . Body = _ _webpack _require _ _ ( 6 ) ;
2021-04-11 12:49:36 -04:00
Matter . Bounds = _ _webpack _require _ _ ( 1 ) ;
Matter . Common = _ _webpack _require _ _ ( 0 ) ;
2020-12-26 17:44:24 -05:00
Matter . Composite = _ _webpack _require _ _ ( 5 ) ;
2021-04-11 12:49:36 -04:00
Matter . Composites = _ _webpack _require _ _ ( 24 ) ;
2020-12-26 17:44:24 -05:00
Matter . Constraint = _ _webpack _require _ _ ( 8 ) ;
2021-04-11 12:49:36 -04:00
Matter . Contact = _ _webpack _require _ _ ( 17 ) ;
Matter . Detector = _ _webpack _require _ _ ( 13 ) ;
Matter . Engine = _ _webpack _require _ _ ( 18 ) ;
2020-12-26 17:44:24 -05:00
Matter . Events = _ _webpack _require _ _ ( 4 ) ;
2021-04-11 12:49:36 -04:00
Matter . Grid = _ _webpack _require _ _ ( 21 ) ;
Matter . Mouse = _ _webpack _require _ _ ( 12 ) ;
Matter . MouseConstraint = _ _webpack _require _ _ ( 25 ) ;
Matter . Pair = _ _webpack _require _ _ ( 9 ) ;
Matter . Pairs = _ _webpack _require _ _ ( 20 ) ;
Matter . Plugin = _ _webpack _require _ _ ( 15 ) ;
Matter . Query = _ _webpack _require _ _ ( 26 ) ;
Matter . Render = _ _webpack _require _ _ ( 16 ) ;
Matter . Resolver = _ _webpack _require _ _ ( 19 ) ;
Matter . Runner = _ _webpack _require _ _ ( 27 ) ;
Matter . SAT = _ _webpack _require _ _ ( 14 ) ;
2020-12-26 17:44:24 -05:00
Matter . Sleeping = _ _webpack _require _ _ ( 7 ) ;
2021-04-11 12:49:36 -04:00
Matter . Svg = _ _webpack _require _ _ ( 28 ) ;
2020-12-26 17:44:24 -05:00
Matter . Vector = _ _webpack _require _ _ ( 2 ) ;
Matter . Vertices = _ _webpack _require _ _ ( 3 ) ;
2021-04-11 12:49:36 -04:00
Matter . World = _ _webpack _require _ _ ( 29 ) ;
2021-04-14 19:36:35 -04:00
// temporary back compatibility
Matter . Engine . run = Matter . Runner . run ;
Matter . Common . deprecated ( Matter . Engine , 'run' , 'Engine.run ➤ use Matter.Runner.run(engine) instead' ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 23 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
* The ` Matter ` module is the top level namespace . It also includes a function for installing plugins on top of the library .
*
* @ class Matter
* /
var Matter = { } ;
module . exports = Matter ;
2021-04-11 12:49:36 -04:00
var Plugin = _ _webpack _require _ _ ( 15 ) ;
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
( function ( ) {
/ * *
* The library name .
* @ property name
* @ readOnly
* @ type { String }
* /
Matter . name = 'matter-js' ;
/ * *
* The library version .
* @ property version
* @ readOnly
* @ type { String }
* /
2021-04-14 19:36:35 -04:00
Matter . version = true ? "0.17.1" : undefined ;
2020-12-26 17:44:24 -05:00
/ * *
* A list of plugin dependencies to be installed . These are normally set and installed through ` Matter.use ` .
* Alternatively you may set ` Matter.uses ` manually and install them by calling ` Plugin.use(Matter) ` .
* @ property uses
* @ type { Array }
* /
Matter . uses = [ ] ;
/ * *
* The plugins that have been installed through ` Matter.Plugin.install ` . Read only .
* @ property used
* @ readOnly
* @ type { Array }
* /
Matter . used = [ ] ;
/ * *
* Installs the given plugins on the ` Matter ` namespace .
* This is a short - hand for ` Plugin.use ` , see it for more information .
2021-04-11 12:49:36 -04:00
* Call this function once at the start of your code , with all of the plugins you wish to install as arguments .
* Avoid calling this function multiple times unless you intend to manually control installation order .
* @ method use
* @ param ... plugin { Function } The plugin ( s ) to install on ` base ` ( multi - argument ) .
* /
Matter . use = function ( ) {
Plugin . use ( Matter , Array . prototype . slice . call ( arguments ) ) ;
} ;
/ * *
* Chains a function to excute before the original function on the given ` path ` relative to ` Matter ` .
* See also docs for ` Common.chain ` .
* @ method before
* @ param { string } path The path relative to ` Matter `
* @ param { function } func The function to chain before the original
* @ return { function } The chained function that replaced the original
* /
Matter . before = function ( path , func ) {
path = path . replace ( /^Matter./ , '' ) ;
return Common . chainPathBefore ( Matter , path , func ) ;
} ;
/ * *
* Chains a function to excute after the original function on the given ` path ` relative to ` Matter ` .
* See also docs for ` Common.chain ` .
* @ method after
* @ param { string } path The path relative to ` Matter `
* @ param { function } func The function to chain after the original
* @ return { function } The chained function that replaced the original
* /
Matter . after = function ( path , func ) {
path = path . replace ( /^Matter./ , '' ) ;
return Common . chainPathAfter ( Matter , path , func ) ;
} ;
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 24 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.Composites ` module contains factory methods for creating composite bodies
* with commonly used configurations ( such as stacks and chains ) .
2020-12-26 17:44:24 -05:00
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
2021-04-11 12:49:36 -04:00
* @ class Composites
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
var Composites = { } ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
module . exports = Composites ;
2020-12-26 17:44:24 -05:00
var Composite = _ _webpack _require _ _ ( 5 ) ;
2021-04-11 12:49:36 -04:00
var Constraint = _ _webpack _require _ _ ( 8 ) ;
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2021-04-11 12:49:36 -04:00
var Body = _ _webpack _require _ _ ( 6 ) ;
var Bodies = _ _webpack _require _ _ ( 11 ) ;
var deprecated = Common . deprecated ;
2020-12-26 17:44:24 -05:00
( function ( ) {
/ * *
2021-04-11 12:49:36 -04:00
* Create a new composite containing bodies created in the callback in a grid arrangement .
* This function uses the body ' s bounds to prevent overlaps .
* @ method stack
* @ param { number } xx
* @ param { number } yy
* @ param { number } columns
* @ param { number } rows
* @ param { number } columnGap
* @ param { number } rowGap
* @ param { function } callback
* @ return { composite } A new composite containing objects created in the callback
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Composites . stack = function ( xx , yy , columns , rows , columnGap , rowGap , callback ) {
var stack = Composite . create ( { label : 'Stack' } ) ,
x = xx ,
y = yy ,
lastBody ,
i = 0 ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
for ( var row = 0 ; row < rows ; row ++ ) {
var maxHeight = 0 ;
for ( var column = 0 ; column < columns ; column ++ ) {
var body = callback ( x , y , column , row , lastBody , i ) ;
if ( body ) {
var bodyHeight = body . bounds . max . y - body . bounds . min . y ,
bodyWidth = body . bounds . max . x - body . bounds . min . x ;
2015-12-05 11:47:50 -05:00
2021-04-11 12:49:36 -04:00
if ( bodyHeight > maxHeight )
maxHeight = bodyHeight ;
Body . translate ( body , { x : bodyWidth * 0.5 , y : bodyHeight * 0.5 } ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
x = body . bounds . max . x + columnGap ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
Composite . addBody ( stack , body ) ;
lastBody = body ;
i += 1 ;
} else {
x += columnGap ;
}
}
y += maxHeight + rowGap ;
x = xx ;
}
2014-05-01 09:09:06 -04:00
2021-04-11 12:49:36 -04:00
return stack ;
} ;
/ * *
* Chains all bodies in the given composite together using constraints .
* @ method chain
* @ param { composite } composite
* @ param { number } xOffsetA
* @ param { number } yOffsetA
* @ param { number } xOffsetB
* @ param { number } yOffsetB
* @ param { object } options
* @ return { composite } A new composite containing objects chained together with constraints
* /
Composites . chain = function ( composite , xOffsetA , yOffsetA , xOffsetB , yOffsetB , options ) {
var bodies = composite . bodies ;
for ( var i = 1 ; i < bodies . length ; i ++ ) {
var bodyA = bodies [ i - 1 ] ,
bodyB = bodies [ i ] ,
bodyAHeight = bodyA . bounds . max . y - bodyA . bounds . min . y ,
bodyAWidth = bodyA . bounds . max . x - bodyA . bounds . min . x ,
bodyBHeight = bodyB . bounds . max . y - bodyB . bounds . min . y ,
bodyBWidth = bodyB . bounds . max . x - bodyB . bounds . min . x ;
var defaults = {
bodyA : bodyA ,
pointA : { x : bodyAWidth * xOffsetA , y : bodyAHeight * yOffsetA } ,
bodyB : bodyB ,
pointB : { x : bodyBWidth * xOffsetB , y : bodyBHeight * yOffsetB }
} ;
var constraint = Common . extend ( defaults , options ) ;
Composite . addConstraint ( composite , Constraint . create ( constraint ) ) ;
}
2015-08-12 19:38:20 -04:00
2021-04-11 12:49:36 -04:00
composite . label += ' Chain' ;
return composite ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Connects bodies in the composite with constraints in a grid pattern , with optional cross braces .
* @ method mesh
* @ param { composite } composite
* @ param { number } columns
* @ param { number } rows
* @ param { boolean } crossBrace
* @ param { object } options
* @ return { composite } The composite containing objects meshed together with constraints
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Composites . mesh = function ( composite , columns , rows , crossBrace , options ) {
var bodies = composite . bodies ,
row ,
col ,
bodyA ,
bodyB ,
bodyC ;
for ( row = 0 ; row < rows ; row ++ ) {
for ( col = 1 ; col < columns ; col ++ ) {
bodyA = bodies [ ( col - 1 ) + ( row * columns ) ] ;
bodyB = bodies [ col + ( row * columns ) ] ;
Composite . addConstraint ( composite , Constraint . create ( Common . extend ( { bodyA : bodyA , bodyB : bodyB } , options ) ) ) ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( row > 0 ) {
for ( col = 0 ; col < columns ; col ++ ) {
bodyA = bodies [ col + ( ( row - 1 ) * columns ) ] ;
bodyB = bodies [ col + ( row * columns ) ] ;
Composite . addConstraint ( composite , Constraint . create ( Common . extend ( { bodyA : bodyA , bodyB : bodyB } , options ) ) ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( crossBrace && col > 0 ) {
bodyC = bodies [ ( col - 1 ) + ( ( row - 1 ) * columns ) ] ;
Composite . addConstraint ( composite , Constraint . create ( Common . extend ( { bodyA : bodyC , bodyB : bodyB } , options ) ) ) ;
2020-12-26 17:44:24 -05:00
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
if ( crossBrace && col < columns - 1 ) {
bodyC = bodies [ ( col + 1 ) + ( ( row - 1 ) * columns ) ] ;
Composite . addConstraint ( composite , Constraint . create ( Common . extend ( { bodyA : bodyC , bodyB : bodyB } , options ) ) ) ;
}
}
}
2014-02-19 09:15:05 -05:00
}
2021-04-11 12:49:36 -04:00
composite . label += ' Mesh' ;
return composite ;
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Create a new composite containing bodies created in the callback in a pyramid arrangement .
* This function uses the body ' s bounds to prevent overlaps .
* @ method pyramid
* @ param { number } xx
* @ param { number } yy
* @ param { number } columns
* @ param { number } rows
* @ param { number } columnGap
* @ param { number } rowGap
* @ param { function } callback
* @ return { composite } A new composite containing objects created in the callback
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Composites . pyramid = function ( xx , yy , columns , rows , columnGap , rowGap , callback ) {
return Composites . stack ( xx , yy , columns , rows , columnGap , rowGap , function ( x , y , column , row , lastBody , i ) {
var actualRows = Math . min ( rows , Math . ceil ( columns / 2 ) ) ,
lastBodyWidth = lastBody ? lastBody . bounds . max . x - lastBody . bounds . min . x : 0 ;
if ( row > actualRows )
return ;
// reverse row order
row = actualRows - row ;
var start = row ,
end = columns - 1 - row ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
if ( column < start || column > end )
return ;
// retroactively fix the first body's position, since width was unknown
if ( i === 1 ) {
Body . translate ( lastBody , { x : ( column + ( columns % 2 === 1 ? 1 : - 1 ) ) * lastBodyWidth , y : 0 } ) ;
}
2017-06-26 18:21:22 -04:00
2021-04-11 12:49:36 -04:00
var xOffset = lastBody ? column * lastBodyWidth : 0 ;
return callback ( xx + xOffset + column * columnGap , y , column , row , lastBody , i ) ;
} ) ;
2020-12-26 17:44:24 -05:00
} ;
2017-06-26 18:21:22 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* This has now moved to the [ newtonsCradle example ] ( https : //github.com/liabru/matter-js/blob/master/examples/newtonsCradle.js), follow that instead as this function is deprecated here.
* @ deprecated moved to newtonsCradle example
* @ method newtonsCradle
* @ param { number } xx
* @ param { number } yy
* @ param { number } number
* @ param { number } size
* @ param { number } length
* @ return { composite } A new composite newtonsCradle body
* /
Composites . newtonsCradle = function ( xx , yy , number , size , length ) {
var newtonsCradle = Composite . create ( { label : 'Newtons Cradle' } ) ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
for ( var i = 0 ; i < number ; i ++ ) {
var separation = 1.9 ,
circle = Bodies . circle ( xx + i * ( size * separation ) , yy + length , size ,
{ inertia : Infinity , restitution : 1 , friction : 0 , frictionAir : 0.0001 , slop : 1 } ) ,
constraint = Constraint . create ( { pointA : { x : xx + i * ( size * separation ) , y : yy } , bodyB : circle } ) ;
2017-06-26 18:21:22 -04:00
2021-04-11 12:49:36 -04:00
Composite . addBody ( newtonsCradle , circle ) ;
Composite . addConstraint ( newtonsCradle , constraint ) ;
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
return newtonsCradle ;
} ;
2017-11-29 19:16:03 -05:00
2021-04-11 12:49:36 -04:00
deprecated ( Composites , 'newtonsCradle' , 'Composites.newtonsCradle ➤ moved to newtonsCradle example' ) ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* This has now moved to the [ car example ] ( https : //github.com/liabru/matter-js/blob/master/examples/car.js), follow that instead as this function is deprecated here.
* @ deprecated moved to car example
* @ method car
* @ param { number } xx
* @ param { number } yy
* @ param { number } width
* @ param { number } height
* @ param { number } wheelSize
* @ return { composite } A new composite car body
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Composites . car = function ( xx , yy , width , height , wheelSize ) {
var group = Body . nextGroup ( true ) ,
wheelBase = 20 ,
wheelAOffset = - width * 0.5 + wheelBase ,
wheelBOffset = width * 0.5 - wheelBase ,
wheelYOffset = 0 ;
var car = Composite . create ( { label : 'Car' } ) ,
body = Bodies . rectangle ( xx , yy , width , height , {
collisionFilter : {
group : group
} ,
chamfer : {
radius : height * 0.5
} ,
density : 0.0002
} ) ;
var wheelA = Bodies . circle ( xx + wheelAOffset , yy + wheelYOffset , wheelSize , {
collisionFilter : {
group : group
} ,
friction : 0.8
} ) ;
var wheelB = Bodies . circle ( xx + wheelBOffset , yy + wheelYOffset , wheelSize , {
collisionFilter : {
group : group
} ,
friction : 0.8
} ) ;
var axelA = Constraint . create ( {
bodyB : body ,
pointB : { x : wheelAOffset , y : wheelYOffset } ,
bodyA : wheelA ,
stiffness : 1 ,
length : 0
} ) ;
var axelB = Constraint . create ( {
bodyB : body ,
pointB : { x : wheelBOffset , y : wheelYOffset } ,
bodyA : wheelB ,
stiffness : 1 ,
length : 0
} ) ;
Composite . addBody ( car , body ) ;
Composite . addBody ( car , wheelA ) ;
Composite . addBody ( car , wheelB ) ;
Composite . addConstraint ( car , axelA ) ;
Composite . addConstraint ( car , axelB ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
return car ;
} ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
deprecated ( Composites , 'car' , 'Composites.car ➤ moved to car example' ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* This has now moved to the [ softBody example ] ( https : //github.com/liabru/matter-js/blob/master/examples/softBody.js)
* and the [ cloth example ] ( https : //github.com/liabru/matter-js/blob/master/examples/cloth.js), follow those instead as this function is deprecated here.
* @ deprecated moved to softBody and cloth examples
* @ method softBody
* @ param { number } xx
* @ param { number } yy
* @ param { number } columns
* @ param { number } rows
* @ param { number } columnGap
* @ param { number } rowGap
* @ param { boolean } crossBrace
* @ param { number } particleRadius
* @ param { } particleOptions
* @ param { } constraintOptions
* @ return { composite } A new composite softBody
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Composites . softBody = function ( xx , yy , columns , rows , columnGap , rowGap , crossBrace , particleRadius , particleOptions , constraintOptions ) {
particleOptions = Common . extend ( { inertia : Infinity } , particleOptions ) ;
constraintOptions = Common . extend ( { stiffness : 0.2 , render : { type : 'line' , anchors : false } } , constraintOptions ) ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
var softBody = Composites . stack ( xx , yy , columns , rows , columnGap , rowGap , function ( x , y ) {
return Bodies . circle ( x , y , particleRadius , particleOptions ) ;
} ) ;
Composites . mesh ( softBody , columns , rows , crossBrace , constraintOptions ) ;
softBody . label = 'Soft Body' ;
return softBody ;
} ;
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
deprecated ( Composites , 'softBody' , 'Composites.softBody ➤ moved to softBody and cloth examples' ) ;
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 25 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.MouseConstraint ` module contains methods for creating mouse constraints .
* Mouse constraints are used for allowing user interaction , providing the ability to move bodies via the mouse or touch .
2020-12-26 17:44:24 -05:00
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
2021-04-11 12:49:36 -04:00
* @ class MouseConstraint
2020-12-26 17:44:24 -05:00
* /
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
var MouseConstraint = { } ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
module . exports = MouseConstraint ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
var Vertices = _ _webpack _require _ _ ( 3 ) ;
var Sleeping = _ _webpack _require _ _ ( 7 ) ;
var Mouse = _ _webpack _require _ _ ( 12 ) ;
2020-12-26 17:44:24 -05:00
var Events = _ _webpack _require _ _ ( 4 ) ;
2021-04-11 12:49:36 -04:00
var Detector = _ _webpack _require _ _ ( 13 ) ;
var Constraint = _ _webpack _require _ _ ( 8 ) ;
var Composite = _ _webpack _require _ _ ( 5 ) ;
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
2021-04-11 12:49:36 -04:00
var Bounds = _ _webpack _require _ _ ( 1 ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
( function ( ) {
2015-12-23 08:08:54 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Creates a new mouse constraint .
* All properties have default values , and many are pre - calculated automatically based on other properties .
* See the properties section below for detailed information on what you can pass via the ` options ` object .
2020-12-26 17:44:24 -05:00
* @ method create
2021-04-11 12:49:36 -04:00
* @ param { engine } engine
2020-12-26 17:44:24 -05:00
* @ param { } options
2021-04-11 12:49:36 -04:00
* @ return { MouseConstraint } A new MouseConstraint
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
MouseConstraint . create = function ( engine , options ) {
var mouse = ( engine ? engine . mouse : null ) || ( options ? options . mouse : null ) ;
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
if ( ! mouse ) {
if ( engine && engine . render && engine . render . canvas ) {
mouse = Mouse . create ( engine . render . canvas ) ;
} else if ( options && options . element ) {
mouse = Mouse . create ( options . element ) ;
} else {
mouse = Mouse . create ( ) ;
Common . warn ( 'MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected' ) ;
}
2020-12-26 17:44:24 -05:00
}
2017-01-26 18:49:29 -05:00
2021-04-11 12:49:36 -04:00
var constraint = Constraint . create ( {
label : 'Mouse Constraint' ,
pointA : mouse . position ,
pointB : { x : 0 , y : 0 } ,
length : 0.01 ,
stiffness : 0.1 ,
angularStiffness : 1 ,
render : {
strokeStyle : '#90EE90' ,
lineWidth : 3
}
} ) ;
2016-02-07 10:53:07 -05:00
2021-04-11 12:49:36 -04:00
var defaults = {
type : 'mouseConstraint' ,
mouse : mouse ,
element : null ,
body : null ,
constraint : constraint ,
collisionFilter : {
category : 0x0001 ,
mask : 0xFFFFFFFF ,
group : 0
2014-02-19 09:15:05 -05:00
}
2021-04-11 12:49:36 -04:00
} ;
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
var mouseConstraint = Common . extend ( defaults , options ) ;
Events . on ( engine , 'beforeUpdate' , function ( ) {
var allBodies = Composite . allBodies ( engine . world ) ;
MouseConstraint . update ( mouseConstraint , allBodies ) ;
MouseConstraint . _triggerEvents ( mouseConstraint ) ;
} ) ;
return mouseConstraint ;
2014-03-22 13:51:49 -04:00
} ;
/ * *
2021-04-11 12:49:36 -04:00
* Updates the given mouse constraint .
* @ private
* @ method update
* @ param { MouseConstraint } mouseConstraint
* @ param { body [ ] } bodies
2014-03-22 13:51:49 -04:00
* /
2021-04-11 12:49:36 -04:00
MouseConstraint . update = function ( mouseConstraint , bodies ) {
var mouse = mouseConstraint . mouse ,
constraint = mouseConstraint . constraint ,
body = mouseConstraint . body ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
if ( mouse . button === 0 ) {
if ( ! constraint . bodyB ) {
for ( var i = 0 ; i < bodies . length ; i ++ ) {
body = bodies [ i ] ;
if ( Bounds . contains ( body . bounds , mouse . position )
&& Detector . canCollide ( body . collisionFilter , mouseConstraint . collisionFilter ) ) {
for ( var j = body . parts . length > 1 ? 1 : 0 ; j < body . parts . length ; j ++ ) {
var part = body . parts [ j ] ;
if ( Vertices . contains ( part . vertices , mouse . position ) ) {
constraint . pointA = mouse . position ;
constraint . bodyB = mouseConstraint . body = body ;
constraint . pointB = { x : mouse . position . x - body . position . x , y : mouse . position . y - body . position . y } ;
constraint . angleB = body . angle ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
Sleeping . set ( body , false ) ;
Events . trigger ( mouseConstraint , 'startdrag' , { mouse : mouse , body : body } ) ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
break ;
}
}
}
}
} else {
Sleeping . set ( constraint . bodyB , false ) ;
constraint . pointA = mouse . position ;
}
2020-12-26 17:44:24 -05:00
} else {
2021-04-11 12:49:36 -04:00
constraint . bodyB = mouseConstraint . body = null ;
constraint . pointB = null ;
if ( body )
Events . trigger ( mouseConstraint , 'enddrag' , { mouse : mouse , body : body } ) ;
}
2015-05-20 15:38:41 -04:00
} ;
2015-12-05 11:47:50 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Triggers mouse constraint events .
* @ method _triggerEvents
* @ private
* @ param { mouse } mouseConstraint
2015-12-05 11:47:50 -05:00
* /
2021-04-11 12:49:36 -04:00
MouseConstraint . _triggerEvents = function ( mouseConstraint ) {
var mouse = mouseConstraint . mouse ,
mouseEvents = mouse . sourceEvents ;
if ( mouseEvents . mousemove )
Events . trigger ( mouseConstraint , 'mousemove' , { mouse : mouse } ) ;
if ( mouseEvents . mousedown )
Events . trigger ( mouseConstraint , 'mousedown' , { mouse : mouse } ) ;
if ( mouseEvents . mouseup )
Events . trigger ( mouseConstraint , 'mouseup' , { mouse : mouse } ) ;
// reset the mouse state ready for the next step
Mouse . clearSourceEvents ( mouse ) ;
2015-12-05 11:47:50 -05:00
} ;
2020-12-26 17:44:24 -05:00
/ *
*
* Events Documentation
*
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired when the mouse has moved ( or a touch moves ) during the last step
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ event mousemove
2020-12-26 17:44:24 -05:00
* @ param { } event An event object
2021-04-11 12:49:36 -04:00
* @ param { mouse } event . mouse The engine ' s mouse instance
2020-12-26 17:44:24 -05:00
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired when the mouse is down ( or a touch has started ) during the last step
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ event mousedown
2020-12-26 17:44:24 -05:00
* @ param { } event An event object
2021-04-11 12:49:36 -04:00
* @ param { mouse } event . mouse The engine ' s mouse instance
2020-12-26 17:44:24 -05:00
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired when the mouse is up ( or a touch has ended ) during the last step
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ event mouseup
2020-12-26 17:44:24 -05:00
* @ param { } event An event object
2021-04-11 12:49:36 -04:00
* @ param { mouse } event . mouse The engine ' s mouse instance
2020-12-26 17:44:24 -05:00
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired when the user starts dragging a body
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ event startdrag
2020-12-26 17:44:24 -05:00
* @ param { } event An event object
2021-04-11 12:49:36 -04:00
* @ param { mouse } event . mouse The engine ' s mouse instance
* @ param { body } event . body The body being dragged
2020-12-26 17:44:24 -05:00
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired when the user ends dragging a body
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ event enddrag
2020-12-26 17:44:24 -05:00
* @ param { } event An event object
2021-04-11 12:49:36 -04:00
* @ param { mouse } event . mouse The engine ' s mouse instance
* @ param { body } event . body The body that has stopped being dragged
2020-12-26 17:44:24 -05:00
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ *
*
* Properties Documentation
*
* /
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* A ` String ` denoting the type of object .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ property type
* @ type string
* @ default "constraint"
* @ readOnly
2020-12-26 17:44:24 -05:00
* /
2014-03-22 13:51:49 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* The ` Mouse ` instance in use . If not supplied in ` MouseConstraint.create ` , one will be created .
2020-12-26 17:44:24 -05:00
*
2021-04-11 12:49:36 -04:00
* @ property mouse
* @ type mouse
* @ default mouse
* /
/ * *
* The ` Body ` that is currently being moved by the user , or ` null ` if no body .
*
* @ property body
* @ type body
* @ default null
* /
/ * *
* The ` Constraint ` object that is used to move the body during interaction .
*
* @ property constraint
* @ type constraint
* /
/ * *
* An ` Object ` that specifies the collision filter properties .
* The collision filter allows the user to define which types of body this mouse constraint can interact with .
* See ` body.collisionFilter ` for more information .
*
* @ property collisionFilter
* @ type object
* /
} ) ( ) ;
/***/ } ) ,
/* 26 */
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
/ * *
* The ` Matter.Query ` module contains methods for performing collision queries .
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Query
* /
var Query = { } ;
module . exports = Query ;
var Vector = _ _webpack _require _ _ ( 2 ) ;
var SAT = _ _webpack _require _ _ ( 14 ) ;
var Bounds = _ _webpack _require _ _ ( 1 ) ;
var Bodies = _ _webpack _require _ _ ( 11 ) ;
var Vertices = _ _webpack _require _ _ ( 3 ) ;
( function ( ) {
/ * *
* Returns a list of collisions between ` body ` and ` bodies ` .
* @ method collides
* @ param { body } body
* @ param { body [ ] } bodies
* @ return { object [ ] } Collisions
* /
Query . collides = function ( body , bodies ) {
var collisions = [ ] ;
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var bodyA = bodies [ i ] ;
if ( Bounds . overlaps ( bodyA . bounds , body . bounds ) ) {
for ( var j = bodyA . parts . length === 1 ? 0 : 1 ; j < bodyA . parts . length ; j ++ ) {
var part = bodyA . parts [ j ] ;
if ( Bounds . overlaps ( part . bounds , body . bounds ) ) {
var collision = SAT . collides ( part , body ) ;
if ( collision . collided ) {
collisions . push ( collision ) ;
break ;
}
}
}
}
}
return collisions ;
} ;
/ * *
* Casts a ray segment against a set of bodies and returns all collisions , ray width is optional . Intersection points are not provided .
* @ method ray
* @ param { body [ ] } bodies
* @ param { vector } startPoint
* @ param { vector } endPoint
* @ param { number } [ rayWidth ]
* @ return { object [ ] } Collisions
2014-03-22 13:51:49 -04:00
* /
2021-04-11 12:49:36 -04:00
Query . ray = function ( bodies , startPoint , endPoint , rayWidth ) {
rayWidth = rayWidth || 1e-100 ;
var rayAngle = Vector . angle ( startPoint , endPoint ) ,
rayLength = Vector . magnitude ( Vector . sub ( startPoint , endPoint ) ) ,
rayX = ( endPoint . x + startPoint . x ) * 0.5 ,
rayY = ( endPoint . y + startPoint . y ) * 0.5 ,
ray = Bodies . rectangle ( rayX , rayY , rayLength , rayWidth , { angle : rayAngle } ) ,
collisions = Query . collides ( ray , bodies ) ;
for ( var i = 0 ; i < collisions . length ; i += 1 ) {
var collision = collisions [ i ] ;
collision . body = collision . bodyB = collision . bodyA ;
}
return collisions ;
} ;
/ * *
* Returns all bodies whose bounds are inside ( or outside if set ) the given set of bounds , from the given set of bodies .
* @ method region
* @ param { body [ ] } bodies
* @ param { bounds } bounds
* @ param { bool } [ outside = false ]
* @ return { body [ ] } The bodies matching the query
* /
Query . region = function ( bodies , bounds , outside ) {
var result = [ ] ;
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ,
overlaps = Bounds . overlaps ( body . bounds , bounds ) ;
if ( ( overlaps && ! outside ) || ( ! overlaps && outside ) )
result . push ( body ) ;
}
return result ;
} ;
/ * *
* Returns all bodies whose vertices contain the given point , from the given set of bodies .
* @ method point
* @ param { body [ ] } bodies
* @ param { vector } point
* @ return { body [ ] } The bodies matching the query
* /
Query . point = function ( bodies , point ) {
var result = [ ] ;
for ( var i = 0 ; i < bodies . length ; i ++ ) {
var body = bodies [ i ] ;
if ( Bounds . contains ( body . bounds , point ) ) {
for ( var j = body . parts . length === 1 ? 0 : 1 ; j < body . parts . length ; j ++ ) {
var part = body . parts [ j ] ;
if ( Bounds . contains ( part . bounds , point )
&& Vertices . contains ( part . vertices , point ) ) {
result . push ( body ) ;
break ;
}
}
}
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
return result ;
} ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 27 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* The ` Matter.Runner ` module is an optional utility which provides a game loop ,
* that handles continuously updating a ` Matter.Engine ` for you within a browser .
* It is intended for development and debugging purposes , but may also be suitable for simple games .
* If you are using your own game loop instead , then you do not need the ` Matter.Runner ` module .
* Instead just call ` Engine.update(engine, delta) ` in your own loop .
2020-12-26 17:44:24 -05:00
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
2021-04-11 12:49:36 -04:00
* @ class Runner
2020-12-26 17:44:24 -05:00
* /
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
var Runner = { } ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
module . exports = Runner ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
var Events = _ _webpack _require _ _ ( 4 ) ;
var Engine = _ _webpack _require _ _ ( 18 ) ;
2020-12-26 17:44:24 -05:00
var Common = _ _webpack _require _ _ ( 0 ) ;
( function ( ) {
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
var _requestAnimationFrame ,
_cancelAnimationFrame ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
if ( typeof window !== 'undefined' ) {
_requestAnimationFrame = window . requestAnimationFrame || window . webkitRequestAnimationFrame
|| window . mozRequestAnimationFrame || window . msRequestAnimationFrame ;
_cancelAnimationFrame = window . cancelAnimationFrame || window . mozCancelAnimationFrame
|| window . webkitCancelAnimationFrame || window . msCancelAnimationFrame ;
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
if ( ! _requestAnimationFrame ) {
var _frameTimeout ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
_requestAnimationFrame = function ( callback ) {
_frameTimeout = setTimeout ( function ( ) {
callback ( Common . now ( ) ) ;
} , 1000 / 60 ) ;
} ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
_cancelAnimationFrame = function ( ) {
clearTimeout ( _frameTimeout ) ;
} ;
}
2014-02-19 09:15:05 -05:00
2021-04-11 12:49:36 -04:00
/ * *
* Creates a new Runner . The options parameter is an object that specifies any properties you wish to override the defaults .
* @ method create
* @ param { } options
* /
Runner . create = function ( options ) {
var defaults = {
fps : 60 ,
correction : 1 ,
deltaSampleSize : 60 ,
counterTimestamp : 0 ,
frameCounter : 0 ,
deltaHistory : [ ] ,
timePrev : null ,
timeScalePrev : 1 ,
frameRequestId : null ,
isFixed : false ,
enabled : true
} ;
var runner = Common . extend ( defaults , options ) ;
runner . delta = runner . delta || 1000 / runner . fps ;
runner . deltaMin = runner . deltaMin || 1000 / runner . fps ;
runner . deltaMax = runner . deltaMax || 1000 / ( runner . fps * 0.5 ) ;
runner . fps = 1000 / runner . delta ;
return runner ;
2014-03-22 13:51:49 -04:00
} ;
2021-04-11 12:49:36 -04:00
2014-03-22 13:51:49 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Continuously ticks a ` Matter.Engine ` by calling ` Runner.tick ` on the ` requestAnimationFrame ` event .
* @ method run
* @ param { engine } engine
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Runner . run = function ( runner , engine ) {
// create runner if engine is first argument
if ( typeof runner . positionIterations !== 'undefined' ) {
engine = runner ;
runner = Runner . create ( ) ;
2014-02-19 09:15:05 -05:00
}
2020-12-26 17:44:24 -05:00
2021-04-11 12:49:36 -04:00
( function render ( time ) {
runner . frameRequestId = _requestAnimationFrame ( render ) ;
if ( time && runner . enabled ) {
Runner . tick ( runner , engine , time ) ;
}
} ) ( ) ;
return runner ;
2014-02-19 09:15:05 -05:00
} ;
2014-02-28 20:10:08 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* A game loop utility that updates the engine and renderer by one step ( a 'tick' ) .
* Features delta smoothing , time correction and fixed or dynamic timing .
* Consider just ` Engine.update(engine, delta) ` if you ' re using your own loop .
* @ method tick
* @ param { runner } runner
* @ param { engine } engine
* @ param { number } time
2014-02-28 20:10:08 -05:00
* /
2021-04-11 12:49:36 -04:00
Runner . tick = function ( runner , engine , time ) {
var timing = engine . timing ,
correction = 1 ,
delta ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
// create an event object
var event = {
timestamp : timing . timestamp
} ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
Events . trigger ( runner , 'beforeTick' , event ) ;
if ( runner . isFixed ) {
// fixed timestep
delta = runner . delta ;
} else {
// dynamic timestep based on wall clock between calls
delta = ( time - runner . timePrev ) || runner . delta ;
runner . timePrev = time ;
// optimistically filter delta over a few frames, to improve stability
runner . deltaHistory . push ( delta ) ;
runner . deltaHistory = runner . deltaHistory . slice ( - runner . deltaSampleSize ) ;
delta = Math . min . apply ( null , runner . deltaHistory ) ;
// limit delta
delta = delta < runner . deltaMin ? runner . deltaMin : delta ;
delta = delta > runner . deltaMax ? runner . deltaMax : delta ;
// correction for delta
correction = delta / runner . delta ;
// update engine timing object
runner . delta = delta ;
}
// time correction for time scaling
if ( runner . timeScalePrev !== 0 )
correction *= timing . timeScale / runner . timeScalePrev ;
if ( timing . timeScale === 0 )
correction = 0 ;
runner . timeScalePrev = timing . timeScale ;
runner . correction = correction ;
2017-11-29 19:16:03 -05:00
2021-04-11 12:49:36 -04:00
// fps counter
runner . frameCounter += 1 ;
if ( time - runner . counterTimestamp >= 1000 ) {
runner . fps = runner . frameCounter * ( ( time - runner . counterTimestamp ) / 1000 ) ;
runner . counterTimestamp = time ;
runner . frameCounter = 0 ;
2014-02-19 09:15:05 -05:00
}
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
Events . trigger ( runner , 'tick' , event ) ;
// update
Events . trigger ( runner , 'beforeUpdate' , event ) ;
Engine . update ( engine , delta , correction ) ;
Events . trigger ( runner , 'afterUpdate' , event ) ;
Events . trigger ( runner , 'afterTick' , event ) ;
2014-02-19 09:15:05 -05:00
} ;
2021-04-11 12:49:36 -04:00
2015-05-20 15:38:41 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* Ends execution of ` Runner.run ` on the given ` runner ` , by canceling the animation frame request event loop .
* If you wish to only temporarily pause the engine , see ` engine.enabled ` instead .
* @ method stop
* @ param { runner } runner
2015-05-20 15:38:41 -04:00
* /
2021-04-11 12:49:36 -04:00
Runner . stop = function ( runner ) {
_cancelAnimationFrame ( runner . frameRequestId ) ;
2020-12-26 17:44:24 -05:00
} ;
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Alias for ` Runner.run ` .
* @ method start
* @ param { runner } runner
* @ param { engine } engine
2020-12-26 17:44:24 -05:00
* /
2021-04-11 12:49:36 -04:00
Runner . start = function ( runner , engine ) {
Runner . run ( runner , engine ) ;
} ;
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ *
*
* Events Documentation
*
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Fired at the start of a tick , before any updates to the engine or timing
*
* @ event beforeTick
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired after engine timing updated , but just before update
*
* @ event tick
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Fired at the end of a tick , after engine update and after rendering
*
* @ event afterTick
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
/ * *
2021-04-11 12:49:36 -04:00
* Fired before update
*
* @ event beforeUpdate
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* Fired after update
*
* @ event afterUpdate
* @ param { } event An event object
* @ param { number } event . timestamp The engine . timing . timestamp of the event
* @ param { } event . source The source object of the event
* @ param { } event . name The name of the event
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ *
*
* Properties Documentation
*
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A flag that specifies whether the runner is running or not .
*
* @ property enabled
* @ type boolean
* @ default true
* /
2015-05-20 15:38:41 -04:00
2021-04-11 12:49:36 -04:00
/ * *
* A ` Boolean ` that specifies if the runner should use a fixed timestep ( otherwise it is variable ) .
* If timing is fixed , then the apparent simulation speed will change depending on the frame rate ( but behaviour will be deterministic ) .
* If the timing is variable , then the apparent simulation speed will be constant ( approximately , but at the cost of determininism ) .
*
* @ property isFixed
* @ type boolean
* @ default false
* /
/ * *
* A ` Number ` that specifies the time step between updates in milliseconds .
* If ` engine.timing.isFixed ` is set to ` true ` , then ` delta ` is fixed .
* If it is ` false ` , then ` delta ` can dynamically change to maintain the correct apparent simulation speed .
*
* @ property delta
* @ type number
* @ default 1000 / 60
* /
2015-05-20 15:38:41 -04:00
2020-12-26 17:44:24 -05:00
} ) ( ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 28 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
/ * *
* The ` Matter.Svg ` module contains methods for converting SVG images into an array of vector points .
*
* To use this module you also need the SVGPathSeg polyfill : https : //github.com/progers/pathseg
*
* See the included usage [ examples ] ( https : //github.com/liabru/matter-js/tree/master/examples).
*
* @ class Svg
* /
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var Svg = { } ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
module . exports = Svg ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
var Bounds = _ _webpack _require _ _ ( 1 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
( function ( ) {
2014-02-19 09:15:05 -05:00
2014-05-01 09:09:06 -04:00
/ * *
2020-12-26 17:44:24 -05:00
* Converts an SVG path into an array of vector points .
* If the input path forms a concave shape , you must decompose the result into convex parts before use .
* See ` Bodies.fromVertices ` which provides support for this .
* Note that this function is not guaranteed to support complex paths ( such as those with holes ) .
* You must load the ` pathseg.js ` polyfill on newer browsers .
* @ method pathToVertices
* @ param { SVGPathElement } path
* @ param { Number } [ sampleLength = 15 ]
* @ return { Vector [ ] } points
2014-05-01 09:09:06 -04:00
* /
2020-12-26 17:44:24 -05:00
Svg . pathToVertices = function ( path , sampleLength ) {
if ( typeof window !== 'undefined' && ! ( 'SVGPathSeg' in window ) ) {
Common . warn ( 'Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.' ) ;
2014-05-05 14:32:51 -04:00
}
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
// https://github.com/wout/svg.topoly.js/blob/master/svg.topoly.js
var i , il , total , point , segment , segments ,
segmentsQueue , lastSegment ,
lastPoint , segmentIndex , points = [ ] ,
lx , ly , length = 0 , x = 0 , y = 0 ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
sampleLength = sampleLength || 15 ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
var addPoint = function ( px , py , pathSegType ) {
// all odd-numbered path types are relative except PATHSEG_CLOSEPATH (1)
var isRelative = pathSegType % 2 === 1 && pathSegType > 1 ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
// when the last point doesn't equal the current point add the current point
if ( ! lastPoint || px != lastPoint . x || py != lastPoint . y ) {
if ( lastPoint && isRelative ) {
lx = lastPoint . x ;
ly = lastPoint . y ;
} else {
lx = 0 ;
ly = 0 ;
}
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
var point = {
x : lx + px ,
y : ly + py
} ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
// set last point
if ( isRelative || ! lastPoint ) {
lastPoint = point ;
}
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
points . push ( point ) ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
x = lx + px ;
y = ly + py ;
2014-05-01 09:09:06 -04:00
}
2020-12-26 17:44:24 -05:00
} ;
2014-05-01 09:09:06 -04:00
2020-12-26 17:44:24 -05:00
var addSegmentPoint = function ( segment ) {
var segType = segment . pathSegTypeAsLetter . toUpperCase ( ) ;
2014-02-19 09:15:05 -05:00
2020-12-26 17:44:24 -05:00
// skip path ends
if ( segType === 'Z' )
return ;
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
// map segment to x and y
switch ( segType ) {
2014-12-28 13:37:43 -05:00
2020-12-26 17:44:24 -05:00
case 'M' :
case 'L' :
case 'T' :
case 'C' :
case 'S' :
case 'Q' :
x = segment . x ;
y = segment . y ;
break ;
case 'H' :
x = segment . x ;
break ;
case 'V' :
y = segment . y ;
break ;
}
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
addPoint ( x , y , segment . pathSegType ) ;
} ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
// ensure path is absolute
Svg . _svgPathToAbsolute ( path ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
// get total length
total = path . getTotalLength ( ) ;
2014-03-22 13:51:49 -04:00
2020-12-26 17:44:24 -05:00
// queue segments
segments = [ ] ;
for ( i = 0 ; i < path . pathSegList . numberOfItems ; i += 1 )
segments . push ( path . pathSegList . getItem ( i ) ) ;
2015-01-20 19:15:04 -05:00
2020-12-26 17:44:24 -05:00
segmentsQueue = segments . concat ( ) ;
2015-01-20 19:15:04 -05:00
2020-12-26 17:44:24 -05:00
// sample through path
while ( length < total ) {
// get segment at position
segmentIndex = path . getPathSegAtLength ( length ) ;
segment = segments [ segmentIndex ] ;
2015-01-20 19:15:04 -05:00
2020-12-26 17:44:24 -05:00
// new segment
if ( segment != lastSegment ) {
while ( segmentsQueue . length && segmentsQueue [ 0 ] != segment )
addSegmentPoint ( segmentsQueue . shift ( ) ) ;
2015-08-12 19:38:20 -04:00
2020-12-26 17:44:24 -05:00
lastSegment = segment ;
}
2015-08-12 19:38:20 -04:00
2020-12-26 17:44:24 -05:00
// add points in between when curving
// TODO: adaptive sampling
switch ( segment . pathSegTypeAsLetter . toUpperCase ( ) ) {
2015-08-12 19:38:20 -04:00
2020-12-26 17:44:24 -05:00
case 'C' :
case 'T' :
case 'S' :
case 'Q' :
case 'A' :
point = path . getPointAtLength ( length ) ;
addPoint ( point . x , point . y , 0 ) ;
break ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
// increment by sample value
length += sampleLength ;
}
2016-05-01 18:54:13 -04:00
2020-12-26 17:44:24 -05:00
// add remaining segments not passed by sampling
for ( i = 0 , il = segmentsQueue . length ; i < il ; ++ i )
addSegmentPoint ( segmentsQueue [ i ] ) ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
return points ;
} ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
Svg . _svgPathToAbsolute = function ( path ) {
// http://phrogz.net/convert-svg-path-to-all-absolute-commands
// Copyright (c) Gavin Kistner
// http://phrogz.net/js/_ReuseLicense.txt
// Modifications: tidy formatting and naming
var x0 , y0 , x1 , y1 , x2 , y2 , segs = path . pathSegList ,
x = 0 , y = 0 , len = segs . numberOfItems ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
for ( var i = 0 ; i < len ; ++ i ) {
var seg = segs . getItem ( i ) ,
segType = seg . pathSegTypeAsLetter ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( /[MLHVCSQTA]/ . test ( segType ) ) {
if ( 'x' in seg ) x = seg . x ;
if ( 'y' in seg ) y = seg . y ;
} else {
if ( 'x1' in seg ) x1 = x + seg . x1 ;
if ( 'x2' in seg ) x2 = x + seg . x2 ;
if ( 'y1' in seg ) y1 = y + seg . y1 ;
if ( 'y2' in seg ) y2 = y + seg . y2 ;
if ( 'x' in seg ) x += seg . x ;
if ( 'y' in seg ) y += seg . y ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
switch ( segType ) {
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
case 'm' :
segs . replaceItem ( path . createSVGPathSegMovetoAbs ( x , y ) , i ) ;
break ;
case 'l' :
segs . replaceItem ( path . createSVGPathSegLinetoAbs ( x , y ) , i ) ;
break ;
case 'h' :
segs . replaceItem ( path . createSVGPathSegLinetoHorizontalAbs ( x ) , i ) ;
break ;
case 'v' :
segs . replaceItem ( path . createSVGPathSegLinetoVerticalAbs ( y ) , i ) ;
break ;
case 'c' :
segs . replaceItem ( path . createSVGPathSegCurvetoCubicAbs ( x , y , x1 , y1 , x2 , y2 ) , i ) ;
break ;
case 's' :
segs . replaceItem ( path . createSVGPathSegCurvetoCubicSmoothAbs ( x , y , x2 , y2 ) , i ) ;
break ;
case 'q' :
segs . replaceItem ( path . createSVGPathSegCurvetoQuadraticAbs ( x , y , x1 , y1 ) , i ) ;
break ;
case 't' :
segs . replaceItem ( path . createSVGPathSegCurvetoQuadraticSmoothAbs ( x , y ) , i ) ;
break ;
case 'a' :
segs . replaceItem ( path . createSVGPathSegArcAbs ( x , y , seg . r1 , seg . r2 , seg . angle , seg . largeArcFlag , seg . sweepFlag ) , i ) ;
break ;
case 'z' :
case 'Z' :
x = x0 ;
y = y0 ;
break ;
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
}
}
2014-06-09 14:40:24 -04:00
2020-12-26 17:44:24 -05:00
if ( segType == 'M' || segType == 'm' ) {
x0 = x ;
y0 = y ;
}
}
} ;
2014-06-09 14:40:24 -04:00
2014-02-19 09:15:05 -05:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } ) ,
2021-04-11 12:49:36 -04:00
/* 29 */
2020-12-26 17:44:24 -05:00
/***/ ( function ( module , exports , _ _webpack _require _ _ ) {
2014-03-22 13:51:49 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* This module has now been replaced by ` Matter.Composite ` .
*
* All usage should be migrated to the equivalent functions found on ` Matter.Composite ` .
* For example ` World.add(world, body) ` now becomes ` Composite.add(world, body) ` .
*
* The property ` world.gravity ` has been moved to ` engine.gravity ` .
2014-03-22 13:51:49 -04:00
*
2021-04-11 12:49:36 -04:00
* For back - compatibility purposes this module will remain as a direct alias to ` Matter.Composite ` in the short term during migration .
* Eventually this alias module will be marked as deprecated and then later removed in a future release .
*
* @ class World
2014-03-22 13:51:49 -04:00
* /
2021-04-11 12:49:36 -04:00
var World = { } ;
2014-03-22 13:51:49 -04:00
2021-04-11 12:49:36 -04:00
module . exports = World ;
2015-08-17 18:50:03 -04:00
2020-12-26 17:44:24 -05:00
var Composite = _ _webpack _require _ _ ( 5 ) ;
var Common = _ _webpack _require _ _ ( 0 ) ;
2015-09-17 13:47:56 -04:00
2014-03-22 13:51:49 -04:00
( function ( ) {
2016-05-01 18:54:13 -04:00
2014-03-22 13:51:49 -04:00
/ * *
2021-04-11 12:49:36 -04:00
* See above , aliases for back compatibility only
2014-03-22 13:51:49 -04:00
* /
2021-04-11 12:49:36 -04:00
World . create = Composite . create ;
World . add = Composite . add ;
World . remove = Composite . remove ;
World . clear = Composite . clear ;
World . addComposite = Composite . addComposite ;
World . addBody = Composite . addBody ;
World . addConstraint = Composite . addConstraint ;
2014-03-22 13:51:49 -04:00
} ) ( ) ;
2020-12-26 17:44:24 -05:00
/***/ } )
/******/ ] ) ;
} ) ;