Majorly improved testing of BaseArg

Majorly improved testing of BaseArg

require "tests/init"

describe "Argument Base", ->
	local Arg, ArgSet, Objects

	before_each ->
		Arg = ulx.Arg!
		ArgSet = ulx.Arg!\Default(123)\Optional!\Hint("my hint")\Help("my help")
		Objects = {123, {}, "hello world", ->}

	it "tests shortcut setters", ->
		assert.equals 123, ArgSet._Default
		assert.equals true, ArgSet._Optional
		assert.equals "my hint", ArgSet._Hint
		assert.equals "my help", ArgSet._Help

		ArgSet\Optional false
		assert.equals false, ArgSet._Optional

		ArgSet\Default nil
		assert.equals nil, ArgSet._Default
		return

	it "tests shortcut errors", ->
		assert.error -> Arg\Optional "apple"
		assert.error -> Arg\Optional {}
		assert.error -> Arg\Hint 41
		assert.error -> Arg\Help(->)
		return

	it "tests UsageShort", ->
		assert.equals "<arg>", Arg\UsageShort!
		assert.equals "[<my hint: default 123>]", ArgSet\UsageShort!
		return

	it "tests UsageLong", ->
		assert.equals [[
Type:     Arg
Hint:     arg
Help:     An arbitrary argument]], Arg\UsageLong!

		assert.equals [[
Type:     Arg
Default:  123 (used if argument is unspecified)
Hint:     my hint
Help:     my help]], ArgSet\UsageLong!
		return

	it "tests Completes", ->
		assert.equal Arg\UsageShort!, Arg\Completes![1]
		assert.equal ArgSet\UsageShort!, ArgSet\Completes![1]
		return

	it "tests IsValid", ->
		pending "determine what this needs to be first"
		return

	it "tests Parse", ->
		for object in *Objects
			assert.equal object, Arg\Parse(object), ArgSet\Parse(object)

		assert.equal nil, Arg\Parse!
		assert.equal 123, ArgSet\Parse!
		return

	it "tests IsPermissible", ->
		objects = {123, {}, "hello world", ->}
		for object in *Objects
			assert.True Arg\IsPermissible(object), ArgSet\IsPermissible(object)
		return

	it "tests Serialize", ->
		assert.equals "", Arg\Serialize!, ArgSet\Serialize!
		return

	it "tests Deserialize", ->
		assert.equals ulx.Arg, moon.type(ulx.Arg.Deserialize!)
		return

-- TODO, same as above for NumArg
	it "NumArg compliance", (using nil) ->
		a = ulx.ArgNum!
		assert.equals("<number: x>", a\UsageShort!)

		a\Optional!
		assert.equals("[<number: x, default 0>]", a\UsageShort!)

		assert.error(-> a\Default("apple"))
		a\Default 41

		assert.same({a\UsageShort!}, a\Completes!)
		assert.equals(
			"Type:     ArgNum\n" ..
			"Default:  41 (used if argument is unspecified)\n" ..
			"Hint:     number\n" ..
			"Help:     A number argument", a\UsageLong!)

		assert.False(a\IsValid("apple"))
		assert.True(a\IsValid(nil))
		assert.False(ulx.ArgNum!\IsValid(nil))
		assert.False(a\Parse("pear"))
		assert.same({true, 41}, {a\Parse(nil)})
		assert.True(a\IsPermissible(3))
		return

require "tests/init"

describe "Test Arguments", (using nil) ->
	it "Base Arg compliance", (using nil) ->
		a = ulx.Arg!
		assert.is_not_nil(a)

		a = ulx.Arg!
		assert.equals("<arg>", a\UsageShort!)

		a\Optional!
		assert.equals("[<arg: default nil>]", a\UsageShort!)

		a\Default(45)\Hint("arg2")
		assert.equals("[<arg2: default 45>]", a\UsageShort!)

		a\Help("this is an arg")

		assert.same({a\UsageShort!}, a\Completes!)
		assert.equals(
			"Type:     Arg\n" ..
			"Default:  45 (used if argument is unspecified)\n" ..
			"Hint:     arg2\n" ..
			"Help:     this is an arg", a\UsageLong!)

		assert.True(a\IsValid("apple"))
		assert.True(a\IsValid(nil))
		assert.False(ulx.Arg!\IsValid(nil))
		assert.equals("pear", a\Parse("pear"))
		assert.equals(45, a\Parse(nil))
		assert.True(a\IsPermissible(false))
		return

	it "NumArg compliance", (using nil) ->
		a = ulx.ArgNum!
		assert.equals("<number: x>", a\UsageShort!)

		a\Optional!
		assert.equals("[<number: x, default 0>]", a\UsageShort!)

		assert.error(-> a\Default("apple"))
		a\Default 41

		assert.same({a\UsageShort!}, a\Completes!)
		assert.equals(
			"Type:     ArgNum\n" ..
			"Default:  41 (used if argument is unspecified)\n" ..
			"Hint:     number\n" ..
			"Help:     A number argument", a\UsageLong!)

		assert.False(a\IsValid("apple"))
		assert.True(a\IsValid(nil))
		assert.False(ulx.ArgNum!\IsValid(nil))
		assert.False(a\Parse("pear"))
		assert.same({true, 41}, {a\Parse(nil)})
		assert.True(a\IsPermissible(3))
		return


More checkups

More checkups

--
-- Copyright (C) 2017 DBot
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

PPM2.TransformNewModelID = (id = 0) ->
    bgID = id % 17
    maneModelID = math.floor(id / 16 - .01) + 1
    maneModelID = 1 if maneModelID == 0
    return maneModelID, bgID

ply.__PPM2_PonyData = nil for ply in *player.GetAll()

