Issues (229)

client/osci/res.py (2 issues)

1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
21
import bisect
22
import glob
23
import math
24
import os
25
import re
26
27
import gdata, client
28
import pygame, pygame.image
29
from osci import gdata
30
import ige.ospace.Const as Const
31
from ige.ospace import Rules
32
from ige import log
33
34
import resources
35
36
whiteShift = 80000
37
redShift = 90000
38
39
smallStarImgs = None
40
techImgs = None
41
bigStarImgs = None
42
planetImgs = None
43
planetImgCnt = None
44
buttonImgs = None
45
cmdInProgressImg = None
46
loginLogoImg = None
47
structProblemImg = None
48
structOffImg = None
49
icons = {}
50
ui_icons = {}
51
52
def initialize():
53
    # needed for progress dlg
54
    global loginLogoImg
55
    loginLogoImg = pygame.image.load(resources.get('logo-login.png')).convert_alpha()
56
57
58
def updateProgress(curr, progress_dlg):
59
    if not progress_dlg: return
60
    if curr % 30 == 0:
61
        periods = '.' * (curr / 30 % 4)
62
        progress_dlg.setProgress(_('Loading resources' + periods), curr)
63
64
65
def loadResources(progress_dlg=None):
66
    curr = 0
67
    max = len(glob.glob(resources.get('galaxy/*.png'))) \
68
        + len(glob.glob(resources.get('techs/*.png'))) \
69
        + len(glob.glob(resources.get('system/*.png'))) \
70
        + len(glob.glob(resources.get('icons/*.png'))) \
71
        + len(glob.glob(resources.get('buttons/*.png')))
72
    if progress_dlg:
73
        progress_dlg.display(_('Loading resources'), 0, max)
74
    # load star imgs
75
    global smallStarImgs
76
    smallStarImgs = {}
77
    for filename in glob.glob(resources.get('galaxy/star_*.png')):
78
        name = re.search("star_([^.]+).png", filename).group(1)
79
        smallStarImgs[name] = pygame.image.load(filename).convert_alpha()
80
        curr += 1
81
        updateProgress(curr, progress_dlg)
82
    # load tech imgs
83
    global techImgs
84
    techImgs = {}
85
    white = pygame.Surface((37, 37))
86
    white.fill((255, 255, 255))
87
    white.set_alpha(64)
88
    red = pygame.Surface((37, 37))
89
    red.fill((255, 0, 0))
90
    red.set_alpha(64)
91
    for filename in glob.glob(resources.get('techs/????.png')):
92
        name = os.path.splitext(os.path.basename(filename))[0]
93
        imgID = int(name)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable int does not seem to be defined.
Loading history...
94
        techImgs[imgID] = pygame.image.load(filename).convert_alpha()
95
        copyImg = techImgs[imgID].convert_alpha()
96
        copyImg.blit(white, (0, 0))
97
        techImgs[imgID + whiteShift] = copyImg
98
        copyImg = techImgs[imgID].convert_alpha()
99
        copyImg.blit(red, (0, 0))
100
        techImgs[imgID + redShift] = copyImg
101
        curr += 1
102
        updateProgress(curr, progress_dlg)
103
    # load big star imgs
104
    global bigStarImgs
105
    bigStarImgs = {}
106
    for filename in glob.glob(resources.get('system/star_*.png')):
107
        name = re.search("star_([^.]+).png", filename).group(1)
108
        bigStarImgs[name] = pygame.image.load(filename).convert_alpha()
109
        curr += 1
110
        updateProgress(curr, progress_dlg)
111
    # load planet images
112
    global planetImgs
113
    global planetImgCnt
114
    planetImgs = {}
115
    planetImgCnt = {}
116
    for filename in glob.glob(resources.get('system/planet_*.png')):
117
        matchobj = re.search("planet_((.)[^.]+).png", filename)
118
        name = matchobj.group(1)
119
        pltype = matchobj.group(2)
120
        if pltype in planetImgCnt:
121
            planetImgCnt[pltype] += 1
122
        else:
123
            planetImgCnt[pltype] = 1
124
        planetImgs[name] = pygame.image.load(filename).convert_alpha()
125
        curr += 1
126
        updateProgress(curr, progress_dlg)
127
    # load ship imgs
128
    global shipImgs
129
    shipImgs = {}
130
    for filename in glob.glob(resources.get('ships/??.png')):
131
        name = os.path.splitext(os.path.basename(filename))[0]
132
        shipImgs[int(name)] = pygame.image.load(filename).convert_alpha()
