1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. The Results have come out of the old ARENA oven. Check out who won the 30th Texturing Contest!
    Dismiss Notice
  4. Hey guys, we've posted the Results for the 30th Modeling Contest. Check them out!
    Dismiss Notice
  5. The 15th Mini-Mapping Contest came to an end. The Secrets of Warcraft 3 are soon to be revealed! Come and vote in the public poll for your favorite maps.
    Dismiss Notice
  6. The 12th incarnation of the Music Contest is LIVE! The theme is Synthwave. Knight Rider needs a song to listen to on his journey. You should definitely have some fun with this theme!
    Dismiss Notice
  7. Join other hivers in a friendly concept-art contest. The contestants have to create a genie coming out of its container. We wish you the best of luck!
    Dismiss Notice
  8. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Panel System v2.1

Submitted by Quilnez
This bundle is marked as approved. It works and satisfies the submission rules.
Description:
This is a custom user interface system in disguise. It allows you to easily adds custom user interfaces into the screen. It supports UI parenting and layering out of the box, giving you easy control over multiple custom UI properties. It's written in highly optimized vJass code with particular rendering technique to allow hundreds of custom interfaces added into the screen with minimal performance cost! Supports clean & highly intuitive API too!

Map example: EmberCraft ARPG
Includes:
- Inventory & equipment system
- Equipment set system
- Item enhancement & socketing system
- Custom status bar
- Shortcut bar system
- Item tooltips system
- Arcane statistic window
- Skill list window
- Shop System

Note: if you need a new font style (face), don't hesitate to request me to make it. Just give me the ttf file (or just mention the name) and I will send you all the textures complete with its configurations very soon.

Available fonts:

Requirements:
  • LinkedListModule
  • (Optional) PanelCameraRegulator: custom camera refreshing and provides event, necessary for the panel system to update positions precisely.
  • (Plugin - Optional) PanelModel: plugin for adding model files into panels.
  • (Plugin - Optional) PanelPlatform: plugin for adding platform objects into panels.
  • (Plugin - Optional) PanelTextTag: plugin for adding text tags into panels.
  • (Plugin - Optional) PanelText: plugin for adding texts with custom style into panels.