class NetworkedPonyData extends PPM2.NetworkedObject
    @NW_ClientsideCreation = true

    @Setup()
    @NetworkVar('Entity',           net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('UpperManeModel',   net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('LowerManeModel',   net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('TailModel',        net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('SocksModel',       net.ReadEntity, net.WriteEntity, NULL)

    @NetworkVar('Race',             (-> math.Clamp(net.ReadUInt(4), 0, 3)), ((arg = PPM2.RACE_EARTH) -> net.WriteUInt(arg, 4)), PPM2.RACE_EARTH)
    @NetworkVar('Gender',           (-> math.Clamp(net.ReadUInt(4), 0, 1)), ((arg = PPM2.GENDER_FEMALE) -> net.WriteUInt(arg, 4)), PPM2.GENDER_FEMALE)
    @NetworkVar('Weight',           (-> math.Clamp(net.ReadFloat(), PPM2.MIN_WEIGHT, PPM2.MAX_WEIGHT)), net.WriteFloat, 1)

    -- Reserved - they can be accessed/used/changed, but they do not do anything
    @NetworkVar('Age',              (-> math.Clamp(net.ReadUInt(4), 0, 2)), ((arg = PPM2.AGE_ADULT) -> net.WriteUInt(arg, 4)), PPM2.AGE_ADULT)

    @NetworkVar('EyelashType',      (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_EYELASHES, PPM2.MAX_EYELASHES)),           ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('TailType',         (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_TAILS, PPM2.MAX_TAILS)),                   ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeType',         (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_UPPER_MANES, PPM2.MAX_UPPER_MANES)),       ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeTypeLower',    (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_LOWER_MANES, PPM2.MAX_LOWER_MANES)),       ((arg = 0) -> net.WriteUInt(arg, 8)), 0)

    @NetworkVar('TailTypeNew',      (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_TAILS_NEW, PPM2.MAX_TAILS_NEW)),               ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeTypeNew',      (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_UPPER_MANES_NEW, PPM2.MAX_UPPER_MANES_NEW)),   ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeTypeLowerNew', (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_LOWER_MANES_NEW, PPM2.MAX_LOWER_MANES_NEW)),   ((arg = 0) -> net.WriteUInt(arg, 8)), 0)

    @NetworkVar('BodyColor',        net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))

    @NetworkVar('SeparateEyes',     net.ReadBool, net.WriteBool,              false)
    for publicName in *{'', 'Left', 'Right'}
        @NetworkVar("EyeType#{publicName}",          (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_EYE_TYPE, PPM2.MAX_EYE_TYPE)), ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
        @NetworkVar("EyeBackground#{publicName}",    net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))
        @NetworkVar("EyeHole#{publicName}",          net.ReadColor, net.WriteColor, 	    Color(0,   0,   0  ))
        @NetworkVar("EyeIrisTop#{publicName}",       net.ReadColor, net.WriteColor, 	    Color(200, 200, 200))
        @NetworkVar("EyeIrisBottom#{publicName}",    net.ReadColor, net.WriteColor, 	    Color(200, 200, 200))
        @NetworkVar("EyeIrisLine1#{publicName}",     net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))
        @NetworkVar("EyeIrisLine2#{publicName}",     net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))
        @NetworkVar("EyeReflection#{publicName}",    net.ReadColor, net.WriteColor,    Color(255, 255, 255, 127))
        @NetworkVar("EyeEffect#{publicName}",        net.ReadColor, net.WriteColor,         Color(255, 255, 255))
        @NetworkVar("EyeLines#{publicName}",         net.ReadBool, net.WriteBool,                           true)
        @NetworkVar("DerpEyes#{publicName}",         net.ReadBool, net.WriteBool,                          false)
        @NetworkVar("DerpEyesStrength#{publicName}", (-> math.Clamp(net.ReadFloat(), PPM2.MIN_DERP_STRENGTH, PPM2.MAX_DERP_STRENGTH)), net.WriteFloat, 1)
        @NetworkVar("HoleWidth#{publicName}",        (-> math.Clamp(net.ReadFloat(), PPM2.MIN_PUPIL_SIZE, PPM2.MAX_PUPIL_SIZE)), net.WriteFloat, 1)
        @NetworkVar("HoleSize#{publicName}",         (-> math.Clamp(net.ReadFloat(), PPM2.MIN_HOLE, PPM2.MAX_HOLE)),             net.WriteFloat, .8)
        @NetworkVar("IrisSize#{publicName}",         (-> math.Clamp(net.ReadFloat(), PPM2.MIN_IRIS, PPM2.MAX_IRIS)),             net.WriteFloat, .8)

    @NetworkVar('SeparateMane',     net.ReadBool, net.WriteBool,              false)
    for i = 1, 6
        @NetworkVar("ManeColor#{i}",            net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("ManeDetailColor#{i}",      net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("ManeURLColor#{i}",         net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("ManeURL#{i}",              net.ReadString, net.WriteString,   '')

        @NetworkVar("TailColor#{i}",            net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("TailDetailColor#{i}",      net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("TailURLColor#{i}",         net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("TailURL#{i}",              net.ReadString, net.WriteString,   '')

        @NetworkVar("LowerManeColor#{i}",       net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("LowerManeURL#{i}",         net.ReadString, net.WriteString,   '')
        @NetworkVar("LowerManeURLColor#{i}",    net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("LowerManeDetailColor#{i}", net.ReadColor, net.WriteColor,     Color(255, 255, 255))

        @NetworkVar("UpperManeColor#{i}",       net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("UpperManeURL#{i}",         net.ReadString, net.WriteString,   '')
        @NetworkVar("UpperManeDetailColor#{i}", net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("UpperManeURLColor#{i}",    net.ReadColor, net.WriteColor,     Color(255, 255, 255))

    @NetworkVar('CMark',            net.ReadBool, net.WriteBool,              true)
    @NetworkVar('CMarkURL',         net.ReadString, net.WriteString,            '')
    @NetworkVar('CMarkType',        (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_CMARK, PPM2.MAX_CMARK)),           ((arg = 4) -> net.WriteUInt(arg, 8)), 4)
    @NetworkVar('TailSize',         (-> math.Clamp(net.ReadFloat(), PPM2.MIN_TAIL_SIZE, PPM2.MAX_TAIL_SIZE)),   net.WriteFloat, 1)

    @NetworkVar('Bodysuit',         (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_SUIT, PPM2.MAX_SUIT)),             ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('Socks',            net.ReadBool, net.WriteBool,              false)
    @NetworkVar('NoFlex',           net.ReadBool, net.WriteBool,              false)
    @NetworkVar('SocksAsModel',     net.ReadBool, net.WriteBool,              false)
    @NetworkVar('SocksColor',       net.ReadColor, net.WriteColor,            Color(255, 255, 255))

    @NetworkVar('BatPonyEars',      net.ReadBool, net.WriteBool,              false)
    @NetworkVar('Fangs',            net.ReadBool, net.WriteBool,              false)
    @NetworkVar('ClawTeeth',        net.ReadBool, net.WriteBool,              false)

    for {:flex, :active} in *PPM2.PonyFlexController.FLEX_LIST
        @NetworkVar("DisableFlex#{flex}", net.ReadBool, net.WriteBool, false) if active

    for i = 1, PPM2.MAX_BODY_DETAILS
        @NetworkVar("BodyDetail#{i}",       (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_DETAIL, PPM2.MAX_DETAIL)), ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
        @NetworkVar("BodyDetailColor#{i}",  net.ReadColor,  net.WriteColor, Color(255, 255, 255))
        @NetworkVar("BodyDetailURL#{i}",    net.ReadString, net.WriteString, '')
        @NetworkVar("BodyDetailURLColor#{i}",  net.ReadColor,  net.WriteColor, Color(255, 255, 255))

    new: (netID, ent) =>
        @recomputeTextures = true
        @isValid = true
        if ent
            @modelCached = ent\GetModel()
            @SetEntity(ent)
            @SetupEntity(ent)
        super(netID)
    IsValid: => @isValid
    GetModel: => @modelCached
    EntIndex: => @entID
    SetupEntity: (ent) =>
        return unless IsValid(ent)
        @modelCached = ent\GetModel()
        @ent = ent
        ent.__PPM2_PonyData\Remove() if ent.__PPM2_PonyData and ent.__PPM2_PonyData.Remove and ent.__PPM2_PonyData ~= @
        ent.__PPM2_PonyData = @
        @entID = ent\EntIndex()
        @ModelChanges(@modelCached, @modelCached)
        if CLIENT
            timer.Simple 0, ->
                @GetRenderController()\CompileTextures() if @GetRenderController()
    ModelChanges: (old = @ent\GetModel(), new = old) =>
        @modelCached = new
        timer.Simple 0.5, ->
            return unless IsValid(@ent)
            @GetBodygroupController()\ApplyBodygroups() if @GetBodygroupController()
            if CLIENT
                @GetRenderController()
                @GetWeightController()
    GenericDataChange: (state) =>
        if state\GetKey() == 'Entity' and IsValid(@GetEntity())
            @SetupEntity(@GetEntity())

        @GetBodygroupController()\DataChanges(state) if @ent

        if CLIENT and @ent
            @GetWeightController()\DataChanges(state) if @GetWeightController()
            @GetRenderController()\DataChanges(state) if @GetRenderController()
    Think: =>
    PlayerRespawn: =>
        if CLIENT
            @GetWeightController()\UpdateWeight() if @GetWeightController()
            @GetRenderController()\PlayerRespawn() if @GetRenderController()
    ApplyBodygroups: => @GetBodygroupController()\ApplyBodygroups() if @ent
    SetLocalChange: (state) => @GenericDataChange(state)
    NetworkDataChanges: (state) => @GenericDataChange(state)
    GetRenderController: =>
        return if SERVER
        return @renderController if not @isValid
        if not @renderController or @modelCached ~= @modelRender
            @modelRender = @modelCached
            cls = PPM2.GetRenderController(@modelCached)
            if @renderController and cls == @renderController.__class
                @renderController.ent = @ent
                return @renderController
            @renderController\Remove() if @renderController
            @renderController = cls(@)
        @renderController.ent = @ent
        return @renderController
    GetWeightController: =>
        return if SERVER
        return @weightController if not @isValid
        if not @weightController or @modelCached ~= @modelWeight
            @modelCached = @modelCached or @ent\GetModel()
            @modelWeight = @modelCached
            cls = PPM2.GetPonyWeightController(@modelCached)
            if @weightController and cls == @weightController.__class
                @weightController.ent = @ent
                return @weightController
            @weightController\Remove() if @weightController
            @weightController = cls(@)
        @weightController.ent = @ent
        return @weightController
    GetBodygroupController: =>
        return @bodygroups if not @isValid
        if not @bodygroups or @modelBodygroups ~= @modelCached
            @modelCached = @modelCached or @ent\GetModel()
            @modelBodygroups = @modelCached
            cls = PPM2.GetBodugroupController(@modelCached)
            if @bodygroups and cls == @bodygroups.__class
                @bodygroups.ent = @ent
                return @bodygroups
            @bodygroups\Remove() if @bodygroups
            @bodygroups = cls(@)
        @bodygroups.ent = @ent
        return @bodygroups
    Remove: (byClient = false) =>
        @isValid = false
        @ent.__PPM2_PonyData = nil if IsValid(@ent) and @ent.__PPM2_PonyData == @
        if CLIENT
            @GetWeightController()\Remove()
            @GetRenderController()\Remove()
        @GetBodygroupController()\Remove()
    __tostring: => "[#{@@__name}:#{@netID}|#{@ent}]"

PPM2.NetworkedPonyData = NetworkedPonyData

entMeta = FindMetaTable('Entity')
entMeta.GetPonyData = =>
    if @__PPM2_PonyData and @__PPM2_PonyData\GetEntity() ~= @
        @__PPM2_PonyData\SetEntity(@)
        @__PPM2_PonyData\SetupEntity(@) if CLIENT
    return @__PPM2_PonyData

--
-- Copyright (C) 2017 DBot
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

PPM2.TransformNewModelID = (id = 0) ->
    bgID = id % 17
    maneModelID = math.floor(id / 16 - .01) + 1
    maneModelID = 1 if maneModelID == 0
    return maneModelID, bgID

OLD_NW_OBJECTS = {}

for ply in *player.GetAll()
    break if not ply.GetPonyData
    if ply\GetPonyData()
        table.insert(OLD_NW_OBJECTS, ply\GetPonyData())

class NetworkedPonyData extends PPM2.NetworkedObject
    @NW_ClientsideCreation = true

    @Setup()
    @NetworkVar('Entity',           net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('UpperManeModel',   net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('LowerManeModel',   net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('TailModel',        net.ReadEntity, net.WriteEntity, NULL)
    @NetworkVar('SocksModel',       net.ReadEntity, net.WriteEntity, NULL)

    @NetworkVar('Race',             (-> math.Clamp(net.ReadUInt(4), 0, 3)), ((arg = PPM2.RACE_EARTH) -> net.WriteUInt(arg, 4)), PPM2.RACE_EARTH)
    @NetworkVar('Gender',           (-> math.Clamp(net.ReadUInt(4), 0, 1)), ((arg = PPM2.GENDER_FEMALE) -> net.WriteUInt(arg, 4)), PPM2.GENDER_FEMALE)
    @NetworkVar('Weight',           (-> math.Clamp(net.ReadFloat(), PPM2.MIN_WEIGHT, PPM2.MAX_WEIGHT)), net.WriteFloat, 1)

    -- Reserved - they can be accessed/used/changed, but they do not do anything
    @NetworkVar('Age',              (-> math.Clamp(net.ReadUInt(4), 0, 2)), ((arg = PPM2.AGE_ADULT) -> net.WriteUInt(arg, 4)), PPM2.AGE_ADULT)

    @NetworkVar('EyelashType',      (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_EYELASHES, PPM2.MAX_EYELASHES)),           ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('TailType',         (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_TAILS, PPM2.MAX_TAILS)),                   ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeType',         (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_UPPER_MANES, PPM2.MAX_UPPER_MANES)),       ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeTypeLower',    (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_LOWER_MANES, PPM2.MAX_LOWER_MANES)),       ((arg = 0) -> net.WriteUInt(arg, 8)), 0)

    @NetworkVar('TailTypeNew',      (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_TAILS_NEW, PPM2.MAX_TAILS_NEW)),               ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeTypeNew',      (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_UPPER_MANES_NEW, PPM2.MAX_UPPER_MANES_NEW)),   ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('ManeTypeLowerNew', (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_LOWER_MANES_NEW, PPM2.MAX_LOWER_MANES_NEW)),   ((arg = 0) -> net.WriteUInt(arg, 8)), 0)

    @NetworkVar('BodyColor',        net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))

    @NetworkVar('SeparateEyes',     net.ReadBool, net.WriteBool,              false)
    for publicName in *{'', 'Left', 'Right'}
        @NetworkVar("EyeType#{publicName}",          (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_EYE_TYPE, PPM2.MAX_EYE_TYPE)), ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
        @NetworkVar("EyeBackground#{publicName}",    net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))
        @NetworkVar("EyeHole#{publicName}",          net.ReadColor, net.WriteColor, 	    Color(0,   0,   0  ))
        @NetworkVar("EyeIrisTop#{publicName}",       net.ReadColor, net.WriteColor, 	    Color(200, 200, 200))
        @NetworkVar("EyeIrisBottom#{publicName}",    net.ReadColor, net.WriteColor, 	    Color(200, 200, 200))
        @NetworkVar("EyeIrisLine1#{publicName}",     net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))
        @NetworkVar("EyeIrisLine2#{publicName}",     net.ReadColor, net.WriteColor, 	    Color(255, 255, 255))
        @NetworkVar("EyeReflection#{publicName}",    net.ReadColor, net.WriteColor,    Color(255, 255, 255, 127))
        @NetworkVar("EyeEffect#{publicName}",        net.ReadColor, net.WriteColor,         Color(255, 255, 255))
        @NetworkVar("EyeLines#{publicName}",         net.ReadBool, net.WriteBool,                           true)
        @NetworkVar("DerpEyes#{publicName}",         net.ReadBool, net.WriteBool,                          false)
        @NetworkVar("DerpEyesStrength#{publicName}", (-> math.Clamp(net.ReadFloat(), PPM2.MIN_DERP_STRENGTH, PPM2.MAX_DERP_STRENGTH)), net.WriteFloat, 1)
        @NetworkVar("HoleWidth#{publicName}",        (-> math.Clamp(net.ReadFloat(), PPM2.MIN_PUPIL_SIZE, PPM2.MAX_PUPIL_SIZE)), net.WriteFloat, 1)
        @NetworkVar("HoleSize#{publicName}",         (-> math.Clamp(net.ReadFloat(), PPM2.MIN_HOLE, PPM2.MAX_HOLE)),             net.WriteFloat, .8)
        @NetworkVar("IrisSize#{publicName}",         (-> math.Clamp(net.ReadFloat(), PPM2.MIN_IRIS, PPM2.MAX_IRIS)),             net.WriteFloat, .8)

    @NetworkVar('SeparateMane',     net.ReadBool, net.WriteBool,              false)
    for i = 1, 6
        @NetworkVar("ManeColor#{i}",            net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("ManeDetailColor#{i}",      net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("ManeURLColor#{i}",         net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("ManeURL#{i}",              net.ReadString, net.WriteString,   '')

        @NetworkVar("TailColor#{i}",            net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("TailDetailColor#{i}",      net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("TailURLColor#{i}",         net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("TailURL#{i}",              net.ReadString, net.WriteString,   '')

        @NetworkVar("LowerManeColor#{i}",       net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("LowerManeURL#{i}",         net.ReadString, net.WriteString,   '')
        @NetworkVar("LowerManeURLColor#{i}",    net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("LowerManeDetailColor#{i}", net.ReadColor, net.WriteColor,     Color(255, 255, 255))

        @NetworkVar("UpperManeColor#{i}",       net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("UpperManeURL#{i}",         net.ReadString, net.WriteString,   '')
        @NetworkVar("UpperManeDetailColor#{i}", net.ReadColor, net.WriteColor,     Color(255, 255, 255))
        @NetworkVar("UpperManeURLColor#{i}",    net.ReadColor, net.WriteColor,     Color(255, 255, 255))

    @NetworkVar('CMark',            net.ReadBool, net.WriteBool,              true)
    @NetworkVar('CMarkURL',         net.ReadString, net.WriteString,            '')
    @NetworkVar('CMarkType',        (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_CMARK, PPM2.MAX_CMARK)),           ((arg = 4) -> net.WriteUInt(arg, 8)), 4)
    @NetworkVar('TailSize',         (-> math.Clamp(net.ReadFloat(), PPM2.MIN_TAIL_SIZE, PPM2.MAX_TAIL_SIZE)),   net.WriteFloat, 1)

    @NetworkVar('Bodysuit',         (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_SUIT, PPM2.MAX_SUIT)),             ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
    @NetworkVar('Socks',            net.ReadBool, net.WriteBool,              false)
    @NetworkVar('NoFlex',           net.ReadBool, net.WriteBool,              false)
    @NetworkVar('SocksAsModel',     net.ReadBool, net.WriteBool,              false)
    @NetworkVar('SocksColor',       net.ReadColor, net.WriteColor,            Color(255, 255, 255))

    @NetworkVar('BatPonyEars',      net.ReadBool, net.WriteBool,              false)
    @NetworkVar('Fangs',            net.ReadBool, net.WriteBool,              false)
    @NetworkVar('ClawTeeth',        net.ReadBool, net.WriteBool,              false)

    for {:flex, :active} in *PPM2.PonyFlexController.FLEX_LIST
        @NetworkVar("DisableFlex#{flex}", net.ReadBool, net.WriteBool, false) if active

    for i = 1, PPM2.MAX_BODY_DETAILS
        @NetworkVar("BodyDetail#{i}",       (-> math.Clamp(net.ReadUInt(8), PPM2.MIN_DETAIL, PPM2.MAX_DETAIL)), ((arg = 0) -> net.WriteUInt(arg, 8)), 0)
        @NetworkVar("BodyDetailColor#{i}",  net.ReadColor,  net.WriteColor, Color(255, 255, 255))
        @NetworkVar("BodyDetailURL#{i}",    net.ReadString, net.WriteString, '')
        @NetworkVar("BodyDetailURLColor#{i}",  net.ReadColor,  net.WriteColor, Color(255, 255, 255))

    new: (netID, ent) =>
        @recomputeTextures = true
        @isValid = true
        if ent
            @modelCached = ent\GetModel()
            @SetEntity(ent)
            @SetupEntity(ent)
        super(netID)
    IsValid: => @isValid
    GetModel: => @modelCached
    EntIndex: => @entID
    SetupEntity: (ent) =>
        return unless IsValid(ent)
        @modelCached = ent\GetModel()
        @ent = ent
        ent.__PPM2_PonyData\Remove() if ent.__PPM2_PonyData and ent.__PPM2_PonyData.Remove and ent.__PPM2_PonyData ~= @
        ent.__PPM2_PonyData = @
        @entID = ent\EntIndex()
        @ModelChanges(@modelCached, @modelCached)
        if CLIENT
            timer.Simple(0, ->
                @GetRenderController()\CompileTextures()
            )
    ModelChanges: (old = @ent\GetModel(), new = old) =>
        @modelCached = new
        timer.Simple 0.5, ->
            return unless IsValid(@ent)
            @GetBodygroupController()\ApplyBodygroups()
            if CLIENT
                @GetRenderController()
                @GetWeightController()
    GenericDataChange: (state) =>
        if state\GetKey() == 'Entity' and IsValid(@GetEntity())
            @SetupEntity(@GetEntity())

        @GetBodygroupController()\DataChanges(state) if @ent

        if CLIENT and @ent
            @GetWeightController()\DataChanges(state)
            @GetRenderController()\DataChanges(state)
    Think: =>
    PlayerRespawn: =>
        if CLIENT
            @GetWeightController()\UpdateWeight()
            @GetRenderController()\PlayerRespawn()
    ApplyBodygroups: => @GetBodygroupController()\ApplyBodygroups() if @ent
    SetLocalChange: (state) => @GenericDataChange(state)
    NetworkDataChanges: (state) => @GenericDataChange(state)
    GetRenderController: =>
        return if SERVER
        if not @renderController or @modelCached ~= @modelRender
            cls = PPM2.GetRenderController(@modelCached)
            @modelRender = @modelCached
            @renderController = cls(@)
        @renderController.ent = @ent
        return @renderController
    GetWeightController: =>
        return if SERVER
        if not @weightController or @modelCached ~= @modelWeight
            cls = PPM2.GetPonyWeightController(@modelCached)
            @modelWeight = @modelCached
            @weightController = cls(@)
        @weightController.ent = @ent
        return @weightController
    GetBodygroupController: =>
        if not @bodygroups or @modelBodygroups ~= @modelCached
            @modelCached = @modelCached or @ent\GetModel()
            cls = PPM2.GetBodugroupController(@modelCached)
            @bodygroups = cls(@)
            @modelBodygroups = @modelCached
        @bodygroups.ent = @ent
        return @bodygroups
    Remove: (byClient = false) =>
        @isValid = false
        @ent.__PPM2_PonyData = nil if IsValid(@ent) and @ent.__PPM2_PonyData == @
        if CLIENT
            @GetWeightController()\Remove()
            @GetRenderController()\Remove()
        @GetBodygroupController()\Remove()
    __tostring: => "[#{@@__name}:#{@netID}|#{@ent}]"

for obj in *OLD_NW_OBJECTS
    obj.__class = NetworkedPonyData
    NetworkedPonyData.NW_Objects[obj.netID] = obj if obj.netID >= 0
OLD_NW_OBJECTS = nil

PPM2.NetworkedPonyData = NetworkedPonyData

entMeta = FindMetaTable('Entity')
entMeta.GetPonyData = =>
    if @__PPM2_PonyData and @__PPM2_PonyData\GetEntity() ~= @
        @__PPM2_PonyData\SetEntity(@)
        @__PPM2_PonyData\SetupEntity(@) if CLIENT
    return @__PPM2_PonyData


Fixes and updates to Scene

Fixes and updates to Scene

* Fix the LP.screen.mouseX and mouseY are function calls, not variables
* Shorten removeAll to use @remove
* Change order for addList and removeList for loop

require "LunoPunk.Tweener"

export ^

class Scene extends Tweener
	new: =>
		super!
		@camera = nil
		@visible = true
		-- private
		@__typeFirst = {}
		@__typeCount = {}
		@__count = 0
		@__classCount = {}
		@__entityNames = {}
		@__farthest = nil
		@__first = nil
		@__layerFarthest = nil
		@__layerNearest = nil
		@__layers = nil
		@__layerList = {}
		@__layerCount = {}
		@__add = {}
		@__remove = {}
		@__recycle = {}
		@__recycled = {}
		@__nearest = nil
		@__sprite = nil
		@__uniqueTypes = nil
		@__updateFirst = nil
		@__renderFirst = {}
		@__renderLast = {}

	-- Override this; called when Scene is switch to, and set to the currently active scene.
	begin: =>

	-- Override this; called when Scene is changed, and the active scene is no longer this.
	-- Changed from end because of issues with the name "end" in Lua
	endScene: =>

	-- Override this, called when game gains focus
	focusGained: =>

	-- Override this, called when game loses focus
	focusLost: =>

	-- Performed by the game loop, updates all contained Entities.
	-- If you override this to give your Scene update code, remember
	-- to call super.update() or your Entities will not be updated.
	update: =>
		e = @__updateFirst
		while e != nil
			if e.active
				e\updateTweens! if e\hasTween!
				e\update!
			e\graphic!\update! if e\graphic! != nil and e\graphic!.active
			e = e.__updateNext

	-- Performed by the game loop, renders all contained Entities.
	-- If you override this to give your Scene render code, remember
	-- to call super.render() or your Entities will not be rendered.
	render: =>
		if @__layerSort
			@__layerList\sort @__layerSort if #@__layerList > 1

		-- if LP.renderMode == RenderMode.Hardware
			-- clearSprites!
			-- AtlasData.setScene(@)

		for layer in *@__layerList do
			e = @__renderLast[layer]
			while e != nil
				e\render! if e.visible
				e = e.__renderPrev

		-- AtlasData\render! if LP.renderMode == RenderMode.Hardware

	-- X position of the mouse in the Scene.
	mouseX: => LP.screen.mouseX! + @camera.x

	-- Y position of the mouse in the Scene.
	mouseY: => LP.screen.mouseY! + @camera.y

	-- Sprite used to store layer sprites when RenderMode.HARDWARE is set.
	sprite: => @__sprite

	-- Adds the Entity to the Scene at the end of the frame.
	-- @param	e		Entity object you want to add.
	-- @return	The added Entity object.
	add: (e) =>
		@__add[#@__add + 1] = e
		e

	-- Removes the Entity from the Scene at the end of the frame.
	-- @param	e		Entity object you want to remove.
	-- @return	The removed Entity object.
	remove: (e) =>
		@__remove[#@__remove + 1] = e
		e

	-- Removes all Entities from the Scene at the end of the frame.
	removeAll: =>
		e = @__updateFirst
		while e != nil
			e = @remove(e).__updateNext

	-- Adds multiple Entities to the scene.
	-- @param	...list		Several Entities (as arguments) or an Array/Vector of Entities.
	addList: (list) =>
		@add e for e in *list

	-- Removes multiple Entities from the scene.
	-- @param	...list		Several Entities (as arguments) or an Array/Vector of Entities.
	removeList: (list) =>
		@remove e for e in *list

	-- Adds an Entity to the Scene with the Graphic object.
	-- @param	graphic		Graphic to assign the Entity.
	-- @param	x			X position of the Entity.
	-- @param	y			Y position of the Entity.
	-- @param	layer		Layer of the Entity.
	-- @return	The Entity that was added.
	addGraphic: (graphic, layer = LP.BASELAYER!, x = 0, y = 0) =>
		e = Entity x, y, graphic

		e.layer = layer if layer != LP.BASELAYER!
		e.active = false

		@add e

	-- Adds an Entity to the Scene with the Mask object.
	-- @param	mask	Mask to assign the Entity.
	-- @param	type	Collision type of the Entity.
	-- @param	x		X position of the Entity.
	-- @param	y		Y position of the Entity.
	-- @return	The Entity that was added.
	addMask: (mask, type, x = 0, y = 0) =>
		e = Entity x, y, nil, mask

		e.type = type if type != ""
		e.active, e.visable = false, false

		@add e

	-- Returns a new Entity, or a stored recycled Entity if one exists.
	-- @param	classType			The Class of the Entity you want to add.
	-- @param	addToScene			Add it to the Scene immediately.
	-- @param	constructorsArgs	List of the entity constructor arguments (optional).
	-- @return	The new Entity object.
	create: (classType, addToScene = true, ...) =>
		className = classType.__class.__name
		e = @__recycle[className]
		if e != nil
			@__recycle[className] = e.__recycleNext
			e.__recycleNext = nil
		else
			e = classType ...

		return @add e if addToScene

		e

	-- Removes the Entity from the Scene at the end of the frame and recycles it.
	-- The recycled Entity can then be fetched again by calling the create() function.
	-- @param	e		The Entity to recycle.
	-- @return	The recycled Entity.
	recycle: (e) =>
		@__recycle[#@__recycle + 1] = e
		@remove e

	-- Clears stored reycled Entities of the Class type.
	-- @param	classType		The Class type to clear.
	clearRecycled: (classType) =>
		idx = 0
		for i = 1, #@__recycle do
			if @__recycle[i].__class == classType
				idx = i
				break

		e = @__recycle[idx]
		n = nil
		while e != nil
			n = e.__recycleNext
			e.__recycleNext = nil
			e = n
		table.remove @__recycle, idx
		return

	-- Clears stored recycled Entities of all Class types.
	clearRecycledAll: =>
		for e in *@__recycle do
			@clearRecycled e.__class

	-- Brings the Entity to the front of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	bringToFront: (e) =>

	-- Sends the Entity to the back of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	sendToBack: (e) =>

	-- Shifts the Entity one place towards the front of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	bringForward: (e) =>

	-- Shifts the Entity one place towards the back of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	sendBackward: (e) =>

	-- If the Entity as at the front of its layer.
	-- @param	e		The Entity to check.
	-- @return	True or false.
	isAtFront: (e) =>

	-- If the Entity as at the back of its layer.
	-- @param	e		The Entity to check.
	-- @return	True or false.
	isAtBack: (e) =>

	-- Returns the first Entity that collides with the rectangular area.
	-- @param	type		The Entity type to check for.
	-- @param	rX			X position of the rectangle.
	-- @param	rY			Y position of the rectangle.
	-- @param	rWidth		Width of the rectangle.
	-- @param	rHeight		Height of the rectangle.
	-- @return	The first Entity to collide, or null if none collide.
	collideRect: (type, rX, rY, rWidth, rHeight) =>
		e = @__typeFirst[type]
		while e != nil
			return e if e.collidable and e\collideRect e.x, e.y, rX, rY, rWidth, rHeight
			e = e.__typeNext

		return nil

	-- Returns the first Entity found that collides with the position.
	-- @param	type		The Entity type to check for.
	-- @param	pX			X position.
	-- @param	pY			Y position.
	-- @return	The collided Entity, or null if none collide.
	collidePoint: (type, pX, pY) =>
		e = @__typeFirst[type]
		result = nil
		while e != nil
			-- only look for entities that collide
			if e.collidable and e\collidePoint e.x, e.y, pX, pY
				-- the first one must be the front one
				if result == nil
					result = e
				-- compare if the new collided entity is above the former one (lower valuer is toward, higher value is backward)
				else if e.layer < result.layer
					result = e

			e = e.__typeNext

		return result

	-- Returns the first Entity found that collides with the line.
	-- @param	type		The Entity type to check for.
	-- @param	fromX		Start x of the line.
	-- @param	fromY		Start y of the line.
	-- @param	toX			End x of the line.
	-- @param	toY			End y of the line.
	-- @param	precision   Distance between consecutive tests. Higher values are faster but increase the chance of missing collisions.
	-- @param	p           If non-null, will have its x and y values set to the point of collision.
	-- @return	The first Entity to collide, or null if none collide.
	collideLine: (type, fromX, fromY, toX, toY, precision, p) =>

	-- Populates an array with all Entities that collide with the rectangle. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type		The Entity type to check for.
	-- @param	rX			X position of the rectangle.
	-- @param	rY			Y position of the rectangle.
	-- @param	rWidth		Width of the rectangle.
	-- @param	rHeight		Height of the rectangle.
	-- @param	into		The Array or Vector to populate with collided Entities.
	collideRectInto: (type, rX, rY, rWidth, rHeight, into = {}) =>
		e = @__typeFirst[type]
		n = #into
		while e != nil
			if e.collidable and e\collideRect e.x, e.y, rX, rY, rWidth, rHeight
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Populates an array with all Entities that collide with the circle. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type 		The Entity type to check for.
	-- @param	circleX		X position of the circle.
	-- @param	circleY		Y position of the circle.
	-- @param	radius		The radius of the circle.
	-- @param	into		The Array or Vector to populate with collided Entities.
	collideCircleInto: (type, circleX, circleY, radius, into = {}) =>
		e = @__typeFirst[type]
		n = #into
		radius *= radius -- square it to avoid the square root
		while e != nil
			if LP.distanceSquared circleX, circleY, e.x, e.y < radius
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Populates an array with all Entities that collide with the position. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type		The Entity type to check for.
	-- @param	pX			X position.
	-- @param	pY			Y position.
	-- @param	into		The Array or Vector to populate with collided Entities.
	collidePointInto: (type, pX, pY, into) =>
		e = @__typeFirst[type]
		n = #into

		while e != nil
			if e.collidable and e\collidePoint e.x, e.y, pX, pY
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Finds the Entity nearest to the rectangle.
	-- @param	type		The Entity type to check for.
	-- @param	x			X position of the rectangle.
	-- @param	y			Y position of the rectangle.
	-- @param	width		Width of the rectangle.
	-- @param	height		Height of the rectangle.
	-- @return	The nearest Entity to the rectangle.
	nearestToRect: (type, x, y, width, height) =>
		e = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil

		while e != nil
			dist = squareRects x, y, width, height, e.x - e.originX, e.y - e.originY, e.width, e.height
			if dist < nearDist
				nearDist = dist
				near = e

			e = e.__typeNext

		return near

	-- Finds the Entity nearest to another.
	-- @param	type		The Entity type to check for.
	-- @param	e			The Entity to find the nearest to.
	-- @param	useHitboxes	If the Entities' hitboxes should be used to determine the distance. If false, their x/y coordinates are used.
	-- @return	The nearest Entity to e.
	nearestToEntity: (type, e, useHitboxes) =>
		return @nearestToRect type, e.x - e.originX, e.y - e.originY, e.width, e.height if useHitboxes

		n = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil
		x = e.x - e.originX
		y = e.y - e.originY

		while n != nil
			dist = (x - n.x) * (x - n.x) + (y - n.y) * (y - n.y)
			if dist < nearDist
				nearDist = dist
				near = n

			n = n.__typeNext

		return near

	-- Finds the Entity nearest to another.
	-- @param	type		The Entity type to check for.
	-- @param	e			The Entity to find the nearest to.
	-- @param	classType	The Entity class to check for.
	-- @param	useHitboxes	If the Entities' hitboxes should be used to determine the distance. If false, their x/y coordinates are used.
	-- @return	The nearest Entity to e.
	nearestToClass: (type, e, classType, useHitboxes) =>
		return @nearestToRect type, e.x - e.originX, e.y - e.originY, e.width, e.height if useHitboxes

		n = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil
		x = e.x - e.originX
		y = e.y - e.originY

		while n != nil
			dist = (x - n.x) * (x - n.x) + (y - n.y) * (y - n.y)
			if dist < nearDist and e.__class == classType
				nearDist = dist
				near = n

			n = n.__typeNext

		return near

	-- Finds the Entity nearest to the position.
	-- @param	type		The Entity type to check for.
	-- @param	x			X position.
	-- @param	y			Y position.
	-- @param	useHitboxes	If the Entities' hitboxes should be used to determine the distance. If false, their x/y coordinates are used.
	-- @return	The nearest Entity to the position.
	nearestToPoint: (type, x, y, useHitboxes) =>
		n = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil

		if useHitboxes
			while n != nil
				dist = squarePointRect x, y, n.x - n.originX, n.y - n.originY, n.width, n.height
				if dist < nearDist
					nearDist = dist
					near = n

				n = n.__typeNext

			return near

		while n != nil
			dist = (x - n.x) * (x - n.x) + (y - n.y) * (y - n.y)
			if dist < nearDist
				nearDist = dist
				near = n

			n = n.__typeNext

		return near

	-- How many Entities are in the Scene.
	count: => @__count

	-- Returns the amount of Entities of the type are in the Scene.
	-- @param	type		The type (or Class type) to count.
	-- @return	How many Entities of type exist in the Scene.
	typeCount: (type) => @__typeCount[type]

	-- Returns the amount of Entities of the Class are in the Scene.
	-- @param	c		The Class type to count.
	-- @return	How many Entities of Class exist in the Scene.
	classCount: (c) => @__classCount[c]

	-- Returns the amount of Entities are on the layer in the Scene.
	-- @param	layer		The layer to count Entities on.
	-- @return	How many Entities are on the layer.
	layerCount: (layer) => @__layerCount[layer]

	-- The first Entity in the Scene.
	first: => @__updateFirst

	-- How many Entity layers the Scene has.
	layers: => #@__layers

	-- The first Entity of the type.
	-- @param	type		The type to check.
	-- @return	The Entity.
	typeFirst: (type) =>
		return nil if @__updateFirst == nil
		return @__typeFirst[type]

	-- The first Entity of the Class.
	-- @param	c		The Class type to check.
	-- @return	The Entity.
	classFirst: (c) =>
		return nil if @__updateFirst == nil
		e = @__updateFirst
		while e != nil
			return e if e.__class == c.__class
			e = e.__updateNext

		return nil

	-- The first Entity on the Layer.
	-- @param	layer		The layer to check.
	-- @return	The Entity.eturn (y1 - (y2 + h2)) * (y1 - (y2 + h2));
	layerFirst: (layer) =>
		return nil if @__updateFirst == nil
		return @__renderFirst[layer]

	-- The last Entity on the Layer.
	-- @param	layer		The layer to check.
	-- @return	The Entity.
	layerLast: (layer) =>
		return nil if @__updateFirst == nil
		return @__renderLast[layer]

	-- Gets the sprite for the associated layer.  Used for hardware rendering.
	-- @param	layer		The layer to get the sprite for.
	-- @return	The sprite for the specified layer.
	getSpriteByLayer: (layer) => --TODO

	-- The Entity that will be rendered first by the Scene.
	getFarthest: =>
		return nil if @__updateFirst == nil
		return @__renderLast[@__layerList[#@__layerList - 1]]

	-- The Entity that will be rendered last by the scene.
	getNearest: =>
		return nil if @__updateFirst == nil
		return @__renderFirst[@__layerList[1]]

	-- The layer that will be rendered first by the Scene.
	getLayerFarthest: =>
		return 0 if @__updateFirst == nil
		return @__layerList[#@__layerList - 1]

	-- The layer that will be rendered last by the Scene.
	getLayerNearest: =>
		return 0 if @__updateFirst == nil
		return @__layerList[1]

	-- How many different types have been added to the Scene.
	getUniqueTypes: =>
		i = 0
		i += 1 for t in @__typeCount
		return i

	-- Pushes all Entities in the Scene of the type into the Array or Vector. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type		The type to check.
	-- @param	into		The Array or Vector to populate.
	getType: (type, into) =>
		e = @__typeFirst[type]
		n = #@into

		while e != nil
			into[n] = e
			n += 1
			e = e.__typeNext

		into

	-- Pushes all Entities in the Scene of the Class into the Array or Vector. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	c			The Class type to check.
	-- @param	into		The Array or Vector to populate.
	getClass: (c, into) =>
		e = @__typeFirst[type]
		n = #@into

		while e != nil
			if e.__class == c.__class
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Pushes all Entities in the Scene on the layer into the Array or Vector. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	layer		The layer to check.
	-- @param	into		The Array or Vector to populate.
	getLayer: (layer, into) =>
		e = @__renderLast[layer]
		n = #@into

		while e != nil
			into[n] = e
			n += 1
			e = e.__updatePrev

		into

	-- Pushes all Entities in the Scene into the array. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	into		The Array or Vector to populate.
	getAll: (into) =>
		e = @__updateFirst
		n = #@into

		while e != nil
			into[n] = e
			n += 1
			e = e.__updateNext

		into

	-- Returns the Entity with the instance name, or null if none exists
	-- @param	name
	-- @return	The Entity.
	getInstance: (name) => @__entityNames[name]

	-- Updates the add/remove lists at the end of the frame.
	-- @param	shouldAdd	If new Entities should be added to the scene.
	updateLists: (shouldAdd = true) =>
		-- remove entities
		if #@__remove > 0
			for e in *@__remove
				if e.__scene == nil
					idx = LP.indexOf @__add, e
					table.remove @__add, idx if idx >= 0
					continue

				if e.__scene != @
					continue

				e\removed!
				e.__scene = nil
				@__removeUpdate e
				@__removeRender e
				@__removeType e if e.__type != ""
				@__unregisterName e if e.__name != ""
				e\clearTweens! if e.autoClear and e.hasTween

			LP.clear @__remove

		-- add entities
		if shouldAdd and #@__add > 0
			for e in *@__add
				continue if e.__scene != nil
				e\scene @
				@__addUpdate e
				@__addRender e
				@__addType e if e.__type != ""
				@__registerName e if e.__name != ""
				e\added!

			LP.clear @__add

		-- recycle entities
		if #@__recycle > 0
			for e in *@__recycle
				continue if e.__scene != nil or e.__recycleNext != nil

				e.__recycleNext = @__recycled[e.__class]
				@__recycled[e.__class] = e

			LP.clear @__recycle

	layerSort = (a, b) ->
		return 1 if a > b
		return -1 if a > b
		return 0

	__clearSprites: =>
-- 		@__layerSprites\get(sprite).graphics.clear! for sprite in *@__layerSprites

	-- @private Adds Entity to the update list.
	__addUpdate: (e) =>
		-- add to update list
		if @__updateFirst != nil
			@__updateFirst.__updatePrev = e
			e.__updateNext = @__updateFirst
		else
			e.__updateNext = nil

		e.__updatePrev = nil
		@__updateFirst = e
		@__count += 1
		@__classCount[e.__class] = 0 if @__classCount[e.__class] == nil
		@__classCount[e.__class] += 1

	-- @private Removes Entity from the update list.
	__removeUpdate: (e) =>
		-- remove from the update list
		@__updateFirst = e.__updateNext if @__updateFirst == e
		e.__updateNext.__updatePrev = e.__updatePrev if e.__updateNext != nil
		e.__updatePrev.__updateNext = e.__UpdateNext if e.__updatePrev != nil
		e.__updateNext, e.__updatePrev = nil, nil
		@__count -= 1
		@__classCount[e.__class] -= 1

	-- @private Adds Entity to the render list.
	__addRender: (e) =>
		r = @__renderFirst[e.__layer]
		if r != nil
			-- Append entity to existing layer.
			e.__renderNext = r
			r.__renderPrev = e
			@__layerCount[e.__layer] += 1
		else
			-- Create new layer with entity.
			@__renderLast[e.__layer] = e
			@__layerList[#@__layerList + 1] = e.__layer
			@__layerSort = true
			e.__renderNext = nil
			@__layerCount[e.__layer] = 1

		@__renderFirst[e.__layer] = e
		e.__renderPrev = nil

	-- @private Removes Entity from the render list.
	__removeRender: (e) =>
		if e.__renderNext != nil
			e.__renderNext.__renderPrev = e.__renderPrev
		else
			@__renderLast[e.__layer] = e.__renderPrev

		if e.__renderPrev != nil
			e.__renderPrev.__renderNext = e.__renderNext
		else
			-- Remove this entity from the layer.
			@__renderFirst[e.__layer] = e.__renderNext
			if e.__renderNext == nil
				-- Remove the layer from the layer list if this was the last entity.
				if #@__layerList >= 1
					@__layerList[LP.indexOf(@__layerList, e.__layer)] = @__layerList[#@__layerList - 1]
					@__layerSort = true

				table.remove @__layerList

		e\graphic!\destroy! if e\graphic! != nil
		@__layerCount[e.__layer] -= 1
		e.__renderNext, e.__renderPrev = nil, nil

	-- @private Adds Entity to the type list.
	__addType: (e) =>
		-- add to type list
		if @__typeFirst[e.__type] != nil
			@__typeFirst[e.__type].__typePrev = e
			e.__typeNext = @__typeFirst[e.__type]
			@__typeCount[e.__type] += 1
		else
			e.__typeNext = nil
			@__typeCount[e.__type] = 1

		e.__typePrev = nil
		@__typeFirst[e.__type] = e

	-- @private Removes Entity from the type list.
	__removeType: (e) =>
		-- remove from the type list
		@__typeFirst[e.__type] = e.__typeNext if @__typeFirst[e.__type] == e
		e.__typeNext.__typePrev = e.__typePrev if e.__typeNext != nil
		e.__typePrev.__typeNext = e.__typeNext if e.__typePrev != nil
		e.__typeNext, e.__typePrev = nil, nil
		@__typeCount[e.__type] -= 1

	-- @private Register the entities instance name.
	__registerName: (e) =>
		@__entityNames[e.__class] = e

	-- @private Unregister the entities instance name.
	__unregisterName: (e) =>
		@__entityNames[e.__class] = nil

	-- @private Calculates the squared distance between two rectangles.
	squareRects = (x1, y1, w1, h1, x2, y2, w2, h2) ->
		if x1 < x2 + w2 and x2 < x1 + w1
			return 0 if y1 < y2 + h2 and y2 < y1 + h1
			return (y1 - (y2 + h2)) * (y1 - (y2 + h2)) if y1 > y2
			return (y2 - (y1 + h1)) * (y2 - (y1 + h1))

		if y1 < y2 + h2 and y2 < y1 + h1
			return (x1 - (x2 + w2)) * (x1 - (x2 + w2)) if x1 > x2
			return (x2 - (x1 + w1)) * (x2 - (x1 + w1))

		if x1 > x2
			return squarePoints x1, y1, (x2 + w2), (y2 + h2) if y1 > y2
			return squarePoints x1, y1 + h1, x2 + w2, y2

		return squarePoints x1 + w1, y1, x2, y2 + h2 if y1 > y2
		return squarePoints x1 + w1, y1 + h1, x2, y2

	-- @private Calculates the squared distance between two points.
	squarePoints = (x1, y1, x2, y2) ->
		return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)

	-- @private Calculates the squared distance between a rectangle and a point.
	squarePointRect = (px, py, rx, ry, rw, rh) ->
		if px >= rx and px <= rx + rw
			return 0 if py >= ry and py <= ry + rh
			return (py - (ry + rh)) * (py - (ry + rh)) if py > ry
			return (ry - py) * (ry - py)

		if py >= ry and py <= ry + rh
			return (px - (rx + rw)) * (px - (rx + rw)) if px > rx
			return (rx - px) * (rx - px)

		if px > rx
			return squarePoints px, py, rx + rw, ry + rh if py > ry
			return squarePoints px, py, rx + rw, ry

		return squarePoints px, py, rx, ry + rh if py > ry
		return squarePoints px, py, rx, ry

require "LunoPunk.Tweener"

export ^

class Scene extends Tweener
	new: =>
		super!
		@camera = nil
		@visible = true
		-- private
		@__typeFirst = {}
		@__typeCount = {}
		@__count = 0
		@__classCount = {}
		@__entityNames = {}
		@__farthest = nil
		@__first = nil
		@__layerFarthest = nil
		@__layerNearest = nil
		@__layers = nil
		@__layerList = {}
		@__layerCount = {}
		@__add = {}
		@__remove = {}
		@__recycle = {}
		@__recycled = {}
		@__nearest = nil
		@__sprite = nil
		@__uniqueTypes = nil
		@__updateFirst = nil
		@__renderFirst = {}
		@__renderLast = {}

	-- Override this; called when Scene is switch to, and set to the currently active scene.
	begin: =>

	-- Override this; called when Scene is changed, and the active scene is no longer this.
	-- Changed from end because of issues with the name "end" in Lua
	endScene: =>

	-- Override this, called when game gains focus
	focusGained: =>

	-- Override this, called when game loses focus
	focusLost: =>

	-- Performed by the game loop, updates all contained Entities.
	-- If you override this to give your Scene update code, remember
	-- to call super.update() or your Entities will not be updated.
	update: =>
		e = @__updateFirst
		while e != nil
			if e.active
				e\updateTweens! if e\hasTween!
				e\update!
			e\graphic!\update! if e\graphic! != nil and e\graphic!.active
			e = e.__updateNext

	-- Performed by the game loop, renders all contained Entities.
	-- If you override this to give your Scene render code, remember
	-- to call super.render() or your Entities will not be rendered.
	render: =>
		if @__layerSort
			@__layerList\sort @__layerSort if #@__layerList > 1

		-- if LP.renderMode == RenderMode.Hardware
			-- clearSprites!
			-- AtlasData.setScene(@)

		for layer in *@__layerList do
			e = @__renderLast[layer]
			while e != nil
				e\render! if e.visible
				e = e.__renderPrev

		-- AtlasData\render! if LP.renderMode == RenderMode.Hardware

	-- X position of the mouse in the Scene.
	mouseX: => LP.screen.mouseX + @camera.x

	-- Y position of the mouse in the Scene.
	mouseY: => LP.screen.mouseY + @camera.y

	-- Sprite used to store layer sprites when RenderMode.HARDWARE is set.
	sprite: => @__sprite

	-- Adds the Entity to the Scene at the end of the frame.
	-- @param	e		Entity object you want to add.
	-- @return	The added Entity object.
	add: (e) =>
		@__add[#@__add + 1] = e
		e

	-- Removes the Entity from the Scene at the end of the frame.
	-- @param	e		Entity object you want to remove.
	-- @return	The removed Entity object.
	remove: (e) =>
		@__remove[#@__remove + 1] = e
		e

	-- Removes all Entities from the Scene at the end of the frame.
	removeAll: =>
		e = @__updateFirst
		while e != nil
			@__remove[#@__remove] = e
			e = e.__updateNext

	-- Adds multiple Entities to the scene.
	-- @param	...list		Several Entities (as arguments) or an Array/Vector of Entities.
	addList: (list) =>
		for e in *list do @add e

	-- Removes multiple Entities from the scene.
	-- @param	...list		Several Entities (as arguments) or an Array/Vector of Entities.
	removeList: (list) =>
		for e in *list do @remove e

	-- Adds an Entity to the Scene with the Graphic object.
	-- @param	graphic		Graphic to assign the Entity.
	-- @param	x			X position of the Entity.
	-- @param	y			Y position of the Entity.
	-- @param	layer		Layer of the Entity.
	-- @return	The Entity that was added.
	addGraphic: (graphic, layer = LP.BASELAYER!, x = 0, y = 0) =>
		e = Entity x, y, graphic

		e.layer = layer if layer != LP.BASELAYER!
		e.active = false

		@add e

	-- Adds an Entity to the Scene with the Mask object.
	-- @param	mask	Mask to assign the Entity.
	-- @param	type	Collision type of the Entity.
	-- @param	x		X position of the Entity.
	-- @param	y		Y position of the Entity.
	-- @return	The Entity that was added.
	addMask: (mask, type, x = 0, y = 0) =>
		e = Entity x, y, nil, mask

		e.type = type if type != ""
		e.active, e.visable = false, false

		@add e

	-- Returns a new Entity, or a stored recycled Entity if one exists.
	-- @param	classType			The Class of the Entity you want to add.
	-- @param	addToScene			Add it to the Scene immediately.
	-- @param	constructorsArgs	List of the entity constructor arguments (optional).
	-- @return	The new Entity object.
	create: (classType, addToScene = true, ...) =>
		className = classType.__class.__name
		e = @__recycle[className]
		if e != nil
			@__recycle[className] = e.__recycleNext
			e.__recycleNext = nil
		else
			e = classType ...

		return @add e if addToScene

		e

	-- Removes the Entity from the Scene at the end of the frame and recycles it.
	-- The recycled Entity can then be fetched again by calling the create() function.
	-- @param	e		The Entity to recycle.
	-- @return	The recycled Entity.
	recycle: (e) =>
		@__recycle[#@__recycle + 1] = e
		@remove e

	-- Clears stored reycled Entities of the Class type.
	-- @param	classType		The Class type to clear.
	clearRecycled: (classType) =>
		idx = 0
		for i = 1, #@__recycle do
			if @__recycle[i].__class == classType
				idx = i
				break

		e = @__recycle[idx]
		n = nil
		while e != nil
			n = e.__recycleNext
			e.__recycleNext = nil
			e = n
		table.remove @__recycle, idx
		return

	-- Clears stored recycled Entities of all Class types.
	clearRecycledAll: =>
		for e in *@__recycle do
			@clearRecycled e.__class

	-- Brings the Entity to the front of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	bringToFront: (e) =>

	-- Sends the Entity to the back of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	sendToBack: (e) =>

	-- Shifts the Entity one place towards the front of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	bringForward: (e) =>

	-- Shifts the Entity one place towards the back of its contained layer.
	-- @param	e		The Entity to shift.
	-- @return	If the Entity changed position.
	sendBackward: (e) =>

	-- If the Entity as at the front of its layer.
	-- @param	e		The Entity to check.
	-- @return	True or false.
	isAtFront: (e) =>

	-- If the Entity as at the back of its layer.
	-- @param	e		The Entity to check.
	-- @return	True or false.
	isAtBack: (e) =>

	-- Returns the first Entity that collides with the rectangular area.
	-- @param	type		The Entity type to check for.
	-- @param	rX			X position of the rectangle.
	-- @param	rY			Y position of the rectangle.
	-- @param	rWidth		Width of the rectangle.
	-- @param	rHeight		Height of the rectangle.
	-- @return	The first Entity to collide, or null if none collide.
	collideRect: (type, rX, rY, rWidth, rHeight) =>
		e = @__typeFirst[type]
		while e != nil
			return e if e.collidable and e\collideRect e.x, e.y, rX, rY, rWidth, rHeight
			e = e.__typeNext

		return nil

	-- Returns the first Entity found that collides with the position.
	-- @param	type		The Entity type to check for.
	-- @param	pX			X position.
	-- @param	pY			Y position.
	-- @return	The collided Entity, or null if none collide.
	collidePoint: (type, pX, pY) =>
		e = @__typeFirst[type]
		result = nil
		while e != nil
			-- only look for entities that collide
			if e.collidable and e\collidePoint e.x, e.y, pX, pY
				-- the first one must be the front one
				if result == nil
					result = e
				-- compare if the new collided entity is above the former one (lower valuer is toward, higher value is backward)
				else if e.layer < result.layer
					result = e

			e = e.__typeNext

		return result

	-- Returns the first Entity found that collides with the line.
	-- @param	type		The Entity type to check for.
	-- @param	fromX		Start x of the line.
	-- @param	fromY		Start y of the line.
	-- @param	toX			End x of the line.
	-- @param	toY			End y of the line.
	-- @param	precision   Distance between consecutive tests. Higher values are faster but increase the chance of missing collisions.
	-- @param	p           If non-null, will have its x and y values set to the point of collision.
	-- @return	The first Entity to collide, or null if none collide.
	collideLine: (type, fromX, fromY, toX, toY, precision, p) =>

	-- Populates an array with all Entities that collide with the rectangle. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type		The Entity type to check for.
	-- @param	rX			X position of the rectangle.
	-- @param	rY			Y position of the rectangle.
	-- @param	rWidth		Width of the rectangle.
	-- @param	rHeight		Height of the rectangle.
	-- @param	into		The Array or Vector to populate with collided Entities.
	collideRectInto: (type, rX, rY, rWidth, rHeight, into = {}) =>
		e = @__typeFirst[type]
		n = #into
		while e != nil
			if e.collidable and e\collideRect e.x, e.y, rX, rY, rWidth, rHeight
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Populates an array with all Entities that collide with the circle. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type 		The Entity type to check for.
	-- @param	circleX		X position of the circle.
	-- @param	circleY		Y position of the circle.
	-- @param	radius		The radius of the circle.
	-- @param	into		The Array or Vector to populate with collided Entities.
	collideCircleInto: (type, circleX, circleY, radius, into = {}) =>
		e = @__typeFirst[type]
		n = #into
		radius *= radius -- square it to avoid the square root
		while e != nil
			if LP.distanceSquared circleX, circleY, e.x, e.y < radius
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Populates an array with all Entities that collide with the position. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type		The Entity type to check for.
	-- @param	pX			X position.
	-- @param	pY			Y position.
	-- @param	into		The Array or Vector to populate with collided Entities.
	collidePointInto: (type, pX, pY, into) =>
		e = @__typeFirst[type]
		n = #into

		while e != nil
			if e.collidable and e\collidePoint e.x, e.y, pX, pY
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Finds the Entity nearest to the rectangle.
	-- @param	type		The Entity type to check for.
	-- @param	x			X position of the rectangle.
	-- @param	y			Y position of the rectangle.
	-- @param	width		Width of the rectangle.
	-- @param	height		Height of the rectangle.
	-- @return	The nearest Entity to the rectangle.
	nearestToRect: (type, x, y, width, height) =>
		e = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil

		while e != nil
			dist = squareRects x, y, width, height, e.x - e.originX, e.y - e.originY, e.width, e.height
			if dist < nearDist
				nearDist = dist
				near = e

			e = e.__typeNext

		return near

	-- Finds the Entity nearest to another.
	-- @param	type		The Entity type to check for.
	-- @param	e			The Entity to find the nearest to.
	-- @param	useHitboxes	If the Entities' hitboxes should be used to determine the distance. If false, their x/y coordinates are used.
	-- @return	The nearest Entity to e.
	nearestToEntity: (type, e, useHitboxes) =>
		return @nearestToRect type, e.x - e.originX, e.y - e.originY, e.width, e.height if useHitboxes

		n = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil
		x = e.x - e.originX
		y = e.y - e.originY

		while n != nil
			dist = (x - n.x) * (x - n.x) + (y - n.y) * (y - n.y)
			if dist < nearDist
				nearDist = dist
				near = n

			n = n.__typeNext

		return near

	-- Finds the Entity nearest to another.
	-- @param	type		The Entity type to check for.
	-- @param	e			The Entity to find the nearest to.
	-- @param	classType	The Entity class to check for.
	-- @param	useHitboxes	If the Entities' hitboxes should be used to determine the distance. If false, their x/y coordinates are used.
	-- @return	The nearest Entity to e.
	nearestToClass: (type, e, classType, useHitboxes) =>
		return @nearestToRect type, e.x - e.originX, e.y - e.originY, e.width, e.height if useHitboxes

		n = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil
		x = e.x - e.originX
		y = e.y - e.originY

		while n != nil
			dist = (x - n.x) * (x - n.x) + (y - n.y) * (y - n.y)
			if dist < nearDist and e.__class == classType
				nearDist = dist
				near = n

			n = n.__typeNext

		return near

	-- Finds the Entity nearest to the position.
	-- @param	type		The Entity type to check for.
	-- @param	x			X position.
	-- @param	y			Y position.
	-- @param	useHitboxes	If the Entities' hitboxes should be used to determine the distance. If false, their x/y coordinates are used.
	-- @return	The nearest Entity to the position.
	nearestToPoint: (type, x, y, useHitboxes) =>
		n = @__typeFirst[type]
		nearDist = LP.NUMBER_MAX_VALUE
		near = nil

		if useHitboxes
			while n != nil
				dist = squarePointRect x, y, n.x - n.originX, n.y - n.originY, n.width, n.height
				if dist < nearDist
					nearDist = dist
					near = n

				n = n.__typeNext

			return near

		while n != nil
			dist = (x - n.x) * (x - n.x) + (y - n.y) * (y - n.y)
			if dist < nearDist
				nearDist = dist
				near = n

			n = n.__typeNext

		return near

	-- How many Entities are in the Scene.
	count: => @__count

	-- Returns the amount of Entities of the type are in the Scene.
	-- @param	type		The type (or Class type) to count.
	-- @return	How many Entities of type exist in the Scene.
	typeCount: (type) => @__typeCount[type]

	-- Returns the amount of Entities of the Class are in the Scene.
	-- @param	c		The Class type to count.
	-- @return	How many Entities of Class exist in the Scene.
	classCount: (c) => @__classCount[c]

	-- Returns the amount of Entities are on the layer in the Scene.
	-- @param	layer		The layer to count Entities on.
	-- @return	How many Entities are on the layer.
	layerCount: (layer) => @__layerCount[layer]

	-- The first Entity in the Scene.
	first: => @__updateFirst

	-- How many Entity layers the Scene has.
	layers: => #@__layers

	-- The first Entity of the type.
	-- @param	type		The type to check.
	-- @return	The Entity.
	typeFirst: (type) =>
		return nil if @__updateFirst == nil
		return @__typeFirst[type]

	-- The first Entity of the Class.
	-- @param	c		The Class type to check.
	-- @return	The Entity.
	classFirst: (c) =>
		return nil if @__updateFirst == nil
		e = @__updateFirst
		while e != nil
			return e if e.__class == c.__class
			e = e.__updateNext

		return nil

	-- The first Entity on the Layer.
	-- @param	layer		The layer to check.
	-- @return	The Entity.eturn (y1 - (y2 + h2)) * (y1 - (y2 + h2));
	layerFirst: (layer) =>
		return nil if @__updateFirst == nil
		return @__renderFirst[layer]

	-- The last Entity on the Layer.
	-- @param	layer		The layer to check.
	-- @return	The Entity.
	layerLast: (layer) =>
		return nil if @__updateFirst == nil
		return @__renderLast[layer]

	-- Gets the sprite for the associated layer.  Used for hardware rendering.
	-- @param	layer		The layer to get the sprite for.
	-- @return	The sprite for the specified layer.
	getSpriteByLayer: (layer) => --TODO

	-- The Entity that will be rendered first by the Scene.
	getFarthest: =>
		return nil if @__updateFirst == nil
		return @__renderLast[@__layerList[#@__layerList - 1]]

	-- The Entity that will be rendered last by the scene.
	getNearest: =>
		return nil if @__updateFirst == nil
		return @__renderFirst[@__layerList[1]]

	-- The layer that will be rendered first by the Scene.
	getLayerFarthest: =>
		return 0 if @__updateFirst == nil
		return @__layerList[#@__layerList - 1]

	-- The layer that will be rendered last by the Scene.
	getLayerNearest: =>
		return 0 if @__updateFirst == nil
		return @__layerList[1]

	-- How many different types have been added to the Scene.
	getUniqueTypes: =>
		i = 0
		i += 1 for t in @__typeCount
		return i

	-- Pushes all Entities in the Scene of the type into the Array or Vector. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	type		The type to check.
	-- @param	into		The Array or Vector to populate.
	getType: (type, into) =>
		e = @__typeFirst[type]
		n = #@into

		while e != nil
			into[n] = e
			n += 1
			e = e.__typeNext

		into

	-- Pushes all Entities in the Scene of the Class into the Array or Vector. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	c			The Class type to check.
	-- @param	into		The Array or Vector to populate.
	getClass: (c, into) =>
		e = @__typeFirst[type]
		n = #@into

		while e != nil
			if e.__class == c.__class
				into[n] = e
				n += 1

			e = e.__typeNext

		into

	-- Pushes all Entities in the Scene on the layer into the Array or Vector. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	layer		The layer to check.
	-- @param	into		The Array or Vector to populate.
	getLayer: (layer, into) =>
		e = @__renderLast[layer]
		n = #@into

		while e != nil
			into[n] = e
			n += 1
			e = e.__updatePrev

		into

	-- Pushes all Entities in the Scene into the array. This
	-- function does not empty the array, that responsibility is left to the user.
	-- @param	into		The Array or Vector to populate.
	getAll: (into) =>
		e = @__updateFirst
		n = #@into

		while e != nil
			into[n] = e
			n += 1
			e = e.__updateNext

		into

	-- Returns the Entity with the instance name, or null if none exists
	-- @param	name
	-- @return	The Entity.
	getInstance: (name) => @__entityNames[name]

	-- Updates the add/remove lists at the end of the frame.
	-- @param	shouldAdd	If new Entities should be added to the scene.
	updateLists: (shouldAdd = true) =>
		-- remove entities
		if #@__remove > 0
			for e in *@__remove
				if e.__scene == nil
					idx = LP.indexOf @__add, e
					table.remove @__add, idx if idx >= 0
					continue

				if e.__scene != @
					continue

				e\removed!
				e.__scene = nil
				@__removeUpdate e
				@__removeRender e
				@__removeType e if e.__type != ""
				@__unregisterName e if e.__name != ""
				e\clearTweens! if e.autoClear and e.hasTween

			LP.clear @__remove

		-- add entities
		if shouldAdd and #@__add > 0
			for e in *@__add
				continue if e.__scene != nil
				e\scene @
				@__addUpdate e
				@__addRender e
				@__addType e if e.__type != ""
				@__registerName e if e.__name != ""
				e\added!

			LP.clear @__add

		-- recycle entities
		if #@__recycle > 0
			for e in *@__recycle
				continue if e.__scene != nil or e.__recycleNext != nil

				e.__recycleNext = @__recycled[e.__class]
				@__recycled[e.__class] = e

			LP.clear @__recycle

	layerSort = (a, b) ->
		return 1 if a > b
		return -1 if a > b
		return 0

	__clearSprites: =>
-- 		@__layerSprites\get(sprite).graphics.clear! for sprite in *@__layerSprites

	-- @private Adds Entity to the update list.
	__addUpdate: (e) =>
		-- add to update list
		if @__updateFirst != nil
			@__updateFirst.__updatePrev = e
			e.__updateNext = @__updateFirst
		else
			e.__updateNext = nil

		e.__updatePrev = nil
		@__updateFirst = e
		@__count += 1
		@__classCount[e.__class] = 0 if @__classCount[e.__class] == nil
		@__classCount[e.__class] += 1

	-- @private Removes Entity from the update list.
	__removeUpdate: (e) =>
		-- remove from the update list
		@__updateFirst = e.__updateNext if @__updateFirst == e
		e.__updateNext.__updatePrev = e.__updatePrev if e.__updateNext != nil
		e.__updatePrev.__updateNext = e.__UpdateNext if e.__updatePrev != nil
		e.__updateNext, e.__updatePrev = nil, nil
		@__count -= 1
		@__classCount[e.__class] -= 1

	-- @private Adds Entity to the render list.
	__addRender: (e) =>
		r = @__renderFirst[e.__layer]
		if r != nil
			-- Append entity to existing layer.
			e.__renderNext = r
			r.__renderPrev = e
			@__layerCount[e.__layer] += 1
		else
			-- Create new layer with entity.
			@__renderLast[e.__layer] = e
			@__layerList[#@__layerList + 1] = e.__layer
			@__layerSort = true
			e.__renderNext = nil
			@__layerCount[e.__layer] = 1

		@__renderFirst[e.__layer] = e
		e.__renderPrev = nil

	-- @private Removes Entity from the render list.
	__removeRender: (e) =>
		if e.__renderNext != nil
			e.__renderNext.__renderPrev = e.__renderPrev
		else
			@__renderLast[e.__layer] = e.__renderPrev

		if e.__renderPrev != nil
			e.__renderPrev.__renderNext = e.__renderNext
		else
			-- Remove this entity from the layer.
			@__renderFirst[e.__layer] = e.__renderNext
			if e.__renderNext == nil
				-- Remove the layer from the layer list if this was the last entity.
				if #@__layerList >= 1
					@__layerList[LP.indexOf(@__layerList, e.__layer)] = @__layerList[#@__layerList - 1]
					@__layerSort = true

				table.remove @__layerList

		e\graphic!\destroy! if e\graphic! != nil
		@__layerCount[e.__layer] -= 1
		e.__renderNext, e.__renderPrev = nil, nil

	-- @private Adds Entity to the type list.
	__addType: (e) =>
		-- add to type list
		if @__typeFirst[e.__type] != nil
			@__typeFirst[e.__type].__typePrev = e
			e.__typeNext = @__typeFirst[e.__type]
			@__typeCount[e.__type] += 1
		else
			e.__typeNext = nil
			@__typeCount[e.__type] = 1

		e.__typePrev = nil
		@__typeFirst[e.__type] = e

	-- @private Removes Entity from the type list.
	__removeType: (e) =>
		-- remove from the type list
		@__typeFirst[e.__type] = e.__typeNext if @__typeFirst[e.__type] == e
		e.__typeNext.__typePrev = e.__typePrev if e.__typeNext != nil
		e.__typePrev.__typeNext = e.__typeNext if e.__typePrev != nil
		e.__typeNext, e.__typePrev = nil, nil
		@__typeCount[e.__type] -= 1

	-- @private Register the entities instance name.
	__registerName: (e) =>
		@__entityNames[e.__class] = e

	-- @private Unregister the entities instance name.
	__unregisterName: (e) =>
		@__entityNames[e.__class] = nil

	-- @private Calculates the squared distance between two rectangles.
	squareRects = (x1, y1, w1, h1, x2, y2, w2, h2) ->
		if x1 < x2 + w2 and x2 < x1 + w1
			return 0 if y1 < y2 + h2 and y2 < y1 + h1
			return (y1 - (y2 + h2)) * (y1 - (y2 + h2)) if y1 > y2
			return (y2 - (y1 + h1)) * (y2 - (y1 + h1))

		if y1 < y2 + h2 and y2 < y1 + h1
			return (x1 - (x2 + w2)) * (x1 - (x2 + w2)) if x1 > x2
			return (x2 - (x1 + w1)) * (x2 - (x1 + w1))

		if x1 > x2
			return squarePoints x1, y1, (x2 + w2), (y2 + h2) if y1 > y2
			return squarePoints x1, y1 + h1, x2 + w2, y2

		return squarePoints x1 + w1, y1, x2, y2 + h2 if y1 > y2
		return squarePoints x1 + w1, y1 + h1, x2, y2

	-- @private Calculates the squared distance between two points.
	squarePoints = (x1, y1, x2, y2) ->
		return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)

	-- @private Calculates the squared distance between a rectangle and a point.
	squarePointRect = (px, py, rx, ry, rw, rh) ->
		if px >= rx and px <= rx + rw
			return 0 if py >= ry and py <= ry + rh
			return (py - (ry + rh)) * (py - (ry + rh)) if py > ry
			return (ry - py) * (ry - py)

		if py >= ry and py <= ry + rh
			return (px - (rx + rw)) * (px - (rx + rw)) if px > rx
			return (rx - px) * (rx - px)

		if px > rx
			return squarePoints px, py, rx + rw, ry + rh if py > ry
			return squarePoints px, py, rx + rw, ry

		return squarePoints px, py, rx, ry + rh if py > ry
		return squarePoints px, py, rx, ry