133
        curr += 1
134
        updateProgress(curr, progress_dlg)
135
    # load star imgs
136
    global icons
137
    icons = {}
138
    for filename in glob.glob(resources.get('icons/[!ui_]*.png')):
139
        name = os.path.splitext(os.path.basename(filename))[0]
140
        icons[name] = pygame.image.load(filename).convert_alpha()
141
        curr += 1
142
        updateProgress(curr, progress_dlg)
143
    # load UI icons
144
    global ui_icons
145
    ui_icons = {}
146
    for filename in glob.glob(resources.get('icons/ui_*.png')):
147
        name = os.path.splitext(os.path.basename(filename))[0]
148
        ui_icons[name] = pygame.image.load(filename).convert_alpha()
149
        curr += 1
150
        updateProgress(curr, progress_dlg)
151
    # load buttons
152
    global buttonImgs
153
    buttonImgs = {}
154
    for filename in glob.glob(resources.get('buttons/*.png')):
155
        name = os.path.splitext(os.path.basename(filename))[0]
156
        buttonImgs[name] = pygame.image.load(filename).convert_alpha()
157
        curr += 1
158
        updateProgress(curr, progress_dlg)
159
    # other icons
160
    global cmdInProgressImg
161
    cmdInProgressImg = pygame.image.load(resources.get('cmdInProgress.png')).convert_alpha()
162
    global structProblemImg
163
    structProblemImg = pygame.image.load(resources.get('struct_problem.png')).convert_alpha()
164
    global structOffImg
165
    structOffImg = pygame.image.load(resources.get('struct_off.png')).convert_alpha()
166
167
168
def prepareUIIcons(color):
169
    for image in ui_icons.values():
170
        image.fill((0, 0, 0, 255), None, pygame.BLEND_RGBA_MULT)
171
        image.fill(color[0:3] + (0, ), None, pygame.BLEND_RGBA_ADD)
172
173
174
def getUIIcon(icon_name):
175
    return ui_icons["ui_" + str(icon_name)]
176
177
178
def getTechImg(techID):
179
    return techImgs.get(techID, techImgs[0])
180
181
182
def getShipImg(combatClass, isMilitary):
183
    return shipImgs.get(int(combatClass) * 10 + int(isMilitary), shipImgs[99])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable shipImgs does not seem to be defined.
Loading history...
184
185
186
def getSmallStarImg(name):
187
    return smallStarImgs[name]
188
189
190
def getBigStarImg(name):
191
    return bigStarImgs[name]
192
193
194
def getPlanetImg(pltype, plid):
195
    global planetImgCnt
196
    name = '%s%d' % (pltype, plid % planetImgCnt[pltype])
197
    return planetImgs[name]
198
199
200
def getButton(name, state):
201
    if state:
202
        name = "%s_%s" % (name, 'active')
203
    else:
204
        name = "%s_%s" % (name, 'inactive')
205
    return buttonImgs[name]
206
207
208
def getUnknownName():
209
    return _('[Unknown]')
210
211
212
def getNA():
213
    return _('N/A')
214
215
216
def getSystemOverviewProblemColor(owner, problem):
217
    if problem:
218
        return gdata.sevColors[gdata.CRI]
219
    else:
220
        return getPlayerColor(owner)
221
222
223
def getFFColorCode(relationship):
224
    if relationship == Const.REL_UNDEF:
225
        return (0xc0, 0xc0, 0xc0)
226
    if relationship == Const.REL_UNITY:
227
        return (0x00, 0xff, 0x00)
228
    relColors = [(0xff, 0x80, 0x80),
229
                 (0xff, 0x90, 0x01),
230
                 (0xff, 0xff, 0x00),
231
                 (0xb0, 0xb0, 0xff),
232
                 (0x80, 0xff, 0xff)]
233
    return relColors[bisect.bisect(Const.REL_BOUNDARIES, relationship)]
234
235
236
def getHabitabilityColorCode(value):
237
    if value < 0:
238
        return (0xff, 0x00, 0xff)
239
    colorCodes = [(255, 5 * value, 0),  # end 255, 125, 0
240
                  (255 - 2 * (value - 25), 125 + 2 * (value - 25), 0),  # end 155, 225, 0
241
                  (155 - 3 * (value - 75), 225, 0),  # end 5, 225, 0
242
                  (0, 255, 2 * (value - 125)),  # end 0, 225, 250
243
                  (0, 255, 255)]
