Пример #1
0
/*---------------------------------------------------------------------*//**
	メニューの位置調整
**//*---------------------------------------------------------------------*/
void FocusMenu::adjustMenuPos(MenuKind mkind)
{
	// フォローなしの場合は必要なし
	if(_unitFllowRef[mkind] == 0)			{	return;	}

	do
	{
		MenuTreeNode* mtnode = _menu[mkind]->getCurrentMenuNode();
		if(mtnode == 0L)						{	break;	}
		MenuWindow* mwnd = (MenuWindow*)mtnode->getPanel();
		if(mwnd == 0L)							{	break;	}
		const RectF32* rectMwnd = mwnd->getRectangle();

		// 対象がいなくなった
		if(!_unitFllowRef[mkind]->isEnable())
		{
			break;	// メニューを閉じる
		}

		// スクリーン座標に変換
		Vector2F vScr;
		CalcUtils::calc3dPosToScreenPos(&vScr, _unitFllowRef[mkind]->getCenterPos());
		f32 x = vScr.x();
		f32 y = vScr.y();

		// ユニット自体が画面外に出たときはメニューを閉じる
		if((x < 0) || (x > Game::getGame()->getLogicalWidth()) || (y < 0) || (y > Game::getGame()->getLogicalHeight()))
		{
			break;	// メニューを閉じる
		}

		// 画面内に収めるように位置修正
		if((x + rectMwnd->w()) > Game::getGame()->getLogicalWidth())	{	x = Game::getGame()->getLogicalWidth() - rectMwnd->w();	}
		else if(x < 0)					{	x = 0;						}
		if((y + rectMwnd->h()) > Game::getGame()->getLogicalHeight())	{	y = Game::getGame()->getLogicalHeight() - rectMwnd->h();	}
		else if(y < 0)					{	y = 0;						}

		// 修正を反映
		if((x != rectMwnd->x()) || (y != rectMwnd->y()))
		{
			PointF32 pt(x, y);
			mwnd->move(&pt);
		}

		return;	// 正常終了
	}
	while(false);

	// なんらかエラーが発生したのでメニューを閉じる
	_menu[mkind]->closeMenu();
}
Пример #2
0
/*---------------------------------------------------------------------*//**
	フレーム制御
**//*---------------------------------------------------------------------*/
void MoveCursor::exec(ExecRes* res, const ExecCtx* ec)
{
	if(TFW_IS_FLAG(_edchFlags, EDCH_EXT_MASK))	{	return;	}	// 外部からの無効化

	// 歩行処理
	GameExecCtx* gec = (GameExecCtx*)ec;
	TouchPanel* ui = gec->getTouchPanel(); 

	bool isEnableSelf = (!gec->isOpenedLockGui()) && (!gec->isLockOperating());
	TFW_SET_FLAG(_edchFlags, EDCH_SELF, !isEnableSelf);
	if(isEnableSelf && !ui->isReacted())
	{
		// 差分を求める
		Vector2F vDiff;
		do
		{
			// 最初にクリックしたとこからの差分で移動
			bool isTouched = _isTouching;
			_isTouching = (ui->getTouchingNum() == 1);
			// タッチ時のポイントを得る
			if(!isTouched && _isTouching)		// タッチした
			{
				ui->getTouchPosition(_ptTouchStart);	// 開始のタッチ位置を得る
				ui->setDragOperating(true);
				_ext->onTapStart(_ptTouchStart);
			}
			else if(isTouched && !_isTouching)	// 離した
			{
				// UI 反応済みフラグを立てるかどうかの判定
				Vector2F vDiff( (f32)(_ptTouchLast->x() - _ptTouchStart->x()), (f32)(_ptTouchLast->y() - _ptTouchStart->y()) );
				f32 lenDiffSq = vDiff.lengthSq();
				if(lenDiffSq >= LEN_MIN_SQ)	// 最小長さを超えている
				{
					ui->setReacted(true);	// 反応済みフラグを立てる
				}

				_ptTouchStart->set(F32_PMAX, F32_PMAX);
				_ptTouchLast->set(F32_PMAX, F32_PMAX);
				_xDiff = 0;
				_yDiff = 0;
				_ext->onTapEnd();
				break;	// 差分計算から抜ける
			}
			if(_isTouching)
			{
				ui->getTouchPosition(_ptTouchLast);		// 現在のタッチ位置を得る
			}

			// 差分を計算する
			vDiff.set( (f32)(_ptTouchLast->x() - _ptTouchStart->x()), (f32)(_ptTouchLast->y() - _ptTouchStart->y()) );
			f32 lenDiffPw = vDiff.lengthSq();
			if(lenDiffPw > LEN_MAX_SQ)	// 最大長さを超えている
			{
				// 最大長さに収める
				vDiff.normalize();
				vDiff *= LEN_MAX;
				// タッチ位置の補正
				_ptTouchLast->x() = _ptTouchStart->x() + (s32)vDiff.x(); 
				_ptTouchLast->y() = _ptTouchStart->y() + (s32)vDiff.y(); 
				ui->setReacted(true);	// 反応済みフラグを立てる
			}
			else if(lenDiffPw < LEN_MIN_SQ)	// 最小長さ未満
			{
				vDiff.set(0.0f, 0.0f);
				_xDiff = 0;
				_yDiff = 0;
				break;	// 差分計算から抜ける
			}
			else
			{
				ui->setReacted(true);	// 反応済みフラグを立てる
			}
			_xDiff = (s32)vDiff.x();
			_yDiff = (s32)vDiff.y();
		}
		while(false);

		// 描画用に角度を得ておく
		Calc::calcAngle(&_angle, vDiff.x(), vDiff.y());
	}
	else if(_isTouching)
	{
		_xDiff = 0;
		_yDiff = 0;
		_isTouching = false;
		_ext->onTapEnd();
	}

	// 2点間の距離を求める
	f32 lenPw = (f32)((_xDiff * _xDiff) + (_yDiff * _yDiff));
	_length = ::sqrtf(lenPw);
	_rateLength = _length / LEN_MAX;

	// 状態を更新する
	if(_length < LEN_WALK)
	{
		_state = STATE_STOP;
	}
	else if(_length < LEN_RUN)
	{
		_state = STATE_WALK;
	}
	else
	{
		_state = STATE_RUN;
	}
}
/*---------------------------------------------------------------------*//**
	描画
**//*---------------------------------------------------------------------*/
void FocusCursor::draw(const RenderCtx* rc)
{
	if(!_isEnableOut || !_isEnableSelf)	{	return;	}	// 無効化中
	
	GameRenderCtx* grc = (GameRenderCtx*)rc;
	Renderer* rdr = rc->getRenderer();
	RectF32 uv;

	// テクスチャ設定
	rdr->bindTexture(_texRef);
	// 加算アルファ合成
	rdr->setAlphaBlendFunc(Renderer::AFUNC_ADD);
	// 2D 解像描画比
	f32 rate2dr = Env_get2drRate();
	// 頂点カラーを基本色に
	rdr->setSolidColor(255, 255, 255, 255);

	// クリック対象を描画
	{
		Tfw* tfw = Game::getGame()->getTfw();						ASSERT(tfw != 0L);
		View* view = tfw->getView();								ASSERT(view != 0L);
		SorSgm* sgm = (SorSgm*)tfw->getSgManager();					ASSERT(sgm != 0L);
		Camera* cam = sgm->getVisibleCamera();
		if(cam != 0L)
		{
			UnitManager* unitmng = Game::getGame()->getUnitManager();	ASSERT(unitmng != 0L);
			for(int i = 0; i < unitmng->getUnitNum(); i++)
			{
				const Unit* unit = unitmng->getUnitFromIndex(i); ASSERT(unit != 0L);
				if(!unit->isEnable())				{	continue;	}	// 無効なユニットは除外
				if(!unit->isEnableFocus())			{	continue;	}	// フォーカスされないユニットは除外
				if(unit->isHidden())				{	continue;	}	// 隠し属性ユニットは除外
				if(unit->isHiddenClick())			{	continue;	}	// クリック選択不可
				if(unit->getUnitType() == UNITTYPE_EQUIPMENT_ITEM)	{	continue;	}	// 所持品は除外
				if(unit->getCenterPos()->z() >= cam->getLoc()->z())	{	continue;	}	// カメラより手前は除外

				// 既にフォーカスがあるユニットは不要
				bool isHadFocus = false;
				for(s32 j = 0; j < NUM_FOCUS_MAX; j++)
				{
					if(_focusarr->getUnit(j) == unit)
					{
						isHadFocus = true;
						break;
					}
				}
				if(isHadFocus)						{	continue;	}

				// スクリーン座標に変換
				Vector2F vScr;
				Gcalc::conv3dPosToScreenPos(&vScr, unit->getCenterPos(), cam, view);

				// 画面外チェック
				if(	((vScr.x() + W_FOCUS_CIRC) < 0) ||
					((vScr.x() - W_FOCUS_CIRC) >= Game::getGame()->getLogicalWidth()) ||
					((vScr.y() + H_FOCUS_CIRC) < 0) ||
					((vScr.y() - H_FOCUS_CIRC) >= Game::getGame()->getLogicalHeight()) )
				{
					continue;
				}

				// 描画
				::glPushMatrix();	// 行列を保存
				::glTranslatef(vScr.x(), vScr.y(), 0.0f);
				drawQuestIcon(rdr, unit, rate2dr);	// クエストアイコン表示
				::glRotatef(_dangFocusable, 0.0f, 0.0f, 1.0f);
				// フォーカス可能アイコン表示
				RectF32 vtx(- W_FOCUS_CIRC / 2, - H_FOCUS_CIRC / 2, W_FOCUS_CIRC, H_FOCUS_CIRC);
				RendererUtils::draw2dTextureRect(rdr, &vtx, Gcalc::calcTexUv(&uv, UV_FOCUSABLE, W_TEX, H_TEX, rate2dr));
				::glPopMatrix();	// 行列を戻す
			}
		}
	}

	// フォーカスカーソル表示
	drawFocusCursor(rdr, _focusarr, 1.0f, rate2dr);

	// マジッククラスターのフォーカスを表示
	MagicSys* mgsys = Game::getGame()->getMagicSys();
	for(int i = 0; i < mgsys->getMaxClusterNum(); i++)
	{
		MagicCluster* mc = mgsys->getClusterFromIndex(i);
		if(mc == 0L)			{	continue;	}
		if(!mc->isValid())		{	continue;	}
		if(!TFW_IS_FLAG(mc->getConfFlags(), MagicCluster::CONFF_SHOW_FC))	{	continue;	}
		rdr->setSolidColor(63, 0, 255, 255);
		drawFocusCursor(rdr, mc->getFocusArray(), 0.5f, rate2dr);
	}

	// 通常アルファ合成
	rdr->setAlphaBlendFunc(Renderer::AFUNC_NORMAL);

	// フォーカスゲージ表示
	for(s32 i = 0; i < NUM_FOCUS_MAX; i++)
	{
		const Unit* unitFocused = _focusarr->getUnit(i);
		if(unitFocused == 0L)	{	continue;	}	// フォーカスがある場合のみ以下を処理する
		const Vector2F* posScr = _focusarr->getScreenPos(i);

		f32 x = posScr->x() + W_FOCUS_CIRC * 0.5f;
		f32 y = posScr->y();

		// ゲージ表示
		if(unitFocused->isCategory(Unit::UNITCAT_CHAR))
		{
			const CharUnit* cunit = (CharUnit*)unitFocused;
			const CharStat* cstat = cunit->getCharStat();
			if(cstat != 0L)
			{
				StatusDrawer::drawCharStat(rc, _texRef, cstat, x, y, StatusDrawer::W_GAUGE_DEFAULT, StatusDrawer::H_GAUGE_DEFAULT, false, false);
			}
		}
		else if(unitFocused->getUnitType() == UNITTYPE_EQUIPMENT_ITEM)
		{
			const EquipmentItemUnit* iunit = (EquipmentItemUnit*)unitFocused;
			const Item* item = iunit->getItem();
			if(item != 0L)
			{
				// 名前表示
				const VcString* name = item->getItemDef()->getName(Env_getLangId());
				if(name != 0L)
				{
					rdr->setSolidColor(255, 255, 255, 255);
					Font* fontJp = grc->getFontSet()->getFont(GameFontSet::JP);
					EasyStringDrawer::draw(fontJp, name, x, y, 8, rc);
					y += 8.0f;
				}

				const EleneStat* eestat = item->getEleneStat();
				if(eestat != 0L)
				{
					StatusDrawer::drawEleneStat(rc, _texRef, eestat, x, y, 60.0f, StatusDrawer::H_ENEGAUGE_DEFAULT, false);
				}
			}
		}
		else if(unitFocused->getUnitType() == UNITTYPE_PUT_ITEM)
		{
			const PutItemUnit* diunit = (PutItemUnit*)unitFocused;
			const ItemDef* itmdf = diunit->getItemDef();
			if(itmdf != 0L)
			{
				// 名前表示
				const VcString* name = itmdf->getName(Env_getLangId());
				if(name != 0L)
				{
					rdr->setSolidColor(255, 255, 255, 255);
					Font* fontJp = grc->getFontSet()->getFont(GameFontSet::JP);
					EasyStringDrawer::draw(fontJp, name, x, y, 8, rc);
					y += 8.0f;
				}
			}
			const EleneStat* eestat = diunit->getEleneStat();
			if(eestat != 0L)
			{
				StatusDrawer::drawEleneStat(rc, _texRef, eestat, x, y, 60.0f, StatusDrawer::H_ENEGAUGE_DEFAULT, false);
			}
		}
	}
}
/*---------------------------------------------------------------------*//**
	フレーム制御
**//*---------------------------------------------------------------------*/
void FocusCursor::exec(ExecRes* res, const ExecCtx* ec)
{
	if(!_isEnableOut)	{	return;	}	// 外部からの無効化

	GameExecCtx* gec = (GameExecCtx*)ec;
	TouchPanel* ui = gec->getTouchPanel(); 

	// フォーカスの有効性更新
	_focusarr->updateValidity();
	// フォーカスの座標値をリセット
	for(s32 i = 0; i < NUM_FOCUS_MAX; i++)
	{
		_focusarr->invalidateScreenPos(i);
	}

	// 有効性判定
	_isEnableSelf = !gec->isLockOperating();
	bool isEnableUiReact = _isEnableSelf && !gec->isOpenedLockGui() && !ui->isReacted() && (_fcntPreventTap == 0.0f);

	// タッチ操作による処理
	if(isEnableUiReact) 
	{
		PointF32 ptTouch, ptStart;
		bool isTap = false;
		bool isDblTapRel = false;
		if(!ui->isReacted())
		{
			const f32 DIFF_TAP_RANGE = 20.0f;
			if(ui->isTapRelease(&ptTouch, &ptStart)) { isTap = ptTouch.isNear(&ptStart, DIFF_TAP_RANGE, DIFF_TAP_RANGE); }	// 面積が狭いので、isClickRelease だとストレスに感じる
			if(ui->isDoubleClickRelease(&ptTouch)) { isDblTapRel = true; }
		}
		if(isTap || isDblTapRel)
		{
			Tfw* tfw = Game::getGame()->getTfw();						ASSERT(tfw != 0L);
			View* view = tfw->getView();								ASSERT(view != 0L);
			SorSgm* sgm = (SorSgm*)tfw->getSgManager();					ASSERT(sgm != 0L);
			Camera* cam = sgm->getVisibleCamera();						ASSERT(cam != 0L);

			UnitManager* unitmng = Game::getGame()->getUnitManager();	ASSERT(unitmng != 0L);
			for(int i = 0; i < unitmng->getUnitNum(); i++)
			{
				Unit* unit = unitmng->getUnitFromIndex(i);				ASSERT(unit != 0L);
				if(!unit->isEnable())		{	continue;	}	// 無効なユニットは除外
				if(!unit->isEnableFocus())	{	continue;	}	// フォーカスされないユニットは除外
				if(unit->isHidden())		{	continue;	}	// 隠し属性ユニットは除外
				if(unit->getUnitType() == UNITTYPE_EQUIPMENT_ITEM)	{	continue;	}	// 所持品は除外
				if(unit->getCenterPos()->z() >= cam->getLoc()->z())	{	continue;	}	// カメラより手前は除外

				// スクリーン座標に変換
				Vector2F vScr;
				Gcalc::conv3dPosToScreenPos(&vScr, unit->getCenterPos(), cam, view);

				if(isDblTapRel)	// ダブルクリック時は直接フォーカスをセットする
				{
					// 一度フォーカスをリセット
					for(int j = 0; j < NUM_FOCUS_MAX; j++)
					{
						setFocus(j, 0L, 0L);
					}
					// 範囲内かどうか判定して、範囲内だったらフォーカス設定する
					if(TFW_IS_NEAR(vScr.x(), ptTouch.x(), RANGE_TOTRG) && TFW_IS_NEAR(vScr.y(), ptTouch.y(), RANGE_TOTRG))
					{
						// フォーカスをセット(上部でリセットしているので、[0] 決めうち)
						setFocus(0, unit, &vScr);
						// UI に反応済みフラグを立てる
						ui->setReacted(true);
						break;
					}
				}
				else if(isTap)	// タップ時はメニューを表示
				{
					// 範囲内かどうか判定して、範囲内だったらメニューを表示する
					TRACELN("{FocusCursor::exec} unit touch?; scr_x=%f, scr_y=%f, click_x=%d, click_y=%d", vScr.x(), vScr.y(), ptTouch.x(), ptTouch.y());
					if(TFW_IS_NEAR(vScr.x(), ptTouch.x(), RANGE_TOTRG) && TFW_IS_NEAR(vScr.y(), ptTouch.y(), RANGE_TOTRG))
					{
						showFocusMenu(unit, &vScr);		// フォーカスメニュー表示
						ui->setReacted(true);	// UI に反応済みフラグを立てる
					}
				}
			}
		}
	}

	// フォーカスカーソルの画面位置を計算
	for(s32 i = 0; i < NUM_FOCUS_MAX; i++)
	{
		// 無効になったユニットは外す
		const Unit* unitFocused = _focusarr->getUnit(i);
		if(unitFocused == 0L)	{	continue;	}
		if(!unitFocused->isEnable())
		{
			setFocus(i, 0L, 0L);
		}

		// スクリーン座標値が未計算の場合、計算する
		if(!_focusarr->isValidScreenPos(i))
		{
			_focusarr->calcScreenPos(i);
		}
	}

	// マジッククラスターのフォーカスの画面位置を計算
	MagicSys* mgsys = Game::getGame()->getMagicSys();
	for(int i = 0; i < mgsys->getMaxClusterNum(); i++)
	{
		MagicCluster* mc = mgsys->getClusterFromIndex(i);
		if(mc == 0L)		{	continue;	}
		if(!mc->isValid())	{	continue;	}
		mc->focusArray()->calcScreenPosAll();
	}

	// タップ防止カウンタの更新
	if(_fcntPreventTap > 0.0f)
	{
		_fcntPreventTap -= ec->getDeltaFrame();
		if(_fcntPreventTap < 0.0f)	{	_fcntPreventTap = 0.0f;	}
	}

	// カーソル回転角度の更新
	_dangFocus += DANG_FOCUS_DELTA;
	if(_dangFocus > 180.0f)		{	_dangFocus -= 360.0f;		}
	_dangFocusable += DANG_FOCUSABLE_DELTA;
	if(_dangFocusable > 180.0f)	{	_dangFocusable -= 360.0f;	}
}