Codes (v2.0):
  • Code (vJASS):

    library PanelCore requires LinkedListModule, optional PanelCamera

        /*
            ~ Panel Core ~

            Provides parenting, events, coordinate conversions & calculations,
            and all necessary functions for panel contents and plugins.
     
            I. API
     
                struct Panel
             
                    Members:
                        readonly unit dummy
                            - Panel's dummy unit object
                        readonly boolean visible
                            - Get panel's visibility state
                        readonly real zDepth
                            - Panel's depth
                        readonly Panel base
                            - List containing all panels
                     
                        readonly static real ScreenCenterX
                        readonly static real ScreenCenterY
                        readonly static real ScreenCenterZ
                            - Get current camera center position
                     
                        readonly static real ReturnValX
                        readonly static real ReturnValY
                        readonly static real ReturnValZ
                            - Returned value from getRelativePos & Win2World method
                     
                    Event related members:
                        readonly static integer EventType
                            - Type of triggered event
                        readonly static thistype TriggeringPanel
                            - Get which panel is triggering the event
                 
                        static constant integer EVENT_PANEL_REFRESHED
                            - Fired when a panel is done refreshing
                        static constant integer EVENT_PANEL_CLEARED
                            - Fired when a panel is done clearing its contents
                        static constant integer EVENT_PANEL_VISIBILITY_MODIFIED
                            - Fired when a panel's visibility is changed (shown/hidden)
                        static constant integer EVENT_PANEL_OPACITY_MODIFIED
                            - Fired when a panel's opacity/transparency is changed
                        static constant integer EVENT_PANEL_DESTROYED
                            - Fired right before a panel is destroyed
         
                    Methods:
                        static method create takes integer id, integer background, real xOffset, real yOffset, real zDepth returns Panel
                            - Instantiate new panel
                            - x/yOffset indicates the distance from center of the screen
                            - zDepth indicates how far from screen position the panel will be
     
                        static method Win2World takes real xOffset, real yOffset, real zDepth returns nothing
                            - Converts screen coordinates into world coordinates
                            - Returned values are stored in: ReturnValX/Y/Z
                     
                        static method RegisterAnyPanelEvent takes code func returns triggercondition
                        static method UnregisterAnyPanelEvent takes triggercondition tc returns nothing
                            - (Un)register a function to be executed on panel events
                            - Passed function must returns boolean
                     
                        method operator background= takes integer texture returns nothing
                            - Modify panel's background texture
                     
                        method operator scale= takes real r returns nothing
                        method operator scale takes nothing returns real
                            - Set/get panel's scale
                     
                        method operator xOffset takes nothing returns real
                        method operator yOffset takes nothing returns real
                            - Get panel position coordinate
                     
                        method operator opacity= takes integer i returns nothing
                        method operator opacity takes nothing returns integer
                            - Set/get panel's opacity/transparency
                 
                        method refresh takes nothing returns nothing
                            - Refresh panel and its contents properties
                        method destroy takes nothing returns nothing
                            - Destroy the panel
                        method clear takes nothing returns nothing
                            - Remove all contents from the panel
                        method move takes real xOffset, real yOffset, real zDepth returns nothing
                            - Move the panel
                        method show takes boolean b returns nothing
                            - Show/hide the panel from screen
                        method getRelativePos takes real xOffset, real yOffset, real zDepth returns nothing
                            - Get screen position relative to panels position
                            - Returned values are stored in: ReturnValX/Y/Z
                 
            III. Credits
                Dirac  | LinkedListModule  | https://www.hiveworkshop.com/threads/snippet-linkedlistmodule.206552/
             
        */


                                   ////////////////////
                                   // Configurations //
                                   ////////////////////
            globals
                // Rawcode of texture replacer ability
                public constant integer TEXTURE_REPLACER_ID = 'APTR'
                public constant integer REPLACER_ORDER_ID = 852511
                // Maximum number of rendering level at zero Z Offset
                public constant integer MAX_LEVEL = 50
                // Only used if not using the camera regulator system
                public constant real REFRESH_RATE = 0.03
            endglobals

                                    //////////////////
                                    // System codes //
                                    //////////////////

        globals
            private location L = Location(0, 0)
            public real DeltaZ = 0
            public real WorldMaxX = 0
            public real WorldMaxY = 0
            public real WorldMinX = 0
            public real WorldMinY = 0
            public constant real HP   = bj_PI/2
            public constant real TAU  = bj_PI*2
            public constant real R270 = bj_PI+HP
            public constant real LEVEL_GAP  = 0.00275
            public constant real CAMERA_GAP = 99.975+LEVEL_GAP*MAX_LEVEL
            public constant real GENERAL_SIZE = 0.0905
            public constant real PIXEL_CORRECTION_X = GENERAL_SIZE*0.8899125
            public constant real PIXEL_CORRECTION_Y = PIXEL_CORRECTION_X*1.3186813
            public constant player PASSIVE = Player(PLAYER_NEUTRAL_PASSIVE)
        endglobals

        public function AngularDifference takes real a, real b returns real
            return Atan2(Sin(a-b), Cos(a-b))
        endfunction

        public function GetTerrainZ takes real x, real y returns real
            call MoveLocation(L, x, y)
            return GetLocationZ(L)
        endfunction

        public function GetUnitZ takes unit u returns real
            return GetTerrainZ(GetUnitX(u), GetUnitY(u))+GetUnitFlyHeight(u)
        endfunction
     
        public function SetUnitZ takes unit u, real z returns nothing
            call SetUnitFlyHeight(u, z-GetTerrainZ(GetUnitX(u), GetUnitY(u)), 0)
        endfunction

        public function ChangeTexture takes unit whichUnit, integer whichTexture returns nothing

            local destructable d = null
            local real x
            local real y
     
            if whichTexture != 0 then
                set d = CreateDestructable(whichTexture, 0, 0, 0, 0, 1)
                if d != null then
                    set x = GetUnitX(whichUnit)
                    set y = GetUnitY(whichUnit)
                    call SetUnitX(whichUnit, 0)
                    call SetUnitY(whichUnit, 0)
                    call IssueTargetOrderById(whichUnit, REPLACER_ORDER_ID, d)
                    call RemoveDestructable(d)
                    call SetUnitX(whichUnit, x)
                    call SetUnitY(whichUnit, y)
                    set d = null
                endif
            endif
     
        endfunction

        struct Panel extends array

            implement LinkedList
     
            readonly real size
            readonly real zDepth
            readonly real xOffset
            readonly real yOffset
     
            private  integer skin
            private  integer op
            readonly boolean visible
            readonly unit dummy
     
            readonly static real ReturnValX = 0
            readonly static real ReturnValY = 0
            readonly static real ReturnValZ = 0
            readonly static real ScreenCenterX = 0
            readonly static real ScreenCenterY = 0
            readonly static real ScreenCenterZ = 0
     
            private static real YawC    = 0
            private static real YawS    = 0
            private static real YawC2   = 0
            private static real YawS2   = 0
            private static real PitchC  = 0
            private static real PitchS  = 0
            private static real Pitch2C = 0
            private static real Pitch2S = 0
     
            readonly static integer  EventType = 0
            readonly static thistype TriggeringPanel = 0
            private  static trigger  EventTrigger = CreateTrigger()
     
            static if not LIBRARY_PanelCamera then
                private static timer Timer = CreateTimer()
            endif
     
            static constant integer EVENT_PANEL_REFRESHED           = 1
            static constant integer EVENT_PANEL_CLEARED             = 2
            static constant integer EVENT_PANEL_VISIBILITY_MODIFIED = 3
            static constant integer EVENT_PANEL_DESTROYED           = 4
            static constant integer EVENT_PANEL_OPACITY_MODIFIED    = 5
     
            private method fireEvent takes integer whichEvent returns nothing
                set TriggeringPanel = this
                set EventType = whichEvent
                call TriggerEvaluate(EventTrigger)
            endmethod
     
            static method Win2World takes real xOffset, real yOffset, real zDepth returns nothing
     
                local real yzOffset = yOffset*Pitch2S*PIXEL_CORRECTION_Y-zDepth*PitchC
         
                set ReturnValX = ScreenCenterX+xOffset*PIXEL_CORRECTION_X*YawC2+yzOffset*YawC
                set ReturnValY = ScreenCenterY+xOffset*PIXEL_CORRECTION_X*YawS2+yzOffset*YawS
                set ReturnValZ = ScreenCenterZ+yOffset*PIXEL_CORRECTION_Y*Pitch2C+zDepth*PitchS
         
            endmethod
     
            static method RegisterAnyPanelEvent takes code func returns triggercondition
                return TriggerAddCondition(EventTrigger, Condition(func))
            endmethod
     
            static method UnregisterAnyPanelEvent takes triggercondition tc returns nothing
                call TriggerRemoveCondition(EventTrigger, tc)
            endmethod
     
            method operator background= takes integer texture returns nothing
                if texture != .skin then
                    call ChangeTexture(.dummy, texture)
                    set .skin = texture
                endif
            endmethod
     
            method operator opacity= takes integer i returns nothing
                set .op = i
                call SetUnitVertexColor(.dummy, 255, 255, 255, i)
                call fireEvent(EVENT_PANEL_OPACITY_MODIFIED)
            endmethod
     
            method operator scale= takes real r returns nothing
                set .size = r*GENERAL_SIZE
                if .visible then
                    call SetUnitScale(.dummy, .size, 1, 1)
                endif
            endmethod
     
            method operator background takes nothing returns integer
                return .skin
            endmethod
     
            method operator opacity takes nothing returns integer
                return .op
            endmethod
     
            method operator scale takes nothing returns real
                return .size/GENERAL_SIZE
            endmethod
     
            method getRelativePos takes real xOffset, real yOffset, real zDepth returns nothing
                call Win2World(.xOffset+xOffset, .yOffset+yOffset, .zDepth+zDepth)
            endmethod
     
            method refresh takes nothing returns nothing
     
                if .visible then
                    call Win2World(.xOffset, .yOffset, .zDepth)
                    if ReturnValX > WorldMinX and ReturnValX < WorldMaxX and ReturnValY > WorldMinY and ReturnValY < WorldMaxY then
                        call SetUnitX(.dummy, ReturnValX)
                        call SetUnitY(.dummy, ReturnValY)
                        call SetUnitZ(.dummy, ReturnValZ)
                        call SetUnitScale(.dummy, .size, 1, 1)
                    else
                        call SetUnitScale(.dummy, 0, 0, 0)
                    endif
                    call fireEvent(EVENT_PANEL_REFRESHED)
                endif
         
            endmethod
     
            method clear takes nothing returns nothing
                call fireEvent(EVENT_PANEL_CLEARED)
            endmethod
     
            method destroy takes nothing returns nothing
                call fireEvent(EVENT_PANEL_DESTROYED)
                call RemoveUnit(.dummy)
                call removeNode()
                call deallocate()
                set .dummy = null
            endmethod
     
            method show takes boolean b returns nothing
                if b != .visible then
                    set .visible = b
                    if b then
                        call SetUnitScale(.dummy, .size, 1, 1)
                    else
                        call SetUnitScale(.dummy, 0, 0, 0)
                        call SetUnitX(.dummy, WorldMaxX)
                        call SetUnitY(.dummy, WorldMaxY)
                    endif
                    call fireEvent(EVENT_PANEL_VISIBILITY_MODIFIED)
                endif
            endmethod
     
            method move takes real xOffset, real yOffset, real zDepth returns nothing
                set .xOffset = xOffset
                set .yOffset = yOffset
                set .zDepth  = -zDepth
            endmethod
     
            static method create takes integer id, integer background, real xOffset, real yOffset, real zDepth returns Panel
         
                local thistype this = allocate()
         
                set .scale   = 1
                set .opacity = 255
                set .visible = true
                set .dummy   = CreateUnit(PASSIVE, id, 0, 0, 0)
                set .skin    = background
         
                static if not LIBRARY_AutoFly then
                    if UnitAddAbility(.dummy, 'Amrf') and UnitRemoveAbility(.dummy, 'Amrf') then
                    endif
                endif
                call UnitAddAbility(.dummy, TEXTURE_REPLACER_ID)
                call UnitRemoveAbility(.dummy, 'Amov')
                call SetUnitPathing(.dummy, false)
                call ChangeTexture(.dummy, background)
                call move(xOffset, yOffset, zDepth)
                call base.insertNode(this)
                call refresh()
         
                return this
            endmethod
     
            private static method GetScreenCenterPos takes nothing returns nothing
         
                local real d
                local real x
                local real y
                local real z
                local real x2
                local real y2
                local real cd
                local real cz
                local real yaw
                local real pitch
             
                static if LIBRARY_PanelCamera then
                    set x   = PanelCamera_LocX
                    set y   = PanelCamera_LocY
                    set cz  = PanelCamera_ZOffset+DeltaZ
                    set cd  = PanelCamera_TargetDistance-CAMERA_GAP
                    set yaw = PanelCamera_Rotation
                    set pitch = PanelCamera_AngleOfAttack
                else
                    set x   = GetCameraTargetPositionX()
                    set y   = GetCameraTargetPositionY()
                    set cz  = GetCameraTargetPositionZ()
                    set cd  = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE)-CAMERA_GAP
                    set yaw = GetCameraField(CAMERA_FIELD_ROTATION)
                    set pitch = GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK)
                endif
         
                if pitch < R270 and pitch > HP then
                    set yaw   = bj_PI+yaw
                    set pitch = bj_PI-pitch
                endif
                set pitch   = (pitch-AngularDifference(pitch, R270)*2)-bj_PI
                set YawC    = Cos(yaw)
                set YawS    = Sin(yaw)
                set YawC2   = Cos(yaw-HP)
                set YawS2   = Sin(yaw-HP)
                set PitchC  = Cos(pitch)
                set PitchS  = Sin(pitch)
                set pitch   = AngularDifference(pitch-HP, R270)
                set Pitch2C = Cos(pitch)
                set Pitch2S = Sin(pitch)
                set d        = cd*PitchC
                set ScreenCenterX = x-d*YawC
                set ScreenCenterY = y-d*YawS
                set ScreenCenterZ = cz+cd*PitchS
         
            endmethod
     
            private static method refreshPanels takes nothing returns boolean
     
                local thistype node = base.next
         
                call GetScreenCenterPos()
                loop
                    exitwhen node.head or node == 0
                    if node.visible then
                        call node.refresh()
                    endif
                    set node = node.next
                endloop
         
                return false
            endmethod
     
            private static method onInit takes nothing returns nothing
     
                set WorldMaxX = GetRectMaxX(bj_mapInitialPlayableArea)
                set WorldMaxY = GetRectMaxY(bj_mapInitialPlayableArea)
                set WorldMinX = GetRectMinX(bj_mapInitialPlayableArea)
                set WorldMinY = GetRectMinX(bj_mapInitialPlayableArea)
         
                call SetCameraPosition(0, 0)
                set DeltaZ = GetCameraTargetPositionZ()
                static if LIBRARY_PanelCamera then
                    call RegisterOnCameraRefreshEvent(function thistype.refreshPanels)
                else
                    call TimerStart(Timer, REFRESH_RATE, true, function thistype.refreshPanels)
                endif
         
            endmethod
     
        endstruct

    endlibrary
     
  • Code (vJASS):

    library PanelCamera
     
        /*
            ~ Panel Camera Regulator ~
       
            A complementary system for the panel system. Required in
            order to let it reposition itself accurately. It works just
            like the native camera, with some hotfixes of course.
       
            By using this, default camera scrolling (mouse & keyboard) will be
            disabled. Camera field roll and field of view isn't allowed to be
            modified as well. And you are only allowed to use some specific
            camera related functions which will be specified below. Deal with it.
       
            I. API
                function RefreshCamera takes nothing returns nothing
                    - Call this everytime you update the camera
               
                function SetCameraFieldEx takes camerafield whichField, real value, real duration returns nothing
                    - This is a replacement of native SetCameraField
                    - You can still use the native ones but you can use this instead if you need some extra speed
               
                function RegisterOnCameraRefreshEvent takes code func return triggercondition
                function UnregisterOnCameraRefreshEvent takes triggercondition cond return nothing
                    - (Un)register a function to be executed everytime camera is done refreshing
           
            II. Extra notes
       
                So far you may only use these native and BJ functions:
                    - SetCameraField
                    - SetCameraFieldForPlayer [GUI]
                    - SetCameraPosition
                    - PanCameraTo
                    - PanCameraToTimed
                    - PanCameraToTimedLocForPlayer [GUI]
                    - CameraSetSmoothingFactor
                    - CameraSetupApply
                    - CameraSetupApplyForceDuration
                    - CameraSetupApplyForPlayer [GUI]
                    - SetCameraTargetController
                    - SetCameraTargetControllerNoZForPlayer[GUI]
               
                Just let me know if you need more functions to be supported.
             
                Function call replacements:
                    (Variable name) = (Replaced function)
                    LocX            = GetCameraTargetPositionX()
                    LocY            = GetCameraTargetPositionY()
                    ZOffset            = CAMERA_FIELD_ZOFFSET / GetCameraTargetPositionZ()
                    AngleOfAttack    = CAMERA_FIELD_ANGLE_OF_ATTACK
                    CameraFarZ        = CAMERA_FIELD_FARZ
                    Rotation        = CAMERA_FIELD_ROTATION
                    TargetDistance    = CAMERA_FIELD_TARGET_DISTANCE
        */

     
                                   ////////////////////
                                   // Configurations //
                                   ////////////////////
                             
        globals
            // Minimum value difference that will be processed by the system
            // Must be a positive value
            private constant real TOLERANCE = 0.1
            // Lower value makes the camera looks smoother but will cause the system
            // to work significantly harder
            private constant real INTERVAL = 0.03125
        endglobals
     
                                    //////////////////
                                    // System codes //
                                    //////////////////

        globals
            public real LocX            = 0
            public real LocY            = 0
            public real ZOffset         = 0
            public real TargetDistance  = bj_CAMERA_DEFAULT_DISTANCE
            public real Rotation        = bj_CAMERA_DEFAULT_ROTATION*bj_DEGTORAD
            public real AngleOfAttack   = bj_CAMERA_DEFAULT_AOA*bj_DEGTORAD
       
            private real LocXTarget     = LocX
            private real LocYTarget     = LocY
            private real TargetDistanceTarget = TargetDistance
            private real RotationTarget = Rotation
            private real AngleOfAttackTarget = AngleOfAttack
            private real ZOffsetTarget  = ZOffset
            private real LocXRate       = 0.0
            private real LocYRate       = 0.0
            private real ZOffsetRate    = 0.0
            private real TargetDistanceRate = 0.0
            private real RotationRate   = 0.0
            private real AngleOfAttackRate = 0.0
       
            private unit    CameraMan
            private player  Locale
            private boolean Boole       = false
            private boolean Notify      = true
            private timer   CamTimer    = CreateTimer()
            private timer   StopTimer   = CreateTimer()
            private trigger Trigg       = CreateTrigger()
            private constant real HP    = bj_PI/2
            private constant real TAU   = bj_PI*2
        endglobals
     
        private function AngularDifference takes real a, real b returns real
            return RAbsBJ(Atan2(Sin(a-b), Cos(a-b)))
        endfunction
     
        function RefreshCamera takes nothing returns nothing
            set Boole = true
            call SetCameraField(CAMERA_FIELD_ROLL, 0, 0)
            call SetCameraField(CAMERA_FIELD_FIELD_OF_VIEW, bj_CAMERA_DEFAULT_FOV, 0)
            call SetCameraField(CAMERA_FIELD_ROTATION, Rotation*bj_RADTODEG, 0)
            call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, AngleOfAttack*bj_RADTODEG, 0)
            call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, TargetDistance, 0)
            call SetCameraField(CAMERA_FIELD_ZOFFSET, ZOffset, 0)
            call SetCameraTargetController(CameraMan, LocX, LocY, false)
            set Boole = false
        endfunction
     
        private function FireEvent takes nothing returns nothing
            if Notify then
                call RefreshCamera()
                call TriggerEvaluate(Trigg)
            endif
        endfunction
     
        private function onTick takes nothing returns nothing
            set Notify = false
            if Rotation != RotationTarget then
                if Cos(Rotation-RotationTarget) <= Cos(RotationRate) then
                    if Sin(RotationTarget-Rotation) >= 0 then
                        set Rotation = Rotation + RotationRate
                    else
                        set Rotation = Rotation - RotationRate
                    endif
                else
                    set Rotation = RotationTarget
                endif
                set Notify = true
            endif
            if AngleOfAttack != AngleOfAttackTarget then
                if Cos(AngleOfAttack-AngleOfAttackTarget) <= Cos(AngleOfAttackRate) then
                    if Sin(AngleOfAttackTarget-AngleOfAttack) >= 0 then
                        set AngleOfAttack = AngleOfAttack + AngleOfAttackRate
                    else
                        set AngleOfAttack = AngleOfAttack - AngleOfAttackRate
                    endif
                else
                    set AngleOfAttack = AngleOfAttackTarget
                endif
                set Notify = true
            endif
            if TargetDistance != TargetDistanceTarget then
                if RAbsBJ(TargetDistance-TargetDistanceTarget) <= RAbsBJ(TargetDistanceRate) then
                    set TargetDistance = TargetDistanceTarget
                else
                    set TargetDistance = TargetDistance + TargetDistanceRate
                endif
                set Notify = true
            endif
            if ZOffset != ZOffsetTarget then
                if RAbsBJ(ZOffset-ZOffsetTarget) <= RAbsBJ(ZOffsetRate) then
                    set ZOffset = ZOffsetTarget
                else
                    set ZOffset = ZOffset + ZOffsetRate
                endif
                set Notify = true
            endif
            if LocX != LocXTarget then
                if RAbsBJ(LocX-LocXTarget) <= RAbsBJ(LocXRate) then
                    set LocX = LocXTarget
                else
                    set LocX = LocX + LocXRate
                endif
                set Notify = true
            endif
            if LocY != LocYTarget then
                if RAbsBJ(LocY-LocYTarget) <= RAbsBJ(LocYRate) then
                    set LocY = LocYTarget
                else
                    set LocY = LocY + LocYRate
                endif
                set Notify = true
            endif
            call FireEvent()
            set Notify = true
        endfunction
     
        function SetCameraFieldEx takes camerafield whichField, real value, real duration returns nothing
            if whichField == CAMERA_FIELD_ROTATION then
                if AngularDifference(Rotation, value*bj_DEGTORAD) > TOLERANCE*bj_DEGTORAD then
                    set RotationTarget = value*bj_DEGTORAD
                    if duration <= 0 then
                        set Rotation = RotationTarget
                        call FireEvent()
                    else
                        set RotationRate = AngularDifference(Rotation, RotationTarget)/duration*INTERVAL
                    endif
                endif
            elseif whichField == CAMERA_FIELD_ANGLE_OF_ATTACK then
                if AngularDifference(AngleOfAttack, value*bj_DEGTORAD) > TOLERANCE*bj_DEGTORAD then
                    set AngleOfAttackTarget = value*bj_DEGTORAD
                    if duration <= 0 then
                        set AngleOfAttack = AngleOfAttackTarget
                        call FireEvent()
                    else
                        set AngleOfAttackRate = AngularDifference(AngleOfAttack, AngleOfAttackTarget)/duration*INTERVAL
                    endif
                endif
            elseif whichField == CAMERA_FIELD_TARGET_DISTANCE then
                if RAbsBJ(TargetDistance-value) > TOLERANCE then
                    set TargetDistanceTarget = value
                    if duration <= 0 then
                        set TargetDistance = value
                        call FireEvent()
                    else
                        set TargetDistanceRate = (value-TargetDistance)/duration*INTERVAL
                    endif
                endif
            elseif whichField == CAMERA_FIELD_ZOFFSET then
                if RAbsBJ(ZOffset-value) > TOLERANCE then
                    set ZOffsetTarget = value
                    if duration <= 0 then
                        set ZOffset = value
                        call FireEvent()
                    else
                        set ZOffsetRate = (value-ZOffset)/duration*INTERVAL
                    endif
                endif
            endif
        endfunction
     
        private function SetCameraFieldCatcher takes camerafield whichField, real value, real duration returns nothing
            if not Boole then
                call SetCameraFieldEx(whichField, value, duration)
            endif
        endfunction
     
        private function SetCameraFieldForPlayerEx takes player whichPlayer, camerafield whichField, real value, real duration returns nothing
            if Locale == whichPlayer then
                call SetCameraFieldEx(whichField, value, duration)
            endif
        endfunction
     
        private function SetCameraPositionEx takes real x, real y returns nothing
            set LocX = x
            set LocY = y
            set LocXTarget = x
            set LocYTarget = y
            call FireEvent()
        endfunction
     
        private function PanCameraToTimedEx takes real x, real y, real duration returns nothing
       
            local boolean updateX = RAbsBJ(LocX-x) > TOLERANCE
            local boolean updateY = RAbsBJ(LocY-y) > TOLERANCE
       
            if updateX or updateY then
                if duration <= 0 then
                    call SetCameraPositionEx(x, y)
                else
                    if updateX then
                        set LocXTarget = x
                        set LocXRate = (x-LocX)/duration*INTERVAL
                    endif
                    if updateY then
                        set LocYTarget = y
                        set LocYRate = (y-LocY)/duration*INTERVAL
                    endif
                endif
            endif
       
        endfunction
     
        private function PanCameraToTimedLocForPlayerEx takes player whichPlayer, location loc, real duration returns nothing
            if Locale == whichPlayer then
                call PanCameraToTimedEx(GetLocationX(loc), GetLocationY(loc), duration)
            endif
        endfunction
     
        private function CameraSetupApplyForceDurationEx takes camerasetup whichSetup, boolean doPan, real forceDuration returns nothing
            call SetCameraFieldEx(CAMERA_FIELD_ANGLE_OF_ATTACK, CameraSetupGetField(whichSetup, CAMERA_FIELD_ANGLE_OF_ATTACK), forceDuration)
            call SetCameraFieldEx(CAMERA_FIELD_FARZ, CameraSetupGetField(whichSetup, CAMERA_FIELD_FARZ), forceDuration)
            call SetCameraFieldEx(CAMERA_FIELD_FIELD_OF_VIEW, CameraSetupGetField(whichSetup, CAMERA_FIELD_FIELD_OF_VIEW), forceDuration)
            call SetCameraFieldEx(CAMERA_FIELD_ROLL, CameraSetupGetField(whichSetup, CAMERA_FIELD_ROLL), forceDuration)
            call SetCameraFieldEx(CAMERA_FIELD_ROTATION, CameraSetupGetField(whichSetup, CAMERA_FIELD_ROTATION), forceDuration)
            call SetCameraFieldEx(CAMERA_FIELD_TARGET_DISTANCE, CameraSetupGetField(whichSetup, CAMERA_FIELD_TARGET_DISTANCE), forceDuration)
            call SetCameraFieldEx(CAMERA_FIELD_ZOFFSET, CameraSetupGetField(whichSetup, CAMERA_FIELD_ZOFFSET), forceDuration)
            if doPan then
                call SetCameraPositionEx(CameraSetupGetDestPositionX(whichSetup), CameraSetupGetDestPositionY(whichSetup))
            endif
        endfunction
     
        private function CameraSetupApplyEx takes camerasetup whichSetup, boolean doPan, boolean panTimed returns nothing
            call CameraSetupApplyForceDurationEx(whichSetup, doPan, 0)
        endfunction
     
        private function CameraSetupApplyForPlayerEx takes boolean doPan, camerasetup whichSetup, player whichPlayer, real duration returns nothing
            if Locale == whichPlayer then
                call CameraSetupApplyForceDurationEx(whichSetup, doPan, duration)
            endif
        endfunction
     
        private function CameraSetSmoothingFactorEx takes real factor returns nothing
            if not Boole then
                set Boole = true
                call CameraSetSmoothingFactor(0)
                set Boole = false
            endif
        endfunction
     
        private function SetCameraTargetControllerEx takes unit whichUnit, real xoffset, real yoffset, boolean inheritOrientation returns nothing
            if not Boole then
                set Boole = true
                call SetCameraTargetController(CameraMan, LocX, LocY, false)
                set Boole = false
            endif
        endfunction
     
        private function SetCameraTargetControllerNoZForPlayerEx takes player whichPlayer, unit whichUnit, real xoffset, real yoffset, boolean inheritOrientation returns nothing
            if Locale == whichPlayer then
                call SetCameraTargetControllerEx(CameraMan, LocX, LocY, false)
            endif
        endfunction

        hook SetCameraField SetCameraFieldCatcher
        hook SetCameraFieldForPlayer SetCameraFieldForPlayerEx
        hook SetCameraPosition SetCameraPositionEx
        hook PanCameraTo SetCameraPositionEx
        hook PanCameraToTimed PanCameraToTimedEx
        hook PanCameraToTimedLocForPlayer PanCameraToTimedLocForPlayerEx
        hook CameraSetSmoothingFactor CameraSetSmoothingFactorEx
        hook CameraSetupApply CameraSetupApplyEx
        hook CameraSetupApplyForceDuration CameraSetupApplyForceDurationEx
        hook CameraSetupApplyForPlayer CameraSetupApplyForPlayerEx
        hook SetCameraTargetController SetCameraTargetControllerEx
        hook SetCameraTargetControllerNoZForPlayer SetCameraTargetControllerNoZForPlayerEx
     
        function RegisterOnCameraRefreshEvent takes code func returns triggercondition
            return TriggerAddCondition(Trigg, Condition(func))
        endfunction
     
        function UnregisterOnCameraRefreshEvent takes triggercondition cond returns nothing
            call TriggerRemoveCondition(Trigg, cond)
        endfunction
     
        private module InitModule
            private static method onInit takes nothing returns nothing
                call init()
            endmethod
        endmodule
     
        private struct Initializer
     
            private static method init takes nothing returns nothing
                set Locale = GetLocalPlayer()
                set CameraMan = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'hpea', 0, 0, 0)
                call SetUnitPathing(CameraMan, false)
                call PauseUnit(CameraMan, true)
                call ShowUnit(CameraMan, false)
                call SetUnitX(CameraMan, 0)
                call SetUnitY(CameraMan, 0)
                call SetCameraTargetController(CameraMan, LocX, LocY, false)
                call TimerStart(CamTimer, INTERVAL, true, function onTick)
                call FireEvent()
            endmethod
       
            implement InitModule
       
        endstruct
     
    endlibrary
     
  • Code (vJASS):

    library PanelModel requires PanelCore

        /*
            ~ Panel Model Plugin ~
       
            Allows to add model files into panels.
       
            I. How to import:
                1. Copy "PanelModel" trigger to your map.
                2. Export "PanelModelDummy.mdx" in import manager to your map.
                3. Save your map, then close and reopen it.
                4. Delete/comment out this line:                                                                                                        */

                //! external ObjectMerger w3u hfoo hPSD unsf "PanelModelDummy" unam "" umdl "war3mapImported\PanelModelDummy.mdl" ubdg 1 uabi "Aloc" uble 0 uico "" umxp 0 umxr 0 ussc 0 ushu "" uaen "" udea "" umvt "float" ucol 0 usnd "" ufle 0 ufoo 0 uspe 1 uhom 1 urac "unknown" usid 0 usin 0 upgr "" uhot "" utip "" utub ""
        /*      5. Done.
       
            II. API
       
                struct PanelModel
               
                    Members:
                        boolean transformAxis
                            - If true, the model's coordinate will be rescaled based on it's parent size
                        readonly unit dummy
                            - Model's dummy unit object
                       
                        readonly real xOffset
                        readonly real yOffset
                            - x/y offset of the model
                       
                        readonly boolean visible
                            - Model's current visibility state
                        readonly Panel parent
                            - Panel that's containing the model
                   
                        readonly static thistype array List
                            - A list containing models in a specific Panel
                            - Takes the desired Panel (parent) instance as index
                   
                    Methods:
                        static method create takes Panel parent, string path, real xOffset, real yOffset, integer level returns thistype
                            - Add a model into a Panel
                       
                        method operator modelPath= takes string path returns nothing
                            - Change the model file
                        method operator level takes nothing returns integer
                            - Get model's rendering level
                       
                        method operator scale= takes real r returns nothing
                        method operator scale takes nothing returns real
                            - Set/get model size
                       
                        method refresh takes nothing returns nothing
                            - Refresh model screen position
                        method destroy takes nothing returns nothing
                            - Delete and remove the model from its parents collection
                        method move takes real xOffset, real yOffset, integer level returns nothing
                            - Move the model to new screen coordinate
                        method show takes boolean b returns nothing
                            - Modify text tag's visibility
                   
        */

                                   ////////////////////
                                   // Configurations //
                                   ////////////////////
        globals
            // Billboarded dummy unit dummy ID
            private constant integer DUMMY_ID = 'hPSD'
            // No need to modify
            private constant string ATTACH_POINT = "origin"
        endglobals
     
                                    //////////////////
                                    // System codes //
                                    //////////////////
     
        struct PanelModel extends array
       
            implement LinkedList
     
            boolean transformAxis
            private effect model
            readonly  unit dummy
       
            readonly real xOffset
            readonly real yOffset
            private  real zOffset
            private  real size
       
            private  boolean pvisible
            readonly boolean visible
            readonly Panel parent
       
            readonly static thistype array List
       
            method operator modelPath= takes string path returns nothing
                call DestroyEffect(.model)
                set .model = AddSpecialEffectTarget(path, .dummy, ATTACH_POINT)
            endmethod
       
            method operator scale= takes real r returns nothing
                set .size = r*PanelCore_GENERAL_SIZE
                if .visible then
                    call SetUnitScale(.dummy, .size*.parent.scale, 1, 1)
                endif
            endmethod
       
            method operator level takes nothing returns integer
                return R2I(.zOffset/PanelCore_LEVEL_GAP)
            endmethod
       
            method operator scale takes nothing returns real
                return .size/PanelCore_GENERAL_SIZE
            endmethod
       
            method destroy takes nothing returns nothing
                call DestroyEffect(.model)
                call RemoveUnit(.dummy)
                call removeNode()
                call deallocate()
                set .dummy = null
                set .model = null
            endmethod
       
            method refresh takes nothing returns nothing
                if .visible and .parent.visible then
                    if .transformAxis then
                        call .parent.getRelativePos(.xOffset*.parent.scale, .yOffset*.parent.scale, .zOffset)
                    else
                        call .parent.getRelativePos(.xOffset, .yOffset, .zOffset)
                    endif
                    if Panel.ReturnValX > PanelCore_WorldMinX and Panel.ReturnValX < PanelCore_WorldMaxX and Panel.ReturnValY > PanelCore_WorldMinY and Panel.ReturnValY < PanelCore_WorldMaxY then
                        call SetUnitX(.dummy, Panel.ReturnValX)
                        call SetUnitY(.dummy, Panel.ReturnValY)
                        call PanelCore_SetUnitZ(.dummy, Panel.ReturnValZ)
                        call SetUnitScale(.dummy, .size*.parent.scale, 1, 1)
                    else
                        call SetUnitScale(.dummy, 0, 0, 0)
                    endif
                endif
            endmethod
       
            method move takes real xOffset, real yOffset, integer level returns nothing
                set .xOffset = xOffset
                set .yOffset = yOffset
                set .zOffset = PanelCore_LEVEL_GAP*level
            endmethod
       
            method show takes boolean b returns nothing
                if b != .visible then
                    set .visible = b
                    if b then
                        call SetUnitScale(.dummy, .size*.parent.scale, 1, 1)
                    else
                        call SetUnitScale(.dummy, 0, 0, 0)
                        call SetUnitX(.dummy, PanelCore_WorldMaxX)
                        call SetUnitY(.dummy, PanelCore_WorldMaxY)
                    endif
                endif
            endmethod
       
            static method create takes Panel parent, string path, real xOffset, real yOffset, integer level returns thistype
       
                local thistype this = allocate()
           
                set .parent  = parent
                set .scale   = 1
                set .visible = true
                set .dummy   = CreateUnit(PanelCore_PASSIVE, DUMMY_ID, 0, 0, 0)
                set .model   = AddSpecialEffectTarget(path, .dummy, ATTACH_POINT)
                set .transformAxis = true
           
                static if not LIBRARY_AutoFly then
                    if UnitAddAbility(.dummy, 'Amrf') and UnitRemoveAbility(.dummy, 'Amrf') then
                    endif
                endif
                call UnitRemoveAbility(.dummy, 'Amov')
                call SetUnitScale(.dummy, .size, 1, 1)
                call move(xOffset, yOffset, level)
                call refresh()
                if List[parent] == 0 then
                    set List[parent] = createNode()
                endif
                call List[parent].insertNode(this)
           
                return this
            endmethod
       
            private static method onPanelEvent takes nothing returns boolean
           
                local thistype node
           
                if List[Panel.TriggeringPanel] != 0 then
                    set node = List[Panel.TriggeringPanel].next
                    loop
                        exitwhen node.head or node == 0
                        if Panel.EventType == Panel.EVENT_PANEL_REFRESHED then
                            call node.refresh()
                        elseif Panel.EventType == Panel.EVENT_PANEL_CLEARED or Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                            call node.destroy()
                        elseif Panel.EventType == Panel.EVENT_PANEL_VISIBILITY_MODIFIED then
                            if not node.parent.visible then
                                call SetUnitX(node.dummy, PanelCore_WorldMaxX)
                                call SetUnitY(node.dummy, PanelCore_WorldMaxY)
                            endif
                        endif
                        set node = node.next
                    endloop
                    if Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                        call List[Panel.TriggeringPanel].flushNode()
                        set List[Panel.TriggeringPanel] = 0
                    endif
                endif
           
                return false
            endmethod
       
            private static method onInit takes nothing returns nothing
                call Panel.RegisterAnyPanelEvent(function thistype.onPanelEvent)
            endmethod
       
        endstruct
     
    endlibrary
     
  • Code (vJASS):

    library PanelPlatform requires PanelCore

        /*
            ~ Panel Platform Plugin ~
       
            Allows to add platform objects into panels.
       
            I. How to import:
                1. Copy "PanelPlatform" trigger to your map.
                2. Done.
       
            II. API
       
                struct PanelPlatform
               
                    Members:
                        boolean transformAxis
                            - If true, the platform's coordinate will be rescaled based on it's parent size
                        readonly unit dummy
                            - Platform's dummy unit object
                   
                        readonly real xOffset
                        readonly real yOffset
                            - x/y offset of the platform
                   
                        readonly integer red
                        readonly integer green
                        readonly integer blue
                        readonly integer alpha
                            - Platform's color channels
                   
                        readonly boolean visible
                            - Platform's visibility state
                        readonly Panel parent
                            - Panel that's containing the platform
                   
                        readonly static thistype array List
                            - A list containing platforms in a specific Panel
                            - Takes the desired Panel (parent) instance as index
                   
                    Methods:
                        static method create takes Panel parent, integer id, integer texture, real xOffset, real yOffset, integer level returns thistype
                            - Add a platform into a Panel
                       
                        method operator texture= takes integer i returns nothing
                            - Change the platform texture
                        method operator level takes nothing returns integer
                            - Get platform's rendering level
                       
                        method operator scale= takes real r returns nothing
                        method operator scale takes nothing returns real
                            - Get/set platform's size
                       
                        method refresh takes nothing returns nothing
                            - Refresh platform screen position
                        method destroy takes nothing returns nothing
                            - Delete and remove the model from its parents collection
                        method move takes real xOffset, real yOffset returns nothing
                            - Move the platform to a new screen coordinate
                        method show takes boolean b returns nothing
                            - Modify platform's visibility state
                        method setColor takes integer r, integer g, integer b, integer a returns nothing
                            - Modify platform's vertex colors
                   
        */

                                    //////////////////
                                    // System codes //
                                    //////////////////

        struct PanelPlatform extends array
       
            implement LinkedList
     
            boolean transformAxis
            readonly unit dummy
       
            readonly real xOffset
            readonly real yOffset
            private  real zOffset
            private  real size
       
            readonly integer red
            readonly integer green
            readonly integer blue
            readonly integer alpha
            private  integer skin
       
            readonly boolean visible
            private  boolean pvisible
            readonly Panel   parent
       
            readonly static thistype array List
       
            method operator texture= takes integer i returns nothing
                if i != .skin then
                    set .skin = i
                    call PanelCore_ChangeTexture(.dummy, i)
                endif
            endmethod
       
            method operator scale= takes real r returns nothing
                set .size = r*PanelCore_GENERAL_SIZE
                if .visible then
                    call SetUnitScale(.dummy, .size*.parent.scale, 1, 1)
                endif
            endmethod
       
            method operator texture takes nothing returns integer
                return .skin
            endmethod
       
            method operator level takes nothing returns integer
                return R2I(.zOffset/PanelCore_LEVEL_GAP)
            endmethod
       
            method operator scale takes nothing returns real
                return .size/PanelCore_GENERAL_SIZE
            endmethod
       
            method destroy takes nothing returns nothing
                call RemoveUnit(.dummy)
                call removeNode()
                call deallocate()
                set .dummy = null
            endmethod
       
            method refresh takes nothing returns nothing
                if .visible and .parent.visible then
                    if .transformAxis then
                        call .parent.getRelativePos(.xOffset*.parent.scale, .yOffset*.parent.scale, .zOffset)
                    else
                        call .parent.getRelativePos(.xOffset, .yOffset, .zOffset)
                    endif
                    if Panel.ReturnValX > PanelCore_WorldMinX and Panel.ReturnValX < PanelCore_WorldMaxX and Panel.ReturnValY > PanelCore_WorldMinY and Panel.ReturnValY < PanelCore_WorldMaxY then
                        call SetUnitX(.dummy, Panel.ReturnValX)
                        call SetUnitY(.dummy, Panel.ReturnValY)
                        call PanelCore_SetUnitZ(.dummy, Panel.ReturnValZ)
                        call SetUnitScale(.dummy, .size*.parent.scale, 1, 1)
                    else
                        call SetUnitScale(.dummy, 0, 0, 0)
                    endif
                endif
            endmethod
       
            method move takes real xOffset, real yOffset, integer level returns nothing
                set .xOffset = xOffset
                set .yOffset = yOffset
                set .zOffset = PanelCore_LEVEL_GAP*level
            endmethod
       
            method setColor takes integer r, integer g, integer b, integer a returns nothing
                set .red   = r
                set .green = g
                set .blue  = b
                set .alpha = a
                call SetUnitVertexColor(.dummy, .red, .green, .blue, R2I(.alpha*.parent.opacity/255.))
            endmethod
       
            method show takes boolean b returns nothing
                if b != .visible then
                    set .visible = b
                    if b then
                        call SetUnitScale(.dummy, .size*.parent.scale, 1, 1)
                    else
                        call SetUnitScale(.dummy, 0, 0, 0)
                        call SetUnitX(.dummy, PanelCore_WorldMaxX)
                        call SetUnitY(.dummy, PanelCore_WorldMaxY)
                    endif
                endif
            endmethod
       
            static method create takes Panel parent, integer id, integer texture, real xOffset, real yOffset, integer level returns thistype
           
                local thistype this = allocate()
           
                set .parent  = parent
                set .scale   = 1
                set .visible = true
                set .dummy   = CreateUnit(PanelCore_PASSIVE, id, 0, 0, 0)
                set .skin    = texture
                set .transformAxis = true
           
                static if not LIBRARY_AutoFly then
                    if UnitAddAbility(.dummy, 'Amrf') and UnitRemoveAbility(.dummy, 'Amrf') then
                    endif
                endif
                call UnitRemoveAbility(.dummy, 'Amov')
                call UnitAddAbility(.dummy, PanelCore_TEXTURE_REPLACER_ID)
                call SetUnitPathing(.dummy, false)
                call SetUnitScale(.dummy, .size, 1, 1)
                call setColor(255, 255, 255, 255)
                call PanelCore_ChangeTexture(.dummy, texture)
                call move(xOffset, yOffset, level)
                if parent.visible then
                    call refresh()
                else
                    call SetUnitX(.dummy, PanelCore_WorldMaxX)
                    call SetUnitY(.dummy, PanelCore_WorldMaxY)
                endif
                if List[parent] == 0 then
                    set List[parent] = createNode()
                endif
                call List[parent].insertNode(this)
           
                return this
            endmethod
       
            private static method onPanelEvent takes nothing returns boolean
           
                local thistype node
           
                if List[Panel.TriggeringPanel] != 0 then
                    set node = List[Panel.TriggeringPanel].next
                    loop
                        exitwhen node.head or node == 0
                        if Panel.EventType == Panel.EVENT_PANEL_REFRESHED then
                            call node.refresh()
                        elseif Panel.EventType == Panel.EVENT_PANEL_CLEARED or Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                            call node.destroy()
                        elseif Panel.EventType == Panel.EVENT_PANEL_VISIBILITY_MODIFIED then
                            if not node.parent.visible then
                                call SetUnitX(node.dummy, PanelCore_WorldMaxX)
                                call SetUnitY(node.dummy, PanelCore_WorldMaxY)
                            endif
                        elseif Panel.EventType == Panel.EVENT_PANEL_OPACITY_MODIFIED then
                            call SetUnitVertexColor(node.dummy, node.red, node.green, node.blue, R2I(node.alpha*node.parent.opacity/255.))
                        endif
                        set node = node.next
                    endloop
                    if Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                        call List[Panel.TriggeringPanel].flushNode()
                        set List[Panel.TriggeringPanel] = 0
                    endif
                endif
           
                return false
            endmethod
       
            private static method onInit takes nothing returns nothing
                call Panel.RegisterAnyPanelEvent(function thistype.onPanelEvent)
            endmethod
       
        endstruct

    endlibrary
     
  • Code (vJASS):

    library PanelTextTag requires PanelCore, optional ZLibrary

        /*
            ~ Panel Text Tag Plugin ~
       
            Allows to add text tags into panels.
       
            I. How to import:
                1. Copy "PanelTextTag" trigger to your map.
                2. Export "PanelTextTagDummy.mdx" in import manager to your map.
                3. Save your map, then close and reopen it.
                4. Delete/comment out this line:                                                                                                        */

                //! external ObjectMerger w3u hfoo hPTD unsf "PanelTextTagDummy" unam "" umdl "war3mapImported\PanelTextTagDummy.mdl" ubdg 1 uabi "Aloc" uble 0 uico "" umxp 0 umxr 0 ussc 0 ushu "" uaen "" udea "" umvt "float" ucol 0 usnd "" ufle 0 ufoo 0 uspe 1 uhom 1 urac "unknown" usid 0 usin 0 upgr "" uhot "" utip "" utub ""
        /*      5. Done.
       
            II. API
       
                struct PanelTextTag
               
                    Members:
                        boolean transformAxis
                            - If true, the text tag's coordinate will be rescaled based on it's parent size
                       
                        readonly real xOffset
                        readonly real yOffset
                            - x/y offset of the text tag
                   
                        readonly integer red
                        readonly integer green
                        readonly integer blue
                        readonly integer alpha
                            - Text tag's color channels
                   
                        readonly string text
                        readonly real size
                            - Text tag's current text & size
                        readonly boolean visible
                            - Text tag's current visibility state
                        readonly Panel parent
                            - Panel that's containing the text tag
                       
                        readonly static thistype array List
                            - A list containing text tags in a specific Panel
                            - Takes the desired Panel (parent) instance as index
                   
                    Methods:
                        static method create takes Panel parent, string s, real size, real xOffset, real yOffset returns thistype
                            - Add a text tag into a panel
                       
                        method refresh takes nothing returns nothing
                            - Refresh text tag screen position
                        method destroy takes nothing returns nothing
                            - Delete and remove the text tag from its parents collection
                        method move takes real xOffset, real yOffset returns nothing
                            - Move the text tag to a new screen coordinate
                        method show takes boolean b returns nothing
                            - Modify text tag's visibility
                        method setText takes string s, real size returns nothing
                            - Change the text tag's text and size
                        method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
                            - Change the text tag's color
                   
        */

                                   ////////////////////
                                   // Configurations //
                                   ////////////////////
     
        globals
            private constant integer DUMMY_ID = 'hPTD'
            private constant real    ZOFFSET  = -14.8
        endglobals
     
                                    //////////////////
                                    // System codes //
                                    //////////////////

        struct PanelTextTag extends array
       
            implement LinkedList
     
            boolean transformAxis
            private texttag tag
       
            readonly real xOffset
            readonly real yOffset
       
            readonly integer red
            readonly integer green
            readonly integer blue
            readonly integer alpha
       
            readonly string text
            readonly real size
       
            private  boolean pvisible
            readonly boolean visible
            readonly Panel parent
       
            readonly static thistype array List
            private  static unit ZPlacer
            private  static player LocalPlayer
       
            method destroy takes nothing returns nothing
                call DestroyTextTag(.tag)
                call removeNode()
                call deallocate()
                set .tag = null
            endmethod
       
            method refresh takes nothing returns nothing
                if .visible and .parent.visible then
                    if .transformAxis then
                        call .parent.getRelativePos(.xOffset*.parent.scale, .yOffset*.parent.scale, 0)
                    else
                        call .parent.getRelativePos(.xOffset, .yOffset, 0)
                    endif
                    if Panel.ReturnValX > PanelCore_WorldMinX and Panel.ReturnValX < PanelCore_WorldMaxX and Panel.ReturnValY > PanelCore_WorldMinY and Panel.ReturnValY < PanelCore_WorldMaxY then
                        call SetUnitX(ZPlacer, Panel.ReturnValX)
                        call SetUnitY(ZPlacer, Panel.ReturnValY)
                        call PanelCore_SetUnitZ(ZPlacer, Panel.ReturnValZ)
                        call SetTextTagPosUnit(.tag, ZPlacer, ZOFFSET)
                        call SetTextTagText(.tag, .text, .size*.parent.scale)
                        call SetTextTagVisibility(.tag, true)
                    else
                        call SetTextTagVisibility(.tag, false)
                    endif
                endif
            endmethod
       
            method show takes boolean b returns nothing
                if b != .visible then
                    set .visible = b
                    if not b then
                        call SetTextTagVisibility(.tag, false)
                    endif
                endif
            endmethod
       
            method move takes real xOffset, real yOffset returns nothing
                set .xOffset = xOffset
                set .yOffset = yOffset
            endmethod
       
            method setText takes string s, real size returns nothing
                set .text = s
                set .size = size
            endmethod
       
            method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
                set .red   = red
                set .green = green
                set .blue  = blue
                set .alpha = alpha
                call SetTextTagColor(.tag, .red, .green, .blue, R2I(.alpha*.parent.opacity/255.))
            endmethod
       
            static method create takes Panel parent, player p, string s, real size, real xOffset, real yOffset returns thistype
           
                local thistype this = allocate()
           
                set .parent  = parent
                set .visible = true
                if GetLocalPlayer() == p then
                    set .tag = CreateTextTag()
                else
                    set .tag = null
                endif
                set .transformAxis = true
           
                call SetTextTagVisibility(.tag, true)
                call SetTextTagPermanent(.tag, true)
                call setText(s, size)
                call setColor(255, 255, 255, 255)
                call move(xOffset, yOffset)
                call refresh()
                if List[parent] == 0 then
                    set List[parent] = createNode()
                endif
                call List[parent].insertNode(this)
           
                return this
            endmethod
       
            private static method onPanelEvent takes nothing returns boolean
           
                local thistype node
           
                if List[Panel.TriggeringPanel] != 0 then
                    set node = List[Panel.TriggeringPanel].next
                    loop
                        exitwhen node.head or node == 0
                        if Panel.EventType == Panel.EVENT_PANEL_REFRESHED then
                            call node.refresh()
                        elseif Panel.EventType == Panel.EVENT_PANEL_CLEARED or Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                            call node.destroy()
                        elseif Panel.EventType == Panel.EVENT_PANEL_VISIBILITY_MODIFIED then
                            if not node.parent.visible then
                                call SetTextTagVisibility(node.tag, false)
                            endif
                        elseif Panel.EventType == Panel.EVENT_PANEL_OPACITY_MODIFIED then
                            call SetTextTagColor(node.tag, node.red, node.green, node.blue, R2I(node.alpha*node.parent.opacity/255.))
                        endif
                        set node = node.next
                    endloop
                    if Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                        call List[Panel.TriggeringPanel].flushNode()
                        set List[Panel.TriggeringPanel] = 0
                    endif
                endif
           
                return false
            endmethod
       
            private static method onInit takes nothing returns nothing
                set ZPlacer = CreateUnit(PanelCore_PASSIVE, DUMMY_ID, 0, 0, 0)
                static if not LIBRARY_AutoFly then
                    if UnitAddAbility(ZPlacer, 'Amrf') and UnitRemoveAbility(ZPlacer, 'Amrf') then
                    endif
                endif
                call PauseUnit(ZPlacer, true)
                call ShowUnit(ZPlacer, false)
                call Panel.RegisterAnyPanelEvent(function thistype.onPanelEvent)
            endmethod
       
        endstruct
     
    endlibrary
     
  • Code (vJASS):

    library PanelText requires PanelCore, PanelPlatform, Ascii

        /*
            ~ Panel Text Plugin ~
     
            Allows to add texts with custom font font into panels.
     
            Text is more powerful that TextTag, it allows you to have
            many  font fonts with "indefinite" length and amount limit.
            Also  it appears  much smoother than TextTag. However, it's
            a lot heavier both in terms of storage and computation.
       
            It's highly recommended not to use too much of it.
     
            I. Requirements:
                - PanelCore                    | -
                - (plugin)   PanelPlatform    | -
                - (required) Ascii            | https://www.hiveworkshop.com/threads/snippet-ascii.190746/
     
            II. How to import:
                1. Copy "PanelText" trigger to your map.
                2. Export "PanelTextDummy.mdx" in import manager to your map.
                3. Save your map, then close and reopen it.
                4. Delete/comment out this line:                                                                                                */

                //! external ObjectMerger w3u hfoo hTED unsf "PanelTextDummy" unam "" umdl "war3mapImported\PanelTextDummy.mdl" ubdg 1 uabi "Aloc" uble 0 uico "" umxp 0 umxr 0 ussc 0 ushu "" uaen "" udea "" umvt "float" ucol 0 usnd "" ufle 0 ufoo 0 uspe 1 uhom 1 urac "unknown" usid 0 usin 0 upgr "" uhot "" utip "" utub ""
        /*      5. Done.
     
            III. API
     
                struct PanelText
             
                    Members:
                        readonly real width
                            - Total width of the whole text in pixel
                        readonly real xOffset
                        readonly real yOffset
                            - Position of the text
                 
                        readonly string font
                            - Text's font font
                        readonly integer length
                            - Number of characters in the text
                        readonly integer level
                            - Rendering level of the text
                 
                        readonly Panel parent
                            - Panel that's containing the text
                     
                        readonly static thistype array List
                            - A list containing Text's in a specific Panel
                            - Takes the desired Panel (parent) instance as index
                 
                    Methods:
                        static method create takes Panel parent, string text, string font, real xOffset, real yOffset, integer level returns thistype
                            - Add new Text to a panel
                     
                        method operator visible takes nothing returns boolean
                            - Get text's current visibility state
                     
                        method operator red takes nothing returns integer
                        method operator green takes nothing returns integer
                        method operator blue takes nothing returns integer
                        method operator alpha takes nothing returns integer
                            - Get text's color channels
                     
                        method operator scale takes nothing returns real
                        method operator scale= takes real r returns nothing
                            - Get/set text size
                       
                        method operator transformAxis= takes boolean b returns nothing
                            - If true, the text's coordinate will be rescaled based on it's parent size
                 
                        method setText takes string text, string font returns nothing
                            - Change the text and its font font
                        method refresh takes nothing returns nothing
                            - Refresh text screen position
                        method destroy takes nothing returns nothing
                            - Remove the text from its container
                        method move takes real xOffset, real yOffset, integer level returns nothing
                            - Move the text to different coordinate and level
                        method setColor takes integer r, integer g, integer b, integer a returns nothing
                            - Modify text's color and transparency
                        method show takes boolean b returns nothing
                            - Show/hide the text
                 
        */

                                   ////////////////////
                                   // Configurations //
                                   ////////////////////
     
        globals
            // Platform object for display characters
            private constant integer DUMMY_ID = 'hTED'
            // Space character width in pixel
            private constant real SPACE_WIDTH = 8.0 // px
            // Default spacing between characters
            private constant real CHAR_GAP    = 1.0
        endglobals
     
                                    //////////////////
                                    // System codes //
                                    //////////////////
     
        private module InitModule
            private static method onInit takes nothing returns nothing
                call init()
            endmethod
        endmodule

        struct PanelTextChar extends array
     
            implement LinkedList
     
            string char
            real   width
            real   height
            real   depth
            PanelPlatform plat
     
            method operator xOffset takes nothing returns real
                return .plat.xOffset
            endmethod
     
            method operator yOffset takes nothing returns real
                return .plat.yOffset
            endmethod
     
            method operator visible takes nothing returns boolean
                return .plat.visible
            endmethod
     
            method show takes boolean b returns nothing
                call .plat.show(b)
            endmethod
     
        endstruct
     
        struct PanelText extends array
     
            implement LinkedList
     
            private  real size
            readonly real width
            readonly real height
            readonly real depth
            readonly real xOffset
            readonly real yOffset
     
            readonly string  text
            readonly integer font
            readonly integer length
            readonly integer level
     
            readonly Panel parent
            readonly PanelTextChar chars
     
            readonly static thistype array List
            readonly static hashtable FontData = InitHashtable()
     
            private method getCharTexture takes string s returns integer
                return LoadInteger(FontData, font + 0, Char2Ascii(s))
            endmethod
     
            private method getCharWidth takes string s returns real
                return LoadReal(FontData, font + 1, Char2Ascii(s))
            endmethod
     
            private method getCharHeight takes string s returns real
                return LoadReal(FontData, font + 2, Char2Ascii(s))
            endmethod
     
            private method getCharDepth takes string s returns real
                return LoadReal(FontData, font + 3, Char2Ascii(s))
            endmethod
     
            method operator visible takes nothing returns boolean
                return .chars.next.plat.visible
            endmethod
     
            method operator red takes nothing returns integer
                return .chars.next.plat.red
            endmethod
     
            method operator green takes nothing returns integer
                return .chars.next.plat.green
            endmethod
     
            method operator blue takes nothing returns integer
                return .chars.next.plat.blue
            endmethod
     
            method operator alpha takes nothing returns integer
                return .chars.next.plat.alpha
            endmethod
     
            method operator scale takes nothing returns real
                return .size
            endmethod
     
            method operator scale= takes real r returns nothing
                set .size = r
                call refresh()
            endmethod
       
            method operator transformAxis= takes boolean b returns nothing
       
                local PanelTextChar c = .chars.next
           
                loop
                    exitwhen c.head
                    if c.plat != 0 then
                        set c.plat.transformAxis = b
                    endif
                    set c = c.next
                endloop
            endmethod
     
            method refresh takes nothing returns nothing
         
                local PanelTextChar c = .chars.next
                local real xOffset = .xOffset
                local real offset
         
                set .width  = 0
                set .height = 0
                set .depth  = 0
                loop
                    exitwhen c.head
                    set offset  = c.width*.size
                    if c.plat != 0 then
                        set c.plat.scale = .size
                        call c.plat.move(xOffset+offset/2, .yOffset, .level)
                        call c.plat.refresh()
                    endif
                    set xOffset = xOffset+offset+CHAR_GAP
                    set .width  = .width+offset+CHAR_GAP
                    if c.height > .height then
                        set .height = c.height*.size
                    endif
                    if c.depth > .depth then
                        set .depth = c.depth*.size
                    endif
                    set c = c.next
                endloop
                set .width = .width-CHAR_GAP
         
            endmethod
     
            private method clear takes nothing returns nothing
         
                local PanelTextChar c = .chars.next
         
                loop
                    exitwhen c.head
                    if c.plat != 0 then
                        call c.plat.destroy()
                    endif
                    set c = c.next
                endloop
                call chars.clearNode()
         
            endmethod
     
            method destroy takes nothing returns nothing
                call clear()
                call chars.flushNode()
                call removeNode()
                call deallocate()
            endmethod
     
            method move takes real xOffset, real yOffset, integer level returns nothing
                set .xOffset = xOffset
                set .yOffset = yOffset
                set .level   = level
                call refresh()
            endmethod
     
            method setColor takes integer r, integer g, integer b, integer a returns nothing
         
                local PanelTextChar c = .chars.next
         
                loop
                    exitwhen c.head
                    if c.plat != 0 then
                        call c.plat.setColor(r, g, b, a)
                    endif
                    set c = c.next
                endloop
         
            endmethod
     
            method show takes boolean b returns nothing
         
                local PanelTextChar c = .chars.next
         
                loop
                    exitwhen c.head
                    if c.plat != 0 then
                        call c.plat.show(b)
                    endif
                    set c = c.next
                endloop
         
            endmethod
     
            private method initText takes nothing returns nothing
     
                local integer i = 0
                local string s
                local real xOffset = .xOffset
                local real yOffset
                local real offset
                local PanelTextChar c
         
                set .width  = 0
                set .height = 0
                set .depth  = 0
                loop
                    exitwhen i == .length
                    set s = SubString(.text, i, i+1)
                    set c = PanelTextChar.allocate()
                    if s == " " then
                        set c.char   = " "
                        set c.width  = SPACE_WIDTH
                        set c.height = 0.0
                        set c.depth  = 0.0
                        set offset   = c.width*.size
                        set c.plat   = 0
                    else
                        set c.char   = s
                        set c.width  = getCharWidth(s)
                        set c.height = getCharHeight(s)
                        set c.depth  = getCharDepth(s)
                        set offset   = c.width*.size
                        set c.plat   = PanelPlatform.create(.parent, DUMMY_ID, getCharTexture(s), xOffset+offset/2, .yOffset, level)
                    endif
                    set xOffset = xOffset+offset+CHAR_GAP
                    set .width  = .width+offset+CHAR_GAP
                    if c.height > .height then
                        set .height = c.height*.size
                    endif
                    if c.depth > .depth then
                        set .depth = c.depth*.size
                    endif
                    call .chars.insertNode(c)
                    set i = i + 1
                endloop
                set .width = .width-CHAR_GAP
         
            endmethod
     
            method setText takes string text, integer font returns nothing
                if .text != text then
                    call clear()
                    set .text   = text
                    set .font   = font
                    set .length = StringLength(text)
                    call initText()
                endif
            endmethod
     
            static method create takes Panel parent, string text, integer font, real xOffset, real yOffset, integer level returns thistype
         
                local thistype this = allocate()
         
                set .parent  = parent
                set .size    = 1
                set .xOffset = xOffset
                set .yOffset = yOffset
                set .level   = level
                set .text    = text
                set .font    = font
                set .length  = StringLength(text)
                set .chars   = PanelTextChar.createNode()
                call initText()
         
                if List[parent] == 0 then
                    set List[parent] = createNode()
                endif
                call List[parent].insertNode(this)
         
                return this
            endmethod
     
            private static method onPanelEvent takes nothing returns boolean
         
                local thistype node
         
                if List[Panel.TriggeringPanel] != 0 then
                    set node = List[Panel.TriggeringPanel].next
                    loop
                        exitwhen node.head
                        if Panel.EventType == Panel.EVENT_PANEL_CLEARED or Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                            call node.destroy()
                        endif
                        set node = node.next
                    endloop
                    if Panel.EventType == Panel.EVENT_PANEL_DESTROYED then
                        call List[Panel.TriggeringPanel].flushNode()
                        set List[Panel.TriggeringPanel] = 0
                    endif
                endif
         
                return false
            endmethod
     
            private static method init takes nothing returns nothing
         
                local string s
                local integer asc
         
                call Panel.RegisterAnyPanelEvent(function PanelText.onPanelEvent)
                implement PanelTextFontData
           
            endmethod
       
            implement InitModule
     
        endstruct
     
        // Font data stuffs
     
        globals
            public integer FontIndex = 0
        endglobals
     
        //! textmacro DefineFontStyle takes FONT
        globals
            integer FONTSTYLE_$FONT$ = -1
        endglobals
        //! endtextmacro
     
        //! textmacro InitFontObject takes FONT, CHAR, INDEX, CODE, WIDTH, HEIGHT, DEPTH
            if FONTSTYLE_$FONT$ == -1 then
                set FONTSTYLE_$FONT$ = PanelText_FontIndex
                set PanelText_FontIndex = PanelText_FontIndex + 4
            endif
            if "$CHAR$" == "''" then // symbol " breaks textmacro
                set asc = Char2Ascii("\"")
            else
                set asc = Char2Ascii("$CHAR$")
            endif
            call SaveInteger(FontData, FONTSTYLE_$FONT$ + 0, asc, '$CODE$$INDEX$')
            call SaveReal   (FontData, FONTSTYLE_$FONT$ + 1, asc, $WIDTH$)
            call SaveReal   (FontData, FONTSTYLE_$FONT$ + 2, asc, $HEIGHT$)
            call SaveReal   (FontData, FONTSTYLE_$FONT$ + 3, asc, $DEPTH$)
        //! endtextmacro
     
        //! textmacro CreateFontObject takes FONT, INDEX, CODE, FILEPATH, EXTENSION
            //! external ObjectMerger w3b YTlb $CODE$$INDEX$ bnam "($FONT$) Char $INDEX$" bfxr -1 bfil ".mdl" boch 0 btxf "$FILEPATH$$INDEX$$EXTENSION$" btxi 33 bsel 0 bgsc 0 bshd "" barm "Ethereal" btar "tree" bcpr 0 bcpd 0 buch 0 bptx "" bsuf "" bcat "D"
        //! endtextmacro
     
    endlibrary
     