244
    boundaries = [25, 75, 125, 200]
245
    return colorCodes[bisect.bisect(boundaries, value)]
246
247
248
def getPirateColonyColorCode(pirate):
249
    if pirate is False:
250
        return (0xc0, 0xc0, 0xc0)
251
    elif pirate == 0:
252
        return (0xff, 0x00, 0xff)
253
    else:
254
        # rest is the same as Habitability
255
        return getHabitabilityColorCode(pirate)
256
257
def getFameColorCode(fame):
258
    if fame > 0 and fame < 200:
259
        # log.debug(fame, (0xff, 255 - int(255*(fame/200)), 0x00))
260
        return (0xff, 255 - int(255 * (fame / 200.0)), 0x00)
261
    if fame == 200:
262
        return (0xff, 0x00, 0xff)  # pirate colony
263
    return (0xc0, 0xc0, 0xc0)
264
265
266
def getMineralColorCode(minerals):
267
    if minerals >= 0:
268
        # use min, since it we occasionally get 201+ mineral levels,
269
        # but it is so rare that we can ignore it for colors.
270
        return (0xff, max(0, min(255, 255 - int(255 * (minerals / 200.0)))), 0x0)
271
    return (0xc0, 0xc0, 0xc0)
272
273
274
def getSlotColorCode(slots):
275
    if slots > 20:
276
        # in case sometime in the future we have larger worlds available
277
        return (0x0, 0xFF, min(255, (slots - 20) * 10))
278
    if slots > 0:
279
        return (int(255 * (slots / 20.0)), 255 - int(255 * (slots / 20.0)), 0x0)
280
    return (0xc0, 0xc0, 0xc0)
281
282
283
def getSlotSystemColorCode(slots, planets):
284
    if planets > 0:
285
        slots = int(float(slots) / planets)
286
        if slots > 20:
287
            # in case sometime in the future we have larger worlds available
288
            return (0x0, 0xFF, min(255, (slots - 20) * 10))
289
        if slots > 0:
290
            return (int(255 * (slots / 20.0)), 255 - int(255 * (slots / 20.0)), 0x0)
291
        return (0xc0, 0xc0, 0xc0)
292
    else:
293
        return (0xc0, 0xc0, 0xc0)
294
295
296
def getStargateColorCode(accel):
297
    accel = accel * 100 - 100
298
    colorCodes = [(0xc0, 0xc0, 0xc0),
299
                  (0xff, 0xff, 0x00),
300
                  (0xff, 0xc0, 0x00),
301
                  (0xff, 0x60, 0x00),
302
                  (0xff, 0x00, 0x00),
303
                  (0xff, 0x00, 0x80),
304
                  (0xff, 0x00, 0xff)]
305
    boundaries = [1, 50, 150, 250, 350, 450]
306
    return colorCodes[bisect.bisect(boundaries, accel)]
307
308
309
def getDockColorCode(refuel, upgrades):
310
    # refuel is based on best dock; upgrades are based on sum of all docks
311
    # refuel range: 0...6
312
    # upgrade range: 0...100 (cap 100)
313
    if (refuel > 1 and upgrades > 0) or (refuel > 2):
314
        # refuel > 2 for other player docks since they always read upgrades of 0
315
        # this probably should be corrected for allies
316
        refuelScale = max(0, min(1, (refuel - 1) / 5.0))
317
        upgradeScale = max(0, min(1, upgrades / 50))
318
        return (0xFF, int(refuelScale * (1 - upgradeScale) * 255), int(refuelScale * (upgradeScale) * 255))
319
    if refuel > 0:
320
        refuelScale = max(0, min(1, refuel / 2.0))
321
        return (0x00, 100 + 100 * int(refuelScale), 100 + 100 * int(refuelScale))  # cyan
322
    return (0xc0, 0xc0, 0xc0)
323
324
325
def getMoraleColors(morale):
326
    if morale >= 0:
327
        return (255 - int(255 * (morale / 100.0)), int(255 * (morale / 100.0)), 0x0)
328
    return (0xc0, 0xc0, 0xc0)
329
330
331
def getPlayerColor(owner, onlyDiplo = False):
332
    if owner == Const.OID_NONE:
333
        return getFFColorCode(Const.REL_UNDEF)
334
    if not onlyDiplo:
335
        if gdata.config.defaults.highlights == 'yes':
336
            if gdata.playersHighlightColors.has_key(owner):
337
                return gdata.playersHighlightColors[owner]
338
    rel = min(Const.REL_UNDEF, client.getRelationTo(owner))
