Ticket #2162: 2162 - Rebased.patch
File 2162 - Rebased.patch, 17.5 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/gui/session/selection.js
107 107 return this.groups[templateName]; 108 108 }; 109 109 110 /** 111 * @return true if the group has at least one member 112 */ 113 EntityGroups.prototype.hasMembers = function() 114 { 115 return Object.keys(this.groups).length != 0; 116 }; 117 110 118 EntityGroups.prototype.getTotalCount = function() 111 119 { 112 120 var totalCount = 0; … … 463 471 function EntityGroupsContainer() 464 472 { 465 473 this.groups = []; 474 this.info = []; 475 // Inits groups from 0 to 9 466 476 for (var i = 0; i < 10; ++i) 477 { 467 478 this.groups[i] = new EntityGroups(); 479 var data = {}; // hitpoints, maxGroupHitPoints, numberOfUnits, initialNumberOfUnits, deathCycle, dirty, attack 480 this.info[i] = data; 481 } 468 482 } 469 483 470 EntityGroupsContainer.prototype.addEntities = function(groupName, ents) 484 /** 485 * Adds entities to the group 486 * @param groupID: id of the group 487 * @param ents: array of entity IDs 488 */ 489 EntityGroupsContainer.prototype.addEntities = function(groupID, ents) 471 490 { 472 491 for each (var ent in ents) 473 for each (var group in this.groups) 492 for (let gID in this.groups) 493 { 494 let group = this.groups[gID]; 474 495 if (ent in group.ents) 496 { 475 497 group.removeEnt(ent); 476 477 this.groups[groupName].add(ents); 498 // Fade and icon should not be triggered if a unit comes to another group. 499 this.removeEnt(gID, ent); 500 break; 501 } 502 } 503 // Add entities to group 504 this.groups[groupID].add(ents); 505 this.updateAdditionalData(groupID, ents, true); 478 506 }; 479 507 508 /** 509 * Removes a entity from the info data 510 * @param groupID: id of the group 511 * @param ents: array of entity IDs 512 */ 513 EntityGroupsContainer.prototype.removeEnt = function(groupID, ent) 514 { 515 if (!this.hasMembers(groupID)) 516 return; 517 var entState = GetEntityState(+ent); 518 if (!entState) 519 return; 520 521 // update the data like this unit would never be in this group 522 var data = this.info[groupID]; 523 data.hitpoints -= entState.hitpoints; 524 data.maxGroupHitPoints -= entState.maxHitpoints; 525 data.numberOfUnits--; 526 data.initialNumberOfUnits--; 527 data.dirty = true; 528 } 529 530 /** 531 * Updates the additional info of a group; can be called for init or update but should only be called, if needed. 532 * @param groupID: id of the group 533 * @param ents: array of entity IDs 534 * @param init: true, if init 535 */ 536 EntityGroupsContainer.prototype.updateAdditionalData = function(groupID, ents, init) 537 { 538 if (!this.hasMembers(groupID)) 539 return; 540 541 if (init) 542 { 543 let data = {}; 544 data.dirty = true; // True, if GUI should be updated 545 data.attack = false; // True, if GUI should start color attack animation 546 data.hitpoints = 0; 547 data.maxGroupHitPoints = 0; 548 data.numberOfUnits = ents.length; 549 data.initialNumberOfUnits = data.numberOfUnits; 550 data.deathCycle = 0; // Used for death icon 551 552 // Update the additional info 553 if (data.numberOfUnits > 0) 554 this.info[groupID] = data; 555 else 556 this.info[groupID] = {}; 557 } 558 559 // update the values needed for the GUI 560 this.updateHealth(groupID); 561 this.updateMaxHealth(groupID); 562 this.updateMembers(groupID); 563 } 564 565 /** 566 * updates the current health points of a group 567 * @param groupID: id of the group 568 */ 569 EntityGroupsContainer.prototype.updateHealth = function(groupID) 570 { 571 if (!this.hasMembers(groupID)) 572 return; 573 574 var data = this.info[groupID]; 575 var hitpoints = 0; 576 // Calculate health 577 for (let ent in this.groups[groupID].ents) 578 { 579 let entState = GetEntityState(+ent); 580 hitpoints += entState.hitpoints; 581 } 582 583 // check, if attack is running. 584 if (hitpoints < data.hitpoints) 585 data.attack = true; 586 // update prev points 587 if (hitpoints != data.hitpoints) 588 { 589 data.hitpoints = hitpoints; 590 data.dirty = true; 591 } 592 } 593 594 /** 595 * Updates the member count of the group 596 * @param groupID: id of the group 597 */ 598 EntityGroupsContainer.prototype.updateMembers = function(groupID) 599 { 600 if (!this.hasMembers(groupID)) 601 return; 602 603 var data = this.info[groupID]; 604 var numberOfUnits = this.groups[groupID].getTotalCount(); 605 if (numberOfUnits < data.numberOfUnits) 606 { 607 // Update unit count 608 data.numberOfUnits = numberOfUnits; 609 data.deathCycle = 1; // Show death symbol 610 // Update max health of the group 611 this.updateMaxHealth(groupID); 612 data.dirty = true; 613 } 614 } 615 616 /** 617 * Updates the max health a group can have 618 * @param groupID: id of the group 619 */ 620 EntityGroupsContainer.prototype.updateMaxHealth = function(groupID) 621 { 622 if (!this.hasMembers(groupID)) 623 return; 624 625 var data = this.info[groupID]; 626 data.maxGroupHitPoints = 0; 627 for (let ent in this.groups[groupID].ents) 628 { 629 let entState = GetEntityState(+ent); 630 data.maxGroupHitPoints += entState.maxHitpoints; 631 } 632 } 633 634 /** 635 * Updates the death cycle icon 636 * @param groupID: id of the group 637 */ 638 EntityGroupsContainer.prototype.updateDeathCycle = function(groupID) 639 { 640 if (!this.hasMembers(groupID)) 641 return; 642 643 var data = this.info[groupID]; 644 if (data.deathCycle > 0) 645 data.deathCycle++; 646 if (data.deathCycle >= g_groupDeathShowIconTicks) 647 data.dirty = true; 648 } 649 480 650 EntityGroupsContainer.prototype.update = function() 481 651 { 482 652 this.checkRenamedEntities(); 483 for each (var groupin this.groups)653 for (let groupID in this.groups) 484 654 { 655 // Nothing to do, if no members are there 656 if (!this.hasMembers(groupID)) 657 continue; 658 659 let group = this.groups[groupID]; 485 660 for (var ent in group.ents) 486 661 { 487 662 var entState = GetEntityState(+ent); … … 489 664 if (!entState) 490 665 group.removeEnt(ent); 491 666 } 667 // update the values needed for the GUI 668 this.updateHealth(groupID); 669 this.updateMembers(groupID); 670 this.updateDeathCycle(groupID); 492 671 } 493 672 }; 494 673 … … 505 684 for each (var renamedEntity in renamedEntities) 506 685 renamedLookup[renamedEntity.entity] = renamedEntity.newentity; 507 686 508 for each (var groupin this.groups)687 for (let groupID in this.groups) 509 688 { 689 let group = this.groups[groupID]; 510 690 for each (var renamedEntity in renamedEntities) 511 691 { 512 692 // Reconstruct the group if at least one entity has been renamed. … … 513 693 if (renamedEntity.entity in group.ents) 514 694 { 515 695 group.rebuildGroup(renamedLookup); 696 this.updateAdditionalData(groupID, Object.keys(group.ents), false); 516 697 break; 517 698 } 518 699 } … … 520 701 } 521 702 }; 522 703 704 /** 705 * Resets the initialNumberOfUnits 706 * @param groupID: id of the group 707 */ 708 EntityGroupsContainer.prototype.resetMemberStatus = function(groupID) 709 { 710 if (!this.hasMembers(groupID)) 711 return; 712 713 var data = this.info[groupID]; 714 data.initialNumberOfUnits = data.numberOfUnits; 715 data.dirty = true; 716 } 717 718 /** 719 * Checks if a group with that ID has members 720 * @param groupID: id of the group 721 */ 722 EntityGroupsContainer.prototype.hasMembers = function(groupID) 723 { 724 return this.groups[groupID].hasMembers(); 725 } 726 727 /** 728 * Gets the dirty state for the GUI 729 * @param groupID: id of the group 730 */ 731 EntityGroupsContainer.prototype.isDirty = function(groupID) 732 { 733 return this.hasMembers(groupID) && this.info[groupID].dirty; 734 } 735 736 /** 737 * Sets the dirty state to false after the GUI redrawed the stuff 738 * @param groupID: id of the group 739 */ 740 EntityGroupsContainer.prototype.resetDirty = function(groupID) 741 { 742 if (!this.hasMembers(groupID)) 743 return; 744 745 this.info[groupID].dirty = false; 746 } 747 748 /** 749 * Gets the attack state for the GUI 750 * @param groupID: id of the group 751 */ 752 EntityGroupsContainer.prototype.isAttacked = function(groupID) 753 { 754 return this.hasMembers(groupID) && this.info[groupID].attack; 755 } 756 757 /** 758 * Sets the attack state to false after the color fade was started 759 * @param groupID: id of the group 760 */ 761 EntityGroupsContainer.prototype.resetAttack = function(groupID) 762 { 763 if (!this.hasMembers(groupID)) 764 return; 765 766 this.info[groupID].attack = false; 767 } 768 769 /** 770 * Sets the death cycle back to zero (off) 771 * @param groupID: id of the group 772 */ 773 EntityGroupsContainer.prototype.resetDeathCycle = function(groupID) 774 { 775 if (!this.hasMembers(groupID)) 776 return; 777 778 this.info[groupID].deathCycle = 0; 779 } 780 523 781 var g_Groups = new EntityGroupsContainer(); -
binaries/data/mods/public/gui/session/session.js
61 61 // always through the list of all ongoing attacks... 62 62 var g_previousHeroHitPoints = undefined; 63 63 64 // Simulation ticks until the deathIcon of a group is removed. 65 var g_groupDeathShowIconTicks = 60; 66 64 67 function GetSimState() 65 68 { 66 69 if (!g_SimState) … … 183 186 gameSpeed.selected = gameSpeedIdx != -1 ? gameSpeedIdx : g_GameSpeeds.Default; 184 187 gameSpeed.onSelectionChange = function() { changeGameSpeed(+this.list_data[this.selected]); }; 185 188 initMenuPosition(); // set initial position 189 initLayoutGroupButtons(); // Init group buttons 186 190 187 191 // Populate player selection dropdown 188 192 var playerNames = []; … … 227 231 //setTimeout(function() { reportPerformance(60); }, 60000); 228 232 } 229 233 234 /** Inits the layout of the group buttons (adds spacers, labels and events to buttons) 235 */ 236 function initLayoutGroupButtons() 237 { 238 var guiName = "Group"; 239 for (let i = 0; i < 10; ++i) 240 { 241 // add label 242 let label = Engine.GetGUIObjectByName("unit"+guiName+"Label["+i+"]").caption = i; 243 244 // add button events and hide it 245 let button = Engine.GetGUIObjectByName("unit"+guiName+"Button["+i+"]"); 246 button.onpress = (function(i) { return function() { performGroup((Engine.HotkeyIsPressed("selection.add") ? "add" : "select"), i); } })(i); 247 button.ondoublepress = (function(i) { return function() { performGroup("snap", i); } })(i); 248 button.onpressright = (function(i) { return function() { performGroup("breakUp", i); } })(i); 249 button.hidden = true; 250 setPanelObjectPosition(button, i, 1); 251 // get the members status bar and add a event 252 let memberButton = Engine.GetGUIObjectByName("unit"+guiName+"MembersButton["+i+"]"); 253 memberButton.onpress = (function(i) { return function() { g_Groups.resetMemberStatus(i); } })(i); 254 } 255 } 256 230 257 function selectViewPlayer(playerID) 231 258 { 232 259 Engine.SetPlayerID(playerID); … … 373 400 var data = {}; 374 401 data.playerAssignments = g_PlayerAssignments; 375 402 data.groups = g_Groups.groups; 403 data.additionalGroupInfo = g_Groups.info; 376 404 // TODO: any other gui state? 377 405 return data; 378 406 } … … 392 420 { 393 421 g_Groups.groups[groupNumber].groups = data.groups[groupNumber].groups; 394 422 g_Groups.groups[groupNumber].ents = data.groups[groupNumber].ents; 423 g_Groups.info[groupNumber] = data.additionalGroupInfo[groupNumber]; 424 g_Groups.info[groupNumber].dirty = true; 395 425 } 396 426 updateGroups(); 397 427 } … … 580 610 */ 581 611 function updateGUIStatusBar(nameOfBar, points, maxPoints, direction) 582 612 { 613 // Check if values are valid 614 if (!(points && maxPoints)) 615 return; 616 583 617 // check, if optional direction parameter is valid. 584 618 if (!direction || !(direction >= 0 && direction < 4)) 585 619 direction = 0; … … 593 627 var value = 100*Math.max(0, Math.min(1, points / maxPoints)); 594 628 595 629 // inverse bar 596 if (direction == 2 || direction == 3)630 if (direction == 2 || direction == 3) 597 631 value = 100 - value; 598 632 599 if (direction == 0)633 if (direction == 0) 600 634 healthSize.rright = value; 601 else if (direction == 1)635 else if (direction == 1) 602 636 healthSize.rbottom = value; 603 else if (direction == 2)637 else if (direction == 2) 604 638 healthSize.rleft = value; 605 else if (direction == 3)639 else if (direction == 3) 606 640 healthSize.rtop = value; 607 641 608 642 // update bar … … 609 643 statusBar.size = healthSize; 610 644 } 611 645 646 /** 647 * Changes the visibility of a status bar 648 * @param nameOfBar: name of the bar 649 * @param hide: true, if bar should be hidden 650 */ 651 function changeVisibilityStatusBar(nameOfBar, hide) 652 { 653 // Get the bar and update it 654 var statusBar = Engine.GetGUIObjectByName(nameOfBar); 655 if (!statusBar) 656 return; 612 657 658 statusBar.hidden = hide; 659 } 660 613 661 function updateHero() 614 662 { 615 663 var playerState = GetSimState().players[Engine.GetPlayerID()]; … … 665 713 g_previousHeroHitPoints = heroState.hitpoints; 666 714 } 667 715 668 716 /** Update groups on the GUI. 717 */ 669 718 function updateGroups() 670 719 { 671 720 var guiName = "Group"; 672 721 g_Groups.update(); 673 for ( var i = 0; i < 10; i++)722 for (let i = 0; i < 10; ++i) 674 723 { 675 var button = Engine.GetGUIObjectByName("unit"+guiName+"Button["+i+"]"); 676 var label = Engine.GetGUIObjectByName("unit"+guiName+"Label["+i+"]").caption = i; 677 if (g_Groups.groups[i].getTotalCount() == 0) 724 let button = Engine.GetGUIObjectByName("unit"+guiName+"Button["+i+"]"); 725 // check, if group has members 726 if (!g_Groups.hasMembers(i)) 727 { 678 728 button.hidden = true; 729 stopColorFade("unitGroupHitOverlay["+i+"]"); 730 let deathIcon = Engine.GetGUIObjectByName("unitGroupIconDeath["+ i +"]"); 731 deathIcon.hidden = true; 732 continue; // nothing to do, if group has no members 733 } 679 734 else 680 button.hidden = false; 681 button.onpress = (function(i) { return function() { performGroup((Engine.HotkeyIsPressed("selection.add") ? "add" : "select"), i); } })(i); 682 button.ondoublepress = (function(i) { return function() { performGroup("snap", i); } })(i); 683 button.onpressright = (function(i) { return function() { performGroup("breakUp", i); } })(i); 684 setPanelObjectPosition(button, i, 1); 735 button.hidden = false; // make button visible 736 737 // check, if status bars must be redrawn 738 if (!g_Groups.isDirty(i)) 739 continue; 740 741 // update the status bars 742 let data = g_Groups.info[i]; 743 updateGUIStatusBar("unitGroupHealthBar["+ i +"]", data.hitpoints, data.maxGroupHitPoints); 744 745 if(data.initialNumberOfUnits == 1) 746 changeVisibilityStatusBar("unitGroupMembersButton["+ i +"]", true); 747 else 748 { 749 changeVisibilityStatusBar("unitGroupMembersButton["+ i +"]", false); 750 updateGUIStatusBar("unitGroupMembersBar["+ i +"]", data.numberOfUnits, data.initialNumberOfUnits, 3); 751 } 752 753 // check, if the attack should be started 754 if (g_Groups.isAttacked(i)) 755 { 756 startColorFade("unitGroupHitOverlay["+i+"]", 100, 10000, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit); 757 g_Groups.resetAttack(i); 758 } 759 760 // check, if the death symbol should be triggered 761 if (data.deathCycle > 0) 762 { 763 let deathIcon = Engine.GetGUIObjectByName("unitGroupIconDeath["+ i +"]"); 764 // show the symbol 765 if (data.deathCycle >= g_groupDeathShowIconTicks) 766 { 767 deathIcon.hidden = true; 768 g_Groups.resetDeathCycle(i); 769 } 770 else if (data.deathCycle >= 1) 771 deathIcon.hidden = false; 772 } 773 774 // reset the dirty state after the updates are complete 775 g_Groups.resetDirty(i); 685 776 } 686 777 } 687 778 -
binaries/data/mods/public/gui/session/session_objects/selection_group_icons.xml
7 7 <object name="unitGroupButton[n]" size="0 0 36 36" type="button" hidden="false" style="iconButton" tooltip_style="sessionToolTipBottomBold"> 8 8 <translatableAttribute id="tooltip">Click to select grouped units, double-click to focus the grouped units and right-click to disband the group.</translatableAttribute> 9 9 <object name="unitGroupIcon[n]" size="3 3 33 33" type="image" sprite="groupsIcon" ghost="true"/> 10 <object name="unitGroupHitOverlay[n]" hidden="true" type="image" ghost="true" size="3 3 33 33"/> 10 11 <object name="unitGroupLabel[n]" type="text" style="largeCenteredOutlinedText" ghost="true"/> 12 <object name="unitGroupIconDeath[n]" size="21 3 35 17" type="image" sprite="killIcon" hidden="true" ghost="true"/> 13 <!-- Group Health bar --> 14 <object size="2 37 34 40" name="unitGroupHealthSection[n]"> 15 <object size="0 0 100% 4" name="unitGroupHealth[n]" ghost="true" type="image"> 16 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 17 <object type="image" sprite="healthBackground" ghost="true"/> 18 <object type="image" sprite="healthForeground" ghost="true" name="unitGroupHealthBar[n]"/> 19 <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/> 20 </object> 21 </object> 22 <!-- Group Health bar --> 23 <object size="37 2 40 34" name="unitGroupMembersButton[n]" type="button" tooltip_style="sessionToolTipBottomBold" 24 tooltip="Click to reset unit counter bar."> 25 <object size="0 0 4 100%" name="unitGroupMembers[n]" ghost="true" type="image"> 26 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 27 <object type="image" sprite="groupSizeBackground" ghost="true"/> 28 <object type="image" sprite="groupSizeForeground" ghost="true" name="unitGroupMembersBar[n]"/> 29 <object type="image" sprite="statsBarShaderVertical" ghost="true"/> 30 </object> 31 </object> 11 32 </object> 12 33 </repeat> 13 34 </object> -
binaries/data/mods/public/gui/session/sprites.xml
9 9 /> 10 10 </sprite> 11 11 12 <sprite name="killIcon"> 13 <image 14 texture="session/icons/kill.png" 15 size="0 0 100% 100%" 16 /> 17 </sprite> 18 19 <sprite name="groupSizeForeground"> 20 <image backcolor="255 184 0 255"/> 21 </sprite> 22 23 <sprite name="groupSizeBackground"> 24 <image backcolor="184 184 184 255"/> 25 </sprite> 26 12 27 <!-- ================================ ================================ --> 13 28 <!-- Menu --> 14 29 <!-- ================================ ================================ -->