Credits:
  • Dirac: LinkedListModule
  • TheDamien and Nestharus: Ascii
Previews
Contents

Panel System (Map)

Reviews
KILLCIDE
Not sure what the craze is right now with Interface systems, but man this one is awesome. As I told TriggerHappy, a system like this can only be improved if more users use it, and I trust that they will report any of the bugs / issues they find. As of...
  1. BlueSaint

    BlueSaint

    Joined:
    Jun 18, 2012
    Messages:
    2,756
    Resources:
    3
    Tools:
    1
    Spells:
    2
    Resources:
    3
    Camera behavior in the demo is a bit weird.

    If only we could have a patch which extends viewport to whole screen.

    And yes flicker is annoying.
     
  2. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    What do you mean? The rotations should be inverted or something?

    The camera flicking is something I can't fix yet.
     
  3. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,633
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    I'm remembering camera smoothing caused flickering for me.
     
  4. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    I've found the problem and turned out it was my fault. The camera system was conflicting with the demo code (risk of using hooks), which is now solved. If it's still flicking for you please let me know.

    EDIT:
    Minor update: added dragon form to demo unit.

    EDIT:
    Update (v1.01):
    - Now requires nothing more than the camera system
    - Now you can apply z offset to panels
    - Camera roll and field of view modification is now properly disabled
    - Some other improvements in camera system
    - Improved demo code

    EDIT:
    Minor update (v1.01a):
    - Fixed a mistake in angular difference calculation
     

    Attached Files:

    Last edited: Feb 27, 2017
  5. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    Update v1.2:
    - Added world bounds into account
    - Fixed a mistake in clear method
    - Now content is removed properly from panel's collection
    - Now utilizes LinkedList
    - Added panel content level getter
    - Started working on new components (texttag, custom text, progress bar, etc.)

    Next:
    - We will have a more convenient coordinate system!
    - I will try to finish at least the text tag and progress bar plug in, I'm still not sure to do the custom text plug in since it will be quite heavy
     
    Last edited: Feb 27, 2017
  6. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    Update v1.3:
    - Now using pixel (px) as measure of coordinating
    - Added new method to panel: applyAxesTransform
    - Added text tag plugin
    - Added new function to the camera system for extra efficiency for end user
    - Some other nerdy improvements

    Update v1.31:
    - Improved the coordinating system
    - Rescaled all platform models accurately using the new coordinating system

    Update v1.32:
    - Now panel allows negative level
    - Now text tag doesn't have level parameter
    - Now text tag is hidden and rescaled accordingly to its parent
    - Improved documentations
    - Fixed potential desync in the demo code
     
    Last edited: Mar 2, 2017
  7. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    Update 1.4:
    - Now the camera system is optional
    - Increased coordinating precision (the demo code coordinating and platform dimensions are outdated)
    - Added panel events, now it's much easier to create plugins
    - Now panel refreshing is automatically done by the panel system itself
    - Improved documentations

    Update 1.41:
    - Added Panel x/yOffset setter & getter method operator which is unaffected by pixel correction
     
    Last edited: Mar 8, 2017
  8. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    Big update with massive reconstructions:

    General:
    - Added new plugin, PanelModel: allows to display any model files on screen
    - PanelContent is renamed to PanelPlatform and treated as a plugin
    - refresh methods are now privatized
    - Improved encapsulations
    - Better collection listing
    - Improved documentations & better trigger management

    TextTag plugin:
    - Added move method
    - Fixed a critical mistake on event initialization

    Update 1.51:
    - Fixed compile error on PanelPlatform & PanelModel without UnitZ library
    - Now PanelModel uses optimized billboarded dummy model
    - Fixed some mistakes on CameraSystem
     
    Last edited: Mar 18, 2017
  9. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    Update 1.6:
    - Added new plugin: TextEx
    - Added SCALE_MODIFIED event to the panel core
    - Now object editor data are generated with macro (for all plugins)
    - Fixed faulty list disposal in all plugins
    - Some improvements in camera system
     
  10. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Just to break your combo there, what are you using to display the stuffs like empty inventory and night elf leafy border? Don't have WC3 on this machine so I can't check the whole file. Tried CTRL+F and can't find any ".blp".
     
  11. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,633
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    It's using dummy units and custom textures.
     
  12. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Is it a different model for each custom texture that is then attached to the dummy's "origin"? Is that better than using images (non-sarcastic honest question)?
     
  13. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,633
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    Last time I checked this system has a new model and texture for each element.

    The UI system I have in the spells section based off of DGUI, uses dummy units with a single model file and the war club ability to dynamically switch textures.
     
  14. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    Ah ok.
    Just wondering, why not using the native images instead? I enumerated the advantages vs disadvantages (based on my knowledge) and in my opinion the advantages outweighs the disadvantages (unless there's more to it that I'm not aware of).

    The advantages are:
    - (Quilnez's) You don't have to import a corresponding model for each element.
    - (TriggerHappy's) You won't populate Destructable Manager with destructables for the warclub change.
    - Create Unit (+ CreateDestructable for TriggerHappy's) vs CreateImage, I think image handle types are less heavy than unit handles.
    - Can be visible in fog but can also be invisible in fog using IsVisibleToPlayer with GetLocalPlayer.

    The disadvantages are:
    - You can't use in-game texture, you have to re-import it with a 1 px transparent border but applying 1 px alpha border is easy to do using BLPLab.
    - Will always appear parallel to the ground and can't have pitch and yaw (because of dummy) angle.
     
  15. TriggerHappy

    TriggerHappy

    Code Moderator

    Joined:
    Jun 23, 2007
    Messages:
    3,633
    Resources:
    22
    Spells:
    11
    Tutorials:
    2
    JASS:
    9
    Resources:
    22
    I don't think you can change the angle of the image to fit the screen correctly, and of course you can't detect clicks.

    But yeah images would be better for non clickable items if it were possible to get that to work, but I don't think it is currently.

    Also, images need a 1px transparent border.
     
  16. Flux

    Flux

    Joined:
    Feb 6, 2014
    Messages:
    2,334
    Resources:
    28
    Maps:
    1
    Spells:
    19
    Tutorials:
    2
    JASS:
    6
    Resources:
    28
    By making the camera points directly to the ground, then you can make image fit the screen. But if the coder/modder does not want to change the camera angle during panel display, then images won't do the trick because they always appear parallel to the ground.

    Can be solved by using trackables but the downside is trackables cannot be destroyed (which I hope the new patch fix). I guess leaving a few undestroyed but disabled trackables won't hurt for one time panels like Hero Selection system but for dynamic panels like this, yeah it's not ideal to use trackables that get's created everytime the player needs the panel.

    Images work fine as far as I know but it crashes on invalid blp/tga paths.

    Luckily there's a tool for that.
     
  17. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    Mine works exactly alike, it uses the war club trick too. I use multiple dummy units because each element has different width and height. You know we can't modify unit's x/y/z scale factor freely using trigger.

    @Flux:
    Your idea is good for FSI systems. But the whole point our system is to make the custom interfaces stick to the screen regardless of the camera setting. Thus images can't fit here because of mentioned issue above.

    EDIT:
    I forgot to revert the MAX_LEVEL constant back to "50". I will update it ASAP.
     
    Last edited: Mar 23, 2017
  18. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    So I decided to update this earlier since there are a number of important fixes.

    v1.7:
    - Now works with any default cliff level
    - Now TextTagEx is properly scaled and repositioned according to its parent
    - Custom font height and depth are now defined
    - TextTagExChar is now public
    - TextTagEx text member is now readable
    - Deleted applyAxesTransfrom method and replaced with a boolean member
    - Improved TextTagEx dummy model so it won't get overlaid by other model with certain texture filtering mode

    More bugs and errors might be exposed soon since I'm implementing this in a more advance system.

    v1.71:
    - Now contents can't be displayed if its parent isn't visible
    - A number of bug fixes and improvements for TextEx plugin
     
    Last edited: Mar 27, 2017
  19. Quilnez

    Quilnez

    Joined:
    Oct 12, 2011
    Messages:
    3,235
    Resources:
    37
    Icons:
    2
    Tools:
    1
    Maps:
    7
    Spells:
    21
    Tutorials:
    2
    JASS:
    4
    Resources:
    37
    This update is focusing on code optimizations. The system underwent hours of highly intensive optimizations. There were too much changes so maybe I can't list all of them.

    v1.8:
    - Now panels only get refreshed if the camera is updating
    - Now camera and panels are effectively updated (only once per tick)
    - Tons of micro optimizations on camera system
    - The camera system is now properly initialized
    - Now the camera system's global variables are public
    - Fixed op limit error possibility on empty list enumerations
    - Fonts initializations are now separated on different trigger
    - Added new panel event for optimal content updating
    - A lot of optimizations on the core system and all plugins, along with updated APIs
    - Improved all structs members encapsulation
    - Up to date documentations
    - And many more...

    I have benchmarked the improvements using cheat engine's speed hack on my UI pack system. Before the update, the FPS dropped to ~30s at 3x game speed. Now it stays healthy at 60 FPS at 6x game speed, FPS dropped to ~30 only when updating the camera.
    I also ran second benchmark, previously it's capable of displaying 300 platforms at once (FPS dropped to ~30). Now it stays healthy at 60 FPS with 600+ platforms (FPS dropped to ~40 when updating the camera).

    I'm very confident the system is at it's prime condition now and ready for public use. Even tho the documentations on those examples are still lacking, I will work on it later. Enjoy...

    EDIT:
    v1.81:
    - Changed camera refreshing behavior
    - Fixed inaccurate camera yaw & pitch rotation error
    - Fixed double termination bug possibility on panel destroy event
    - Some optimizations on core system

    In the next update, I will probably re-structure the parenting system, making the coordinate calculation a bit more efficient and allows nested parenting (panels inside panel) so creating UI can't be any more comfortable than this.

    EDIT:
    v1.8b (new version formatting [1.82 > 1.8b]):
    - The core system is now much better organized
    - Coordinate conversions are now separated in its own method
    - Now calculating panel coordinates equally fast as calculating components'
    - Fixed some mistakes in previous update
     
    Last edited: Apr 4, 2017