339
    return getFFColorCode(rel)
340
341
342
def getControlColor(owner, onlyDiplo = False):
343
    if owner == Const.OID_NONE:
344
        return False
345
    if not onlyDiplo:
346
        if gdata.config.defaults.highlights == 'yes':
347
            if gdata.playersHighlightColors.has_key(owner):
348
                return fadeDarkColor(gdata.playersHighlightColors[owner])
349
    rel = min(Const.REL_UNDEF, client.getRelationTo(owner))
350
    return fadeDarkColor(getFFColorCode(rel))
351
352
353
def getGateLineWidth(owner):
354
    if owner == Const.OID_NONE:
355
        return 1
356
    rel = min(Const.REL_UNDEF, client.getRelationTo(owner))
357
    if rel == 1250:
358
        return 2
359
    return 1
360
361
362
def getStarmapWidgetPlanetColor(ownerid, bio, mineral, slot,
363
                                stargate, dockfuel, dockupgrade, fame,
364
                                stratres, morale, pirate=False):
365
    colors = {}
366
    for datatype in gdata.OVERLAY_TYPES:
367
        colors[datatype] = getStarmapWidgetPlanetColorPerDatatype(datatype, ownerid, bio, mineral, slot,
368
                                                                  stargate, dockfuel, dockupgrade, fame,
369
                                                                  stratres, morale, pirate)
370
    return colors
371
372
373
def getStarmapWidgetSystemColor(ownerid, bio, mineral, slot,
374
                                num_planets, stargate, dockfuel, dockupgrade, fame,
375
                                stratres, morale, pirate=False):
376
    # systems follow the same logic of the planets
377
    colors = getStarmapWidgetPlanetColor(ownerid, bio, mineral, slot,
378
                                         stargate, dockfuel, dockupgrade, fame,
379
                                         stratres, morale, pirate)
380
    # system has only one difference, which we have to override
381
    colors[gdata.OVERLAY_SLOT] = getSlotSystemColorCode(slot, num_planets)
382
    return colors
383
384
385
def getStarmapWidgetPlanetColorPerDatatype(datatype, ownerid, bio, mineral, slot,
386
                                           stargate, dockfuel, dockupgrade, fame,
387
                                           stratres, morale, pirate):
388
    if (datatype == gdata.OVERLAY_OWNER):
389
        return getPlayerColor(ownerid)
390
    if (datatype == gdata.OVERLAY_DIPLO):
391
        return getPlayerColor(ownerid, True)
392
    if (datatype == gdata.OVERLAY_BIO):
393
        return getHabitabilityColorCode(bio)
394
    if (datatype == gdata.OVERLAY_MIN):
395
        return getMineralColorCode(mineral)
396
    if (datatype == gdata.OVERLAY_SLOT):
397
        return getSlotColorCode(slot)
398
    if (datatype == gdata.OVERLAY_STARGATE):
399
        return getStargateColorCode(stargate)
400
    if (datatype == gdata.OVERLAY_DOCK):
401
        return getDockColorCode(dockfuel, dockupgrade)
402
    if (datatype == gdata.OVERLAY_FAME):
403
        return getFameColorCode(fame)
404
    if (datatype == gdata.OVERLAY_PIRATECOLONYCOST):
405
        return getPirateColonyColorCode(pirate)
406
    if (datatype == gdata.OVERLAY_MORALE):
407
        return getMoraleColors(morale)
408
    return getPlayerColor(ownerid)  # default
409
410
411
def fadeColor(triplet):
412
    return ((triplet[0] + 0xc0) / 2, (triplet[1] + 0xc0) / 2, (triplet[2] + 0xc0) / 2)
413
414
415
def fadeDarkColor(triplet):
416
    return ((triplet[0] + 0x00 * 2) / 3, (triplet[1] + 0x00 * 2) / 3, (triplet[2] + 0x00 * 2) / 3)
417
418
419
def formatTime(time, separator=':'):
420
    time = int(math.ceil(time))
421
    sign = ''
422
    if time < 0:
423
        time = - time
424
        sign = '-'
425
    days = time / Rules.turnsPerDay
426
    hours = time % Rules.turnsPerDay
427
    return '%s%d%s%02d' % (sign, days, separator, hours)
428
429
430
def formatBE(b, e):
431
    return '%d / %d' % (b, e)
432
433
434
def globalQueueName(index):
435
    return ['Default', 'Red', 'Blue', 'Yellow', 'Violet'][